Hello 大家好,我是兔子
在Spring开发中,事务管理是保证数据一致性的核心机制。但许多开发者在使用@Transactional
注解时,都曾踩过事务失效的坑。本文总结了8个最常见的原因,通过代码示例带你快速定位问题。
一、数据库引擎不支持事务(最隐蔽的坑)
示例场景: MySQL使用MyISAM引擎
@Transactional
public void transferMoney() {
// 转账业务逻辑...
}
原因分析: MyISAM引擎不支持事务,即使代码正确,事务也不会生效。
解决方案: 检查数据库表引擎是否为InnoDB:
ALTER TABLE your_table ENGINE = InnoDB;
二、非public方法使用@Transactional
错误示例:
@Transactional
private void updateOrderStatus() { // 非public方法
// 更新订单状态
}
原因分析: Spring基于代理实现事务,无法为private/protected方法生成代理。
解决方案: 将方法改为public:
@Transactional
public void updateOrderStatus() { ... }
三、异常类型不匹配
错误示例:
@Transactional
public void createOrder() throws Exception {
// 业务代码...
if(error) throw new Exception("错误"); // 抛出检查型异常
}
原因分析: 默认只回滚RuntimeException和Error,检查型异常不会触发回滚。
解决方案: 指定回滚异常类型:
@Transactional(rollbackFor = Exception.class)
四、自调用导致事务失效
错误示例:
public class OrderService {
public void processOrder() {
updateInventory(); // 自调用
}
@Transactional
public void updateInventory() { ... }
}
原因分析: 通过this调用的方法不会经过代理对象。
解决方案:
1. 注入自身代理对象:
@Autowired
private OrderService selfProxy;
public void processOrder() {
selfProxy.updateInventory();
}
2. 使用AopContext获取代理:
((OrderService) AopContext.currentProxy()).updateInventory();
五、事务传播设置不当
典型场景:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void methodA() {
methodB();
}
@Transactional(propagation = Propagation.REQUIRED)
public void methodB() {
// 异常发生
}
现象: methodB抛出异常时,methodA的事务可能不会回滚。
解决方案: 理解不同传播机制的特点,必要时使用嵌套事务(NESTED)。
六、手动捕获异常未抛出
错误示例:
@Transactional
public void saveData() {
try {
// 可能出错的代码
} catch (Exception e) {
e.printStackTrace(); // 吞掉异常
}
}
原因分析: 事务管理器无法感知到异常。
解决方案: 在catch块中抛出运行时异常:
catch (Exception e) {
throw new RuntimeException(e);
}
七、多数据源配置冲突
典型错误: 配置多个DataSource但未指定事务管理器:
@Bean
@Primary
public DataSource primaryDataSource() { ... }
@Bean
public DataSource secondaryDataSource() { ... }
解决方案: 明确指定事务管理器:
@Transactional("secondaryTransactionManager")
public void multiDataSourceOperation() { ... }
八、未启用事务管理
致命错误: 忘记在配置类添加注解:
// 缺失@EnableTransactionManagement
@SpringBootApplication
public class Application { ... }
解决方案: 确保主配置类包含以下注解:
@EnableTransactionManagement
快速检查清单
当遇到事务失效时,请按此顺序检查:
- 数据库引擎是否支持事务
- 异常类型和捕获方式
- 方法是否为public
- 是否自调用
- 是否启用事务管理
- 多数据源配置
- 事务传播设置
- 是否手动捕获异常
喜欢的话可以给博主点点关注哦 ➕