b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

spring aop 注解 Spring声明式事务为何不回滚

电脑杂谈  发布时间:2018-02-01 22:07:45  来源:网络整理

spring aop 注解 jdk_spring aop maven_spring aop 注解

疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚。于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致。下面总结一下经验教训。

下面先总结一下Spring的事务管理方式,spring支持两种事务管理的操作方式,编程式的和声明式的(xml或者注解)。

编程式的事务管理(实际应用中很少使用)

通过使用TransactionTemplate 手动管理事务

声明式的事务管理(开发中推荐使用(代码侵入最少))

Spring的声明式事务是通过AOP实现的

总结一下导致事务不回滚的两个原因,一是Service类内部方法调用,二是try…catch异常。

大概就是 Service 中有一个方法 A,会内部调用方法 B, 方法 A 没有事务管理,方法 B 采用了声明式事务,通过在方法上声明 Transactional 的注解来做事务管理。示例代码如下:

@Service
public class RabbitServiceImpl implements RabbitService {

    @Autowired
    private RabbitDao rabbitDao;
    @Autowired
    private TortoiseDao tortoiseDao;

    @Override
    public Rabbit methodA(String name){
        return methodB(name);
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
    public boolean methodB(String name){
        rabbitDao.insertRabbit(name);
        tortoiseDao.insertTortoise(name);
        return true;
    }

}

单元测试代码如下:

public class RabbitServiceImplTest {

    @Autowired
    private RabbitService rabbitService;

    // 事务未开启
    @Test
    public void testA(){
        rabbitService.methodA("rabbit");
    }

    // 事务开启
    @Test
    public void testB(){
        rabbitService.methodB("rabbit");
    }
}

从上一节中可以看到,声明式事务是通通过AOP动态代理实现的,这样会产生一个代理类来做事务管理,而目标类(service)本身是不能感知代理类的存在的。

对于加了@Transactional注解的方法来说,在调用代理类的方法时,会先通过TransactionInterceptor开启事务,然后在调用目标类的方法,最后在调用结束后,TransactionInterceptor 会提交或回滚事务,大致流程如下图:

spring aop 注解 jdk_spring aop maven_spring aop 注解

这里写图片描述

总结,在方法 A 中调用方法 B,实际上是通过“this”的引用,也就是直接调用了目标类的方法,而非通过 Spring 上下文获得的代理类,所以事务是不会开启的。


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-64434-1.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...