@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默认情况下,仅对RuntimeException
和Error
进行回滚。如果自定义异常没有继承他们两个进行的实现,就不会回滚。
那么,在日常开发过程中自定义异常的时候,可以定义为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等支撑分布式框架
如果你发现还有其他情况还没有囊括其中,欢迎告诉大家在评论区评论,共同进步。