Spring声明式事务生效是有条件滴!
在日常工作中,经常使用@Transactional 注解进行事务的声明,但如果发现事务未生效,可以从下面几个方面进行排查。
常见失效场景总结
场景 | 原因 | 解决方案 |
---|---|---|
内部方法调用 | 绕过了Spring代理 | 注入自身或使用AopContext |
private方法 | AOP无法增强 | 改为public方法 |
final方法/类 | 无法被代理 | 移除final修饰符 |
非Spring管理 | 不是代理对象 | 确保Bean由Spring管理 |
异常被捕获 | 异常未抛出到代理层 | 检查异常处理逻辑 |
数据库不支持 | 如MyISAM引擎 | 使用InnoDB等支持事务的引擎 |
1、配置事务管理器
在服务的启动类,需要配置@EnableTransactionManagement,核心作用是启用Spring的声明式事务管理功能。
在Spring Boot中,通常不需要显式添加@EnableTransactionManagement;但如果exclude = {DataSourceAutoConfiguration.class}
排除了DataSource自动配置,则需要显式声明
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) // 排除是由于项目需要,需要声明多数据源
@EnableTransactionManagement // 激活事务管理
public class Application {// 启用后,Spring会为带有@Transactional的Bean创建代理
}
或者可以使用XML配置方式配置
<tx:annotation-driven transaction-manager="transactionManager"/>
2、代理机制生效
// ❌ 错误:内部方法调用,事务不生效
@Service
public class UserService {@Transactionalpublic void methodA() {// 直接调用内部方法,事务失效this.methodB();}@Transactionalpublic void methodB() {// 事务不会生效}
}// ✅ 正确:通过Spring代理调用
@Service
public class UserService {@Autowiredprivate UserService self; // 注入自己或通过ApplicationContext获取@Transactionalpublic void methodA() {// 通过代理调用,事务生效self.methodB();}@Transactionalpublic void methodB() {// 事务生效}
}
3、异常类型匹配
@Transactional(rollbackFor = Exception.class)
public String createTask(ModelTaskDTO modelTaskDTO) throws TException, InterruptedException {// 所有异常都会回滚
}// 默认情况只回滚RuntimeException和Error
@Transactional // 只回滚RuntimeException
public void defaultRollback() {throw new IOException(); // 不会回滚
}
4、方法修饰符要求
public class ModelTrainingServiceImpl {// ✅ 正确:public方法@Transactionalpublic String createTask() {// 事务生效}// ❌ 错误:private方法事务不生效@Transactionalprivate void privateMethod() {// 事务不生效}// ❌ 错误:final方法无法被代理@Transactionalpublic final void finalMethod() {// 事务不生效}
}
5、Bean必须由Spring管理
// ✅ 正确:Spring管理的Bean
@Service
public class ModelTrainingServiceImpl {@Transactionalpublic void method() {// 事务生效}
}// ❌ 错误:手动new的对象
ModelTrainingServiceImpl service = new ModelTrainingServiceImpl();
service.method(); // 事务不生效
6、数据库支持事务
-
使用支持事务的数据库引擎(如MySQL的InnoDB)
-
正确配置数据源和连接
7、事务传播行为
@Service
public class YourService {@Transactional(propagation = Propagation.REQUIRED)public void method1() {// 默认传播行为}@Transactional(propagation = Propagation.REQUIRES_NEW)public void method2() {// 总是开启新事务}
}