日常使用 @Transactional 事务不生效的原因

5 篇文章 0 订阅

@Transactional是在Spring开发的时候非常普遍实用的注解,该注解主要用来声明事务。它的实现原理是通过Spring AOP在注解修饰方法的前后织入事务管理的实现语句,所以开发者只需要通过这个注解就能代替一系列繁琐的事务开始、事务关闭等重复性的编码任务。

编码方式确实非常简单了,但也因为隐藏了直观的实现逻辑,一些错误的编码方法可能会让@Transactional注解失效,达不到事务的作用。估计大多数童鞋遇到过明明加了次注解但是事务不生效。

一、选择支持事务的引擎和数据库

在mysql中用的最多的存储引擎有:innodb,bdb,myisam ,memory 等。其中innodb和bdb支持事务而myisam等不支持事务。

二、缺少启注解事务管理

@EnableTransactionManagement(proxyTargetClass = true)

三、@Transactional修饰方法不是public

错误案例:

/**
 * @author 重庆阿汤哥
 * @Description:
 * @date 2021/12/1  10:59
 */

public class TestServiceImpl{
    
    @Transactional
    private void  testMethod() {
        // 写数据库操作
    }
    
}
 

@Transactional基于Spring AOP实现的,使用注解时需要满足次要求。正确的是直接把方法访问类型改成public即可。

四、回滚异常配置不正确

/**
 * @author 重庆阿汤哥
 * @Description:
 * @date 2021/12/1  10:59
 */
    @Transactional(rollbackFor = 自定义异常.Class)
    public int insertDictData(SysDictData dictData) {
        int row = dictDataMapper.insert(dictData);
        return row;
    }

@Transactional默认情况下,仅对RuntimeExceptionError进行回滚。如果自定义异常没有继承他们两个进行的实现,就不会回滚。

那么,在日常开发过程中自定义异常的时候,可以定义为RuntimeException的子类;如果不是RuntimeException,但也希望触发回滚,那么可以使用rollbackFor属性来指定具体要回滚的异常。

五、跨库操作

 /**
 * @author 重庆阿汤哥
 * @Description:
 * @date 2021/12/1  10:59
 */
public class TestServiceImpl {
        
        /**
     * @author 重庆阿汤哥
     * @Description:支付接口
     * @date 2021/12/1  10:59
     */
    @Transactional
    public void payMethod(OrderIO io) {
        repertoryDataBase.save(io);
        payCoreDataBase.pay(io);
    }

}

这个例子里的repertoryDataBase和payCoreDataBase是连接的两个不同数据源。正常情况下,这种跨数据源的事务是不会成功的。

如果要在多个数据源之间实现事务,可以实用JTA、LCN、SEATA等支撑分布式框架

 如果你发现还有其他情况还没有囊括其中,欢迎告诉大家在评论区评论,共同进步。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值