Spring @Transactional 注解细节

转载自:https://www.jianshu.com/p/ec899855f049

叙述

对于 Java 后端开发人员,Spring 事务注解几乎天天都会接触。但是,你真的全部了解 Spring 事务注解的细节吗?今天我们就来深入讨论一下 Spring 事务注解中回滚、传播行为和只读这三个属性的配置调优。

希望通过本文能让大家了解更多和数据库事务相关的框架,以及数据库引擎的内部原理,为大家的数据库优化工作提供一些有用的建议。

为什么要配置 rollbackFor = Exception.class

最近,阿里将其编码规范按照 IDE 插件的方式发布。插件检查结果中有这么一条:“Spring 事务需要设置 rollbackFor 属性或者显式调用 rollback 方法”。为什么需要设置 rollbackFor 属性呢?

简单来说,如果不设置 rollbackFor = Exception.class,则当方法抛出检查型异常时,数据库操作不会回滚。

举例来说,对于下面的代码:

@Transactional
public void demo() throws Exception {
    this.userRepository.save(new User(USERNAME));
    throw new Exception("No Rollback");
}

执行完毕之后,数据库中会增加一条 user 记录。如果你希望在方法抛出检查型异常后触发数据库回滚,那你需要这样写:

@Transactional(rollbackFor = Exception.class)
public void demo() throws Exception {
    this.userRepository.save(new User(USERNAME));
    throw new Exception("No Rollback");
}

或者使用 TransactionStatus.setRollbackOnly() 手动触发回滚:

@Transactional
public void demo() {
    this.userRepository.save(new User(USERNAME));
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}

如果你的方法没有声明异常,只会抛出运行时异常,则不需要设置 rollbackFor。运行时异常抛出后会触发事务回滚。

@Transactional
public void demo() {
    this.userRepository.save(new User(USERNAME));
    throw new RuntimeException("Rollback");
}

如果代码如上所示,则不会有新的 user 记录。因为数据库操作回滚了。

需不需要配置 rollbackFor

因为如果方法会抛出检查型异常,则必须在方法中声明异常。因此,一般而言,如果方法没有声明异常,则不需要配置在 Spring 事务注解中配置 rollbackFor。

另外,我在阿里的 Java 编码规范里也没有找到关于设置 rollbackFor 的内容。因此,我的个人意见是方法不抛出检查型异常就不必设置 rollbackFor。

Spring 为何这么设计

对于 Spring 为什么默认不回滚检查型异常这个问题,我想是和 Java 异常处理的原则有关。原则上,检查型异常都是业务异常流的一部分,需要开发人员定制开发相应的异常处理功能。既然需要开发人员定制,自然 Spring 认为自己不必画蛇添足了,自动地回滚数据库操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值