一、错误的try catch导致事物不能回滚
在catch中没有将异常抛出,因为事物通知只有捕捉到了目标抛出去的异常,才能进行后续的回滚处理,如果目标自己处理的异常,并没有抛出,事物通知是无法感知的。
解决方案:
方案一:异常原样抛出
方案二:手动设置TransactionStatus.setRollbackOnly()
二、aop切面顺序导致事物不能正确回滚
原因:事物切面优先级最低,但是日过自定义的切面的优先级和他一样,则还是自定义的切面在内层,这时若自定义的切面没用正确的抛出异常,事物则不能回滚
解决方案:同上一个案例一样抛出异常即可。
三、非public方法导致事物失效
原因:spring为方法创建代理,添加0事物通知,前提都是该方法时public修饰的
解决:改为public方法
四、父子容器导致事物失效
原因:子容器扫描的范围过大,把未添加事物配置的service扫描出来
解决1:各扫描各的
解决2:不要用父子容器,所有的bean都放在同一个容器里面
父子容器只有在使用springMvc的这种老项目你们才会出现,使用springboot的项目都是一个容易,不会出现父子容器事物失效的情况。
五、调用本类方法导致事物传播行为失效
原因:本类方法调用不经过代理,因此无法增加,事物就会失效
解决1:依赖注入自己的(代理)来调用,最简单的解决方案
解决2:添加开始代理对象的注解@EnableAspectJAutoProxy(exposeProxy=true),然后再代码中获取代理对象调用本类的方法
六、@Transactional没有保证原子行为(多线程并发争抢同一个资源的时候会出现问题)
原因:事物的原子性仅涵盖insert,update,delete,select… for update 语句,select方法并不阻塞
解决1:通过synchrinazed保证目标方法的原子性
业务逻辑,先查询后两次更新
解决2:使用select… for update 替换select (排他锁,在做查询的时候,如果当前线程执行修改的语句没有commit提交,则其他线程阻塞)