目录
一、什么是事务
事务是一组操作的集合,它是一个不可分割的工作单位,这些操作要么同时成功,要么同时失败。事务的操作步骤:开启事务(一组操作开始前,开启事务 start transaction/begin)、提交事务(这组操作全部成功后,提交事务 commit)、回滚事务(中间任何一个操作出现异常,回滚事务 rollback)。
事务的特性ACID:
- 原子性:事务是不可分割的最小操作单元,要么全部成功,要么全部失败
- 一致性:事务完成时,必须使所有的数据都保持一致的状态。
- 隔离性:数据库系统提供的隔离机制,保证事务在不受外部并发操作的影响的独立环境下运行
- 持久性:事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。
二、事务管理
删除部门,同时删除该部门下的所有。
注解: @Transactional
位置:业务(service)层的方法上、类上、接口上,建议加在用于增删改的方法上。
作用:将当前方法交给spring进行事务管理,方法执行前开启事务;成功执行完毕,提交事务;出现异常,回滚事务。
可以在application.yml配置文件中开启事务管理日志,这样就可以在控制看到和事务相关的日志信息了 。在YAML格式的配置文件中,缩进是非常重要的,因为它决定了层级关系。
#spring事务管理日志
logging:
level:
org.springframework.jdbc.support.JdbcTransactionManager: debug
@Transactional
@Override
public void delete(Integer id) {
deptMapper.delete(id);//根据部门id删除部门
int i=1/0;
empMapper.deleteByDeptId(id);//根据部门id删除员工
}
@Delete("delete from emp where dept_id=#{deptId}")
void deleteByDeptId(Integer deptId);
添加Spring事务管理后,由于服务端程序引发了异常,所以事务进行回滚
三、Spring事务失效的场景
情况一:异常捕获处理
原因:事务通知只有在捕捉到了目标抛出的异常,才能进行后续的回滚处理,如果目标自己处理掉了异常,事务通知无法知悉,事务失效。
解决:在catch块中添加throw new RuntimeException抛出
情况二:抛出检查异常
原因:Spring默认只会回滚非检查异常(RuntimeException)。
解决:配置rollbackFor属性@Transactianal(rollbackFor=Exception.cla),rollbackFor属性用于控制出现何种异常类型。
@Transactional(rollbackFor = Exception.class)
@Override
public void delete(Integer id) throws Exception {
deptMapper.delete(id);//根据部门id删除部门
// int i=1/0;
if (true){
throw new Exception("出错了");
}
empMapper.deleteByDeptId(id);//根据部门id删除员工
}
情况三:非public方法导致的事务失效
原因:Spring 为方法创建代理,添加事务通知,前提条件都是该方法是public的。
解决:改为public方法。
四、事务传播行为
事务的传播行为就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行事务控制。
所谓事务的传播行为,指的就是在A方法运行的时候,首先会开启一个事务,在A方法当中又调用了B方法, B方法自身也具有事务,那么B方法在运行的时候,到底是加入到A方法的事务当中来,还是B方法在运行的时候新建一个事务?这个就涉及到了事务的传播行为。我们要想控制事务的传播行为,在@Transactional注解的后面指定一个属性propagation,通过 propagation 属性来指定传播行为。
@Service
public class DeptLogServiceImpl implements DeptLogService {
@Autowired
private DeptLogMapper deptLogMapper;
@Transactional(propagation = Propagation.REQUIRES_NEW)//事务传播行为:不论是否有事务,都新建事务
@Override
public void insert(DeptLog deptLog) {
deptLogMapper.insert(deptLog);
}
}
Propagation.REQUIRES_NEW :不论是否有事务,都创建新事务 ,运行在一个独立的事务中