spring事务失效的问题

具体场景为:
在类A里面有方法a 和方法b, 然后方法b上面用 @Transactional加了方法级别的事务,最后在方法a里面 调用了方法b, 结果发现方法b里面的事务没有生效!!

实际上是这样的:
在同一个类之中,方法互相调用,切面无效 ,而不仅仅是事务。
这里事务之所以无效,是因为spring的事务是通过aop实现的。

代码如下:

    @Autowired
    ExcelDetailRecordDOMapper excelRecordDOMapper;
    
    
    @Test
    public void insertBatchTest() throws Exception {
        // insertBatch2的事务失效
        insertBatch2();
    }

    @Transactional
    public void insertBatch2() throws Exception {
        ExcelDetailRecordDO excelRecordDO2 = new ExcelDetailRecordDO();
        excelRecordDO2.setId(1801L);//数据库无此数据,可以插入
        excelRecordDOMapper.insert(excelRecordDO2);
        ExcelDetailRecordDO excelRecordDO1 = new ExcelDetailRecordDO();
        excelRecordDO1.setId(100L);//数据库有,因此主键冲突 ,本应连带1801一起回滚,但是实际上却没有,因为这个方法是被insertBatchTest方法调用触发的
        excelRecordDOMapper.insert(excelRecordDO1);
    }

    @Transactional //有效
    @Test
    public void insertBatch() throws Exception {
        ExcelDetailRecordDO excelRecordDO2 = new ExcelDetailRecordDO();
        excelRecordDO2.setId(1800L);//数据库无此数据,因此可以插入
        excelRecordDOMapper.insert(excelRecordDO2);
        ExcelDetailRecordDO excelRecordDO1 = new ExcelDetailRecordDO();
        excelRecordDO1.setId(100L);//数据库有,因此主键冲突,正常的将1800一起回滚了
        excelRecordDOMapper.insert(excelRecordDO1);
    }
    

原因:
spring的aop是通过动态代理实现的,也就是在原来的类的基础上,又生成了一个子类代理类,在代理类中调用了原来的类的方法,但是在调用之前,执行了写在切面上的逻辑。

比如说原来的是

方法 a(){
// …业务逻辑
}

代理之后的是
方法 proxy(){
//切面逻辑…
方法();
//切面逻辑…
}

因此,在本类的方法之间互相调用,代理类是不知道的,根本没有走代理类。

但是外部的其他类就不一样了,外部类在调用的时候,实际上是调用的原来类的代理类。

本类调用的时候如图下:
spring事务失效的问题_第1张图片

解决方法1:
去替换掉原来的
因为aspectj有事务增强特性,解决了这个问题。
解决方法2:
显式调用
spring事务失效的问题_第2张图片

事务增强
https://www.cnblogs.com/zyzcj/p/7840920.html

循环引用
https://jinnianshilongnian.iteye.com/blog/1415278

你可能感兴趣的:(spring源码学习专栏)