前段时间发现自己对 spring
默认事务理解不对,引发了一些问题。特意写了个例子进行求证。
@Transactional
是指 org.springframework.transaction.annotation.Transactional
一、错误的使用方式
- 在方法上加上
@Transactional
,不管当前方法的调用方式,内部子方法,以及修饰符 - 在主方法上加
@Transactional
,子方法上也加@Transactional
- 在私有方法上加
@Transactional
- 在非
@Autowired
注入的bean
中的方法上加@Transactional
- 将
@Autowired
注入的bean
中的方法当做子方法调用,子方法上有@Transactional
- 方法形成调用链,事务传播控制不到位
- 方法内部的事务边界划分不清晰,导致事务处理经常抛异常
二、正确的使用方式
- 主方法上加
@Transactional
会将当前方法及子方法(包括注入的或私有定义的)都控制在一个事务内 - 主方法上加
@Transactional
子方法注入 加上@Transactional(propagation= Propagation.REQUIRES_NEW)
子方法会单独开启事务
注意事项
- 在非注入的方法上使用
@Transactional
无效 ,必须是@Autowired
注入的bean
且由public
修饰,因为事务是代理执行的 - 在使用
@Transactional(propagation= Propagation.REQUIRES_NEW)
时,不需要单独配置事务管理器 - 如果
mysql
事务出现问题,记得去查看数据引擎是否是InnoDB
,因为MyISAM
引擎不支持事务;附上一个修改命令alter table table_name engine=InnoDB
三、事务使用必须要注意的事情
根据同事的提醒加上自己犯的错误,总结到了一下几点:
- 尽量控制事务在当前业务模块中,尽可能避免业务模块外的事务传播,以免链路中一个异常引发整个事务回滚
- 在方法上使用
@Transactional
之前需要确定方法内部的事务边界,是否存在多个事务边界 - 在方法中抛出异常时,需要特别清楚异常抛出代表的意味不只是终结当前业务代码不往下执行,同时也意味着当前方法的事务可能发生回滚
评论区