@transactional注解失效导致回滚失败,主因包括:①方法非public;②异常被吞或未设rollbackfor;③同类内部调用绕过代理;④类未被spring管理或方法为final。

权限本身不会导致“回滚失败”,你真正遇到的,是 @Transactional 注解失效 —— 表现为:方法加了事务注解,但异常发生后数据仍被提交,看起来像“回滚没起作用”。这背后几乎都不是数据库权限问题,而是 Spring 事务机制未被正确触发。
方法不是 public 修饰
Spring 事务基于动态代理实现,只有 public 方法才能被代理拦截。如果把 @Transactional 加在 private、protected 或包级(default)方法上,事务注解完全被忽略。
- private void doSave() { ... } → 事务无效
- public void doSave() { ... } → 正确写法
异常被自己吞掉,没抛给 Spring
@Transactional 默认只对 RuntimeException 和 Error 自动回滚。如果你 catch 了异常又没重新 throw,或者只抛出 checked 异常(如 IOException、SQLException),Spring 就不会触发回滚。
- try { ... throw new Exception("业务失败"); } catch (Exception e) { log.info(e); } → 不回滚
- 加上 @Transactional(rollbackFor = Exception.class),并确保异常最终向上抛出
- 或在 catch 块中手动标记回滚:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()
同类内部调用绕过代理
在同一个 Service 类中,A 方法直接调用本类的 B 方法(哪怕 B 加了 @Transactional),由于 this 调用不经过代理对象,事务不生效。
- public void createOrder() { saveOrder(); } → 事务失效
- saveOrder() 是本类方法且加了 @Transactional,也无效
- 解决方式:抽取到另一个 Bean;或通过 AopContext.currentProxy() 获取代理对象再调用
类没被 Spring 管理或方法被 final 修饰
事务要生效,目标类必须是 Spring 容器管理的 Bean(即加了 @Service/@Component 等)。同时,final 方法无法被 CGLIB 代理,@Transactional 也会失效。
- 没有 @Service 的普通类 → 事务不工作
- public final void update() { ... } → 即使加注解也无效
- 确保类由 Spring 创建,且事务方法可被代理(非 final、非 static)











