1、背景
在我们的日常开发中,经常会存在在一个Service层中调用另外一个Service层的方法。比如
:我们有一个TaskService,里面有一个execTask方法,且这个方法存在事务,这个方法在执行完之后,需要调用LogService的insertLog方法记录一条日志,这个方法上也有事务,不管日志记录成功还是失败,都不能影响execTask方法的执行。因此我们很容易写出如下代码。
@Transactional
public void execTaskV1(){
log.info("开始执行任务");
try {
logService.insertLogV1();
} catch (Exception e) {
log.error("添加日志出现错误");
}
log.info("完成任务执行");
}
思考:
上方的代码,如果insertLogV1
跑出了异常,execTaskV1
方法的事务可以正常提交吗?
2、异常是如何实现出现的
1、了解Spring事务的传播属性
传播行为 | 描述 | 应用场景 | 行为特点 |
---|---|---|---|
Propagation.REQUIRED |
|
|
– 如果当前事务不存在,创建新事务。 |
Propagation.SUPPORTS |
|
|
– 如果当前事务不存在,以非事务方式执行。 |
Propagation.MANDATORY |
|
|
IllegalTransactionStateException 。 |
Propagation.REQUIRES_NEW |
|
|
– 当前事务(如果有)会被挂起,直到新事务完成。 |
Propagation.NOT_SUPPORTED |
|
|
– 暂停当前事务(如果有)。 |
Propagation.NEVER |
|
|
TransactionException 。 |
Propagation.NESTED |
|
|
– 如果当前事务不存在,创建新事务。 |
2、模拟异常出现
Transaction rolled back because it has been marked as rollback-only
这个异常在上述的案例中是如何实现的呢?

从上图中可知,出现了Transaction rolled back because it has been marked as rollback-only
这个异常,那么这个异常是如何出现的呢?
其实这个是和Spring事务的传播属性Propagation
有关。
默认情况下@Transaction
的传播属性是Propagation.REQUIRED
, 即如果当前存在事务,则加入该事务;如果当前没有事务,则启动一个新的事务。
在我们的例子中,事务的隔离级别都是Propagation.REQUIRED
,即是在同一个事务中,因此insertLogV1
方法抛出异常后,虽然上层捕获到了,但其实这个时候这个事务已经被标记成回滚
状态了,因此事务无法提交成功。
如何解决:
只需要修改insertLogV1
事务的传播属性为Propagation.REQUIRES_NEW
即可。
3、完整代码
完整代码-https://gitee.com/huan1993/spring-cloud-parent/tree/master/springboot/springboot-transaction-v1
原文始发于微信公众号(huan1993的编程coding):Transaction rolled back because marked as rollback-only问题解决
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/312673.html