1. 方法不是 public修饰
Spring AOP 仅对 public 方法生成代理,非 public 方法(private、protected、default)的 @Transactional 会被忽略,事务不生效。
// 错误示例:private方法的事务无效
@Transactional
private void saveData() { ... }
2. 未开启事务管理
需通过 @EnableTransactionManagement 注解开启 Spring 事务支持(Spring Boot 项目会自动开启,非 Boot 项目需手动配置)。若未开启,@Transactional 注解完全不生效。
3. 事务传播行为配置错误
某些传播行为会导致事务不生效,例如:
● Propagation.NOT_SUPPORTED:以非事务方式执行,若当前存在事务则挂起。
● Propagation.NEVER:不允许在事务中执行,若当前存在事务则抛异常。
// 错误示例:此方法不会在事务中执行
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void saveData() { ... }
4. 异常被捕获且未重新抛出
事务默认仅在未捕获的 unchecked 异常(如 RuntimeException)时回滚。若方法内部捕获了异常且未重新抛出,事务会认为执行成功而提交,导致 “看似失效”。
// 错误示例:异常被捕获,事务不会回滚
@Transactional
public void saveData() {
try {
// 数据库操作
throw new RuntimeException("出错了");
} catch (Exception e) {
// 仅捕获异常未抛出,事务提交
}
}
5. 异常类型不匹配
默认情况下,事务仅对 RuntimeException 和 Error 回滚。若抛出 checked 异常(如 IOException),且未通过 rollbackFor 指定,事务不会回滚。
// 错误示例:抛出IOException(checked异常),事务不回滚
@Transactional
public void saveData() throws IOException {
throw new IOException("IO错误");
}
// 正确示例:指定rollbackFor包含checked异常
@Transactional(rollbackFor = IOException.class)
public void saveData() throws IOException { ... }
6. 数据源未配置事务管理器
Spring 事务依赖 PlatformTransactionManager(如 DataSourceTransactionManager)。若未配置事务管理器(或配置错误),@Transactional 无法生效。
// 正确配置示例(Spring Boot自动配置,非Boot需手动)
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
7. 数据库本身不支持事务
若使用的数据库存储引擎不支持事务(如 MySQL 的 MyISAM 引擎),即使配置了 @Transactional,事务也不会生效。需将引擎改为 InnoDB。
8.同一类中调用 @Transactional方法失效
Spring 的事务管理基于 AOP 动态代理:
● 当外部调用被 @Transactional 标注的方法时,Spring 会通过代理对象拦截调用,在方法执行前后开启、提交 / 回滚事务。
● 但如果是类内部方法调用(例如 A.method1() 调用同一个类的 A.method2(),且 method2 被 @Transactional 标注),此时调用的是目标对象本身(而非代理对象),AOP 拦截器无法生效,导致事务注解失效。
@Service
public class UserService {
// 内部调用带@Transactional的方法
public void createUser() {
// 此处调用的是目标对象的saveUser(),而非代理对象,事务失效
this.saveUser();
}
@Transactional
public void saveUser() {
// 数据库操作(事务不生效)
}
}
如何避免同一类内部调用导致的事务失效?
若必须在同一类中调用事务方法,可通过以下方式让事务生效:
1. 自注入代理对象(需开启 @EnableAspectJAutoProxy(exposeProxy = true)):
@Service
public class UserService {
// 注入自身代理对象
@Autowired
private UserService self;
public void createUser() {
// 调用代理对象的事务方法
self.saveUser();
}
@Transactional
public void saveUser() { ... }
}
2. 通过 AopContext 获取代理对象:
public void createUser() {
// 获取当前类的代理对象
UserService proxy = (UserService) AopContext.currentProxy();
proxy.saveUser(); // 事务生效
}
















- 最新
- 最热
只看作者