Spring事务失效场景
-
数据库不支持事务
- 比如MySQL数据库的MyISAM存储引擎
-
事务方法未被Spring管理
- 使用Spring注解@Transactional进行事务管理的方法所在的类没有在Spring IOC容器的管理中。
-
事务方法不是public修饰符
- Spring对事务方法时通过AOP实现的,只对public方法进行处理。
-
同一个类中没有事务声明的方法调用被声明事务的方法
- Spring对事务方法时通过AOP实现的,如果最外层方法没有被事务声明时,即时被直接调用的同一个类中的方法上面存在事务,也不会生效。
- 如果外层的方法上面有事务,直接调用的同一个类中的方法上面即时有事务,也不会直接生效。最终是被外层方法的事务控制。
-
未配置事务管理器
-
如果在项目中没有配置Spring的事务管理器,Spring的事务也不会生效。
java@Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); }
-
-
方法的事务传播类型不支持事务
-
如果内部方法的事务传播类型为不支持事务的传播类型,内部方法就不会被Spring的事务管理
java@Service public class OrderService { @Autowired private OrderDao orderDao; @Autowired private ProductDao productDao; @Transactional(propagation = Propagation.REQUIRED) public void submitOrder(){ //生成订单 Order order = new Order(); long number = Math.abs(new Random().nextInt(500)); order.setId(number); order.setOrderNo("order_" + number); orderDao.saveOrder(order); //减库存 this.updateProductStockCountById(1, 1L); } // 事务传播类型NOT_SUPPORTED,不支持事务 @Transactional(propagation = Propagation.NOT_SUPPORTED) public void updateProductStockCountById(Integer stockCount, Long id){ productDao.updateProductStockCountById(stockCount, id); } }
-
-
不正确的捕获异常
- 如果方法抛出的异常被捕获处理,没有被Spring获取到时,最终会正常提交,不会回滚。
-
Spring事务管理针对的异常和抛出的异常类型不一致
- 默认情况下Spring事务注解@Transaction只会针对RuntimeException异常进行处理
- 如果@Transaction配置的处理异常是RuntimeException,但抛出的异常是Exception,事务失效。