Spring编程式事务和声明式事务的应用场景的区别

在面试中,经常会遇到这个问题,面试官经常说编程式事务比声明式事务的掌控粒度更细,能够精确到代码行,而声明式事务作为注解使用只能控制整个方法。我个人认为是不太正确的。下面来看一下我的想法

1.编程式事务

    public void test() {
        int a = 1;
        try {
            // 开启事务
            int b = 10 / 0;
        } catch (Exception e) {
            System.out.println("出错了");
            // 事务回滚
        } finally {
            // 事务提交
        }
    }

大概是这样使用,可以看到a变量并不受事务的影响,所以可以实现对方法中的局部代码行进行事务的控制。

2.声明式事务

声明式事务主要用注解来实现。

@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
    public void insertUser(@RequestBody TbUser user) throws FileNotFoundException {
       int a = 1;
       int b = 2;
       
    }

大概是这样实现,表面上看起来确实是只能对整个方法进行事务管理。

注:rollbackFor默认回滚RuntimeException的所有子类,即使你想捕捉数组长度异常类再回滚,但实际上抛的ArithmeticException异常,也是会回滚的。具体可以看这位老哥的文章:@Transactional注解的rollbackFor属性 - 简书

3.反转

其实声明式事务依然可以实现对于代码行的控制。

@Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
    public void insertUser(@RequestBody TbUser user) throws FileNotFoundException {
       int a = 1;
       int b = afterA();

    }

    @Transactional(rollbackFor = {Exception.class}, propagation = Propagation.REQUIRED)
    public int afterA() {
        return 2;
    }

可以把要实现精确控制的代码写入其他方法,通过调用其他方法来实现事务的精确控制。这里会用到事务的传播行为。但这样的写法也是有问题的

4.存在的问题

第3步的代码是有很大的问题的,你会发现事务的传播行为失效了。并没有按照你想的步骤来执行。是因为如果你想通过这种方式来实现精确控制,是不能把被调用的方法和需要调用的方法写在同一个对象里,具体的原因可以看这位老哥写的,非常透彻:spring 事务Propagation.REQUIRES_NEW 不起作用的原因_hepei120的博客-CSDN博客

最后的代码实现:

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值