@Transactional 注解详解以及事务失效原因

@Transactional是Spring框架提供的一个关于事务管理的注解,它实现了声明式事务管理。这个注解可以被应用在接口定义、类定义和方法级别。


1.使用@Transactional

通常,我们会在需要进行数据库操作的service层的方法上添加@Transactional注解,来表明该方法需要进行数据库事务控制。以下是一个简单的例子:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void insertTwo() {
        User userA = new User();
        userA.setUserName("userA");
        userRepository.save(userA);

        // 制造一个错误,使得两次插入操作都无法成功
        int error = 1 / 0;

        User userB = new User();
        userB.setUserName("userB");
        userRepository.save(userB);
    }
}

以上代码中,insertTwo方法内部有两次数据插入操作,如果一次成功一次失败,则两次操作都不会生效,因为它们被包含在同一个事务当中。


2.@Transactional参数详解

  • propagation:定义事务的传播行为,默认值是 Propagation.REQUIRED

    • REQUIRED:如果当前存在事务,那么加入该事务;如果当前没有事务,则创建一个新的事务。
    • SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式执行。
    • MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
    • REQUIRES_NEW:创建新的事务,如果当前存在事务,把当前事务挂起。
    • NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
    • NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
    • NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则此选项等价于 REQUIRED
  • isolation:定义事务的隔离级别,默认值是 Isolation.DEFAULT

    • DEFAULT:使用后端数据库默认的隔离级别。
    • READ_UNCOMMITTED:读取未提交数据。
    • READ_COMMITTED:读取已提交数据。
    • REPEATABLE_READ:可重复读。
    • SERIALIZABLE:串行化。
  • timeout:设置事务超时时间,默认值是 -1,表示永不超时。

  • readOnly:指定事务是否为只读事务。只读事务可以帮助数据库引擎优化事务。如若事务只读取数据而不做任何更新操作,应设置为只读。

  • rollbackFor:用于指定能引发事务回滚的异常类数组。

  • noRollbackFor:用于指定不会引发事务回滚的异常类数组。

以下是使用了所有参数的示例:

@Transactional(propagation = Propagation.REQUIRED,
              isolation = Isolation.READ_COMMITTED,
              timeout = 3600,
              readOnly = false,
              rollbackFor = Exception.class,
              noRollbackFor = FileNotFoundException.class)
public void insertTwo() {
    // ...
}

3.事务失效的原因

有时候,我们在使用 @Transactional 注解后,会发现事务并没有如预期那样生效。这种情况可能是由以下几个原因导致的:

  1. 方法访问权限设置问题:被 @Transactional 注解的方法必须是public的。

  2. 事务方法嵌套调用问题:如果在同一个类中,一个没有使用 @Transactional 的方法内部调用了另一个带有 @Transactional 的方法,那么事务是不会起作用的。

  3. 数据库引擎不支持事务:例如,MySQL的MyISAM引擎就不支持事务。

  4. 异常类型不匹配:默认情况下,当运行时(unchecked)异常发生时,Spring会标记事务进行回滚;对于检查型(checked)异常,Spring则不会标记事务进行回滚。可以通过 rollbackFornoRollbackFor 参数来改变这一行为。

以上就是 @Transactional 的基本使用和事务失效的常见原因。希望能帮助大家更好地理解和使用 @Transactional 来管理你们的事务。


4.总结

使用Transactional注解可以帮我们更简单、方便地进行事务控制。然而,它并不适用于所有场合,比如在多线程环境中,由于Spring采用线程绑定的策略来管理事务,因此@Transactional无效;另外,在异步方法中,@Transactional也无法生效。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值