SpringBoot中@Transactional事务用法

@Transactional作用


主要用于声明式事务管理。它可以用于类或者方法级别,控制方法中的数据库操作是否要被事务管理。当 @Transactional 注解应用于某个方法时,该方法中的所有数据库操作(增、删、改等)会被绑定到一个事务中,保证这些操作在一个整体的事务上下文中执行。

@Transactional属性


propagation属性 - 事务传播范围

propagation 代表事务的传播行为,默认值为 Propagation.REQUIRED

  • Propagation.REQUIRED:如果当前存在事务,则加入该事务,如果当前不存在事务,则创建一个新的事务。( 也就是说如果A方法和B方法都添加了注解,在默认传播模式下,A方法内部调用B方法,会把两个方法的事务合并为一个事务 )
  • Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前不存在事务,则以非事务的方式继续运行。
  • Propagation.MANDATORY:如果当前存在事务,则加入该事务;如果当前不存在事务,则抛出异常。
  • Propagation.REQUIRES_NEW:重新创建一个新的事务,如果当前存在事务,暂停当前的事务。( 当类A中的 a 方法用默认Propagation.REQUIRED模式,类B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中调用 b方法操作数据库,然而 a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW会暂停 a方法的事务 )
  • Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务,暂停当前的事务。
  • Propagation.NEVER:以非事务的方式运行,如果当前存在事务,则抛出异常。
  • Propagation.NESTED :和 Propagation.REQUIRED 效果一样。

isolation 属性 - 事务隔离级别

isolation :事务的隔离级别,默认值为Isolation.DEFAULT

  • Isolation.DEFAULT:使用底层数据库默认的隔离级别。
  • Isolation.READ_UNCOMMITTED:读未提交
  • Isolation.READ_COMMITTED:读已提交
  • Isolation.REPEATABLE_READ:可重复读
  • Isolation.SERIALIZABLE:串行化

timeout 属性 - 事务超时时间

事务的超时时间,默认值为 -1。如果超过该时间限制但事务还没有完成,则自动回滚事务。

readOnly 属性

指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。

rollbackFor 属性 - 指定异常触发事务回滚

用于指定能够触发事务回滚的异常类型,可以指定多个异常类型。

noRollbackFor属性 - 指定异常不触发事务回滚

抛出指定的异常类型,不回滚事务,也可以指定多个异常类型。

示例


@RequestMapping("/test")
@RestController
public class TestController {

    @Autowired
    private TestService testService;

    @PostMapping("/doTransactionTest")
    public String doTransactionTest(@RequestBody RolePO rolePO) {
        return testService.doTransactionTest(rolePO);
    }
}

@Service
public class TestService {

    @Resource
    private RolePOMapper rolePOMapper;

    @Transactional(rollbackFor=RuntimeException.class)
    public String doTransactionTest(RolePO rolePO) {
        rolePO.setId(UUID.randomUUID().toString().replace("-", ""));
        rolePO.setCode(1);
        rolePO.setCreateTime(new Date());
        rolePO.setStatus(true);
        int count = rolePOMapper.insert(rolePO);

        if (count > 0) {
            throw new RuntimeException("异常错误");
        }

        return "count = " + count;
    }
}

@Transactional失效场景


方法内部调用@Transactional修饰的方法事务不生效

@Transactional事务场景也是基于动态代理实现的,那么相当于给方法增强,通过代理对象处理,而通过this调用的是源对象,绕过了代理对象,所以事务不生效。

@Service
public class TestService {

    @Resource
    private RolePOMapper rolePOMapper;

    public String doTransactionTest(RolePO rolePO) {

        int count = this.doInnerTest(rolePO);
        return "count = " + count;
    }

    @Transactional(rollbackFor=RuntimeException.class)
    public int doInnerTest(RolePO rolePO) {
        rolePO.setId(UUID.randomUUID().toString().replace("-", ""));
        rolePO.setCode(1);
        rolePO.setCreateTime(new Date());
        rolePO.setStatus(true);
        int count = rolePOMapper.insert(rolePO);

        if (count > 0) {
            throw new RuntimeException("异常错误");
        }

        return count;
    }
}

参考

https://blog.csdn.net/qq_42631788/article/details/142257583

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容