Spring事务-使用@Transactional在事务中立即提交部分数据库操作

目录

一、背景

二、需求

三、Spring事务的传播级别及失效场景

1.Spring事务的传播级别

2.失效场景及正确用法


一、背景

在项目中使用数据库锁表实现分布式锁,在方法A中调用方法B,方法B是一个多节点同步的方法,内部使用写锁表的逻辑实现分布式锁,方法A是使用@Transactional标注的事务,默认情况下在调用方法B是会加入该事务,导致写锁表的操作会在方法A结束时被提交,是这显然不能满足实现分布式锁的初衷。

二、需求

在方法A的事务中,在执行到方法B的操作锁表逻辑时立即提交对数据库锁表的修改。

三、Spring事务的传播级别及失效场景

1.Spring事务的传播级别

Spring中使用@Transactional实现的声明式事务的事务传播级别可以参考以下两篇文章,这里不过多赘述。

【Spring Boot】事务的隔离级别与事务的传播特性详解:如何在 Spring 中使用事务?不同隔离级别的区别?_spring默认的事务传播级别详解-CSDN博客

Spring中事务的传播机制以及REQUIRED、REQUIRES_NEW、NESTED区别以及代码演示_requires和nested-CSDN博客

2.失效场景及正确用法

下面说明通过@Transactional设置事务传播级别的失效场景以及正确使用方式。

失效场景:调用本类对象的方法或不经Spring代理对象的方法。

正确用法:调用其他Service类对象的方法,即Spring容器管理的实例方法。

public class TestService2Impl implements TestService2 {

    @Autowired
    private LockTableMapper mapper;

    @Autowired
    private LogConfigurationMapper logConfigurationMapper;
    
    @Autowired
    private TestService2Inner testService2Inner;

    @Override
    @Transactional
    public String save(LockTable lockTable) {
        LogConfiguration logConfiguration = new LogConfiguration();
        logConfiguration.setId(UUID.randomUUID().toString().substring(0,32));
        //调用代理类的doLock方法,指定的事务传播级别生效。
//        String s = testService2Inner.doLock(lockTable);
        //调用本类的doLock方法时,指定的事务传播级别失效
        String s = doLock(lockTable);
        int insert = logConfigurationMapper.insert(logConfiguration);
//        int i = 1/0;
        return s;
//        return String.valueOf(insert);
    }

    
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public String doLock(LockTable lockTable){
        log.info("call acquireLock...");
        String s = acquireLock(lockTable);
//        int i = 1/0;
        return s;
    }

    private String acquireLock(LockTable lockTable){
        return String.valueOf(mapper.insert(lockTable));
    }
}

上述例子中,save方法开启了一个默认事务,在save方法中若调用本类的doLock方法,即使该方法使用@Transactional(propagation = Propagation.REQUIRES_NEW)标注了事务的传播级别也不会生效。

若调用TestService2Inner对象的doLock方法则会生效,因为TestService2Inner对象时通过Spring容器管理的对象,通过@Autowired注入的对象其实是该类的代理对象。而Spring的声明式事务控制就是通过代理对象实现的。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值