spring事务失效的原因与场景
Spring的事务在什么样的情况下会失效?
1底层数据库不支持事务
如MySQL的MyISAM 引擎是不支持事务操作的,如果底层使用MySQL数据库和MyISAM 引擎。那么spring事务事务管理会失效。
2没有被spring管理
如下面例子所示:
// @Service
public class OrderServiceImpl implements OrderService {
@Transactional
public void updateOrder(Order order) {
// update order;
}
}
如果此时把 @Service
注解注释掉,这个类就不会被加载成一个 Bean,那这个类就不会被 Spring 管理了,事务自然就失效了。
3方法不是public
– 该异常一般情况都会被编译器帮忙识别
以下来自 Spring 官方文档:
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do
annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the
annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need
to annotate non-public methods.
翻译:
在使用代理时,应该只对具有公共可见性的方法应用@Transactional注释。如果使用@Transactional注释了受保护的、私有的或包可见的方法,则不会引发错误,但注释的方法不会显示配置的事务设置。如果需要注释非公共方法,请考虑使用AspectJ。
如:
4本类中没有事务的方法调用了其他没有加事务的方法
方法A加了事务注解,但是它调用了没有加事务的方法B。那么此时方法会失效:
// methodA,和methodB在同一个类中
@Transactional(rollbackFor = Exception.class)
public void methodA(){
methodB();
}
public void methodB(){
System.out.println("事务失效");
}
5数据源,没有配置事务管理器
事务生效,必须配置数据源管理器:
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
6主动不支持事务
如使用@Transactional(propagation = Propagation.NOT_SUPPORTED)
传播属性NOT_SUPPORTED
不支持事务
当前若存在事务则挂起,
7异常被捕获
@Transactional(rollbackFor = Exception.class)
public void testTransactionException(){
try {
System.out.println("事务失效");
} catch (Exception e) {
e.printStackTrace();
}
}
8异常类型错误或格式错误
默认回滚的是:RuntimeException。如果要其他异常生效。需要配置rollbackFor = SQLException.class
或者它的父类LException
@Transactional()
//@Transactional(rollbackFor = SQLException.class)
// @Transactional(rollbackFor = Exception.class)
public void testTransactionDefaultException(){
try {
System.out.println("111");
throw new SQLException("事务失效");
} catch (SQLException e) {
e.printStackTrace();
}
}