当前位置:网站首页>转账业务追加日志(事务的传播行为).
转账业务追加日志(事务的传播行为).
2022-07-23 14:35:00 【lwj_07】

先明白什么是事务的传播行为:

事务的传播行为:把log记录日志的方法设置成不受spring事务管理的形式,也就是说:当我们在该业务逻辑层转账方法上添加完spring注解后,该方法中如果出现了异常,那么该方法中所有的东西都会被回滚,也就是说不会修改数据库的信息 (只要操作sql语句的方法都是有事务的)
同理,log记录日志的方法因为调用的也是数据层的sql语句,因此也会被回滚,也就是说不执行,
但是我们业务中无论转账是否成功,都想让这个记录日志的方法把信息追加记录到数据库当中,因此需要把这个记录日志的事务不再受spring事务的管理,因此该行为叫做事务的传播行为
通俗易懂的说:就是spring管理的事务开启回滚的时候,记录日志log方法不受spring事务的控制影响(也就是说不回滚,就想要把转账信息记录在数据库中)
回滚:意思就是当转账方法的过程中出现某些异常情况的时候,就阻止转账/收款成功,就是当遇到异常的时候直接回滚,不让它调用数据库中的转账和收款sql语句方法了
因此我们该怎么让本来受spring事务控制的log方法,不再受spring事务控制呢:
在不想受spring控制影响的log接口方法中加入注解:@Transactional(propagation = Propagation.REQUIRES_NEW)

总体代码如下所示:

程序测试:

AccountService接口:(转账操作方法)

AccountServiceImpl实现类:(在转账方法上开启spring事务,一般都在实现该接口的方法中写注解)
重点理解这里的: logService.log(out,in,money); 为什么要用业务逻辑层接口调用,不直接用数据层调用,(原因就是在接口上用注解的形式可以不受spring事务的管理,如果直接用数据层调用的话,那么不受spring事务管理的注解就没地方放了)
package com.itheima.service.impl;
import com.itheima.dao.AccountDao;
import com.itheima.service.AccountService;
import com.itheima.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.*;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
/**
* 转账操作方法
* @param out 转账方
* @param in 收款方
* @param money 转账金额
*/
public void transfer(String out,String in ,Double money) {
try{
// 调用数据层的转账方法
accountDao.outMoney(out,money);
/**
* 假设这里模拟出现不安全操作,那么在spring事务的管理之下,如果转账操作的过程中出现不安全的操作转账/收款/记录日志这些关于sql语句事务的
* 操作都是会被spring事务给回滚的,也就是说这些方法都不执行了(但是记录日志log由于事务的传播行为
* 自己玩自己的,不受spring事务的管理了,因此无论这里安不安全,记录日志对数据库的操作都是会变的/记录的)
*/
int i = 1/0;
// 调用数据层的收款方法
accountDao.inMoney(in,money);
}finally { // finally里面的代码是一定执行的,因为想让记录转账日志无论如何都执行所
// 以方finally里面,要是不放的话,如果outMoney()或者inMoney()后出现异常
//后就停止执行代码了,放finally里面后无论是否出现异常都会执行
// 注意:这里是业务逻辑层的loginService调用的(目的:就是创建业务逻辑层
// logServiceImpl 然后可以使用注解的方式让该方法不受spring事务的管理)
logService.log(out,in,money);
}
}
}
数据层AccountDao:
package com.itheima.dao;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;
public interface AccountDao {
/**
* 收款功能
*
* @param name 收款人
* @param money 收款金额
*/
@Update("update tbl_account set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
/**
* 转账功能
* @param name 转账人
* @param money 转账金额
*/
@Update("update tbl_account set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
}LogService:(记录日志接口:写不受spring事务管理的注解,自己玩自己的,尽管spring管理的事务回滚了,该记录日志一样能执行操作信息)

LoginServiceImpl:

数据层LogDao:
package com.itheima.dao;
import org.apache.ibatis.annotations.Insert;
public interface LogDao {
@Insert("insert into tbl_log (info,createDate) values(#{info},now())")
void log(String info);
}
因此我们假设业务层开启spring事务后,假定转账过程中是不安全的 (int i =10/0 ) ,那么转账/收款对数据库的sql语句操作的方法将不再执行,也就是说被spring事务回滚了,但由于记录日志设置了不受spring事务管理了,因此无论转账过程是否异常,记录日志的sql都是会执行的:
假定数据库双方金额都是1000元:

执行测序程序test,在spring管理的情况下进行不安全的转账操作:
会发现执行后:由于转账过程中是不安全的,所以转账/收款方法被spring事务回滚了,保证了金额的安全

但是由于本来也受spring事务管理的log记录日志方法(1、为什么受spring事务管理:因为记录日志调用方法在spring注解的转账操作方法当中。 2、为什么log记录转账日志的方法可以不受spring事务管理:因为log记录日志调用的log方法本身也是传递给数据层对数据库进行操作的,所以本身也自带事务,加上注解后可以不受spring事务管理)在加入相对应的注解之后,不再受spring事务的管理,也就是说无论是否回滚,该记录日志的sql语句都是能被执行的:

边栏推荐
- Sorting - introduction, code ideas, usage suggestions, code implementation -1
- Solution for iPhone unable to open openv** file
- Kubernetes kubelet 硬核知识 架构
- Kubernetes Kubelet管理pod核心流程
- [30. N-queen problem]
- VScode——代码、文件改动无法保存
- Shell | 查看进程的方法的不完全总结
- PPPoE协议讲解以及拨号过程Wireshark抓包解析
- Function secondary development / plug-in development of JMeter (detailed version)
- Pyinstaller+installforge multi file project software packaging
猜你喜欢
随机推荐
新零售电商平台怎么做?才能实现传统零售企业数字化转型?
虚拟机网络连接方式
通用分页实现
Weisfeiler Lehman graph isomorphism test and others
动态库*.dll文件的Debug/Release版本是否可以混用(交叉用)?
常见模拟电路设计 一(含仿真):方波、三角波、正弦波的互相发生「建议收藏」
How to refine the operation of small program mall?
Explain SQL optimization in detail
JS if the decimal is 0, subtract it, not keep it
Wechat applet class binding, how to bind two variables
VSCode PIO创建工程失败分析和解决办法
Program environment and pretreatment
Wechat applet wx.hideloading() will close the toast prompt box
59.雷电安全常识
When does MySQL use table locks and row locks?
ROS2自学笔记:Rviz可视化工具
【flask高级】从源码深入理解flask路由之endpoint
详解一次SQL优化
PIP reports an error could not find a version that satisfies the... No matching distribution
Emgu CV3+C#图像处理(四):使用EmguCV获取摄像头、读取视频









