@Transactional事务回滚不生效,注解的继承

本文解析了Java中注解的继承机制,强调了@Inherited元注解的作用,并通过@Transactional注解的例子说明了注解在接口与实现类之间的正确使用方式。

关于注解的继承

刚在群里有个人问怎么事务回滚不生效,然后截图一看,@Transactional打在接口上。这毫无疑问就是错误的根源,让他把@Transactional写在实现方法上就解决了。

众所周知,注解一般不能被继承。但是准确的说, 子类其实是可以继承父类的type注解的,如果需要继承父类的方法上的注解,就需要加一个@Inherited元注解。
关于元注解大家可通过 https://blog.youkuaiyun.com/javazejian/article/details/71860633 了解
但是,大家如果看到@Transactional的源码的话,就会发现它自带了@Inherited注解:
在这里插入图片描述

那么为什么群里的同学还是出错呢?请仔细看我上面说的:子类其实是可以继承父类的type注解的,如果需要继承父类的方法上的注解,就需要加一个@Inherited元注解。

其中有一个特性:写在父类的类上的注解可以被继承,父类的方法上的注解无法被继承!
所以一般来说,我们应当在实现方法上打注解。

在 Spring 框架中,使用 `@Transactional` 注解来管理事务是常见的做法。然而,在某些情况下,尤其是在执行删除(delete)操作时,事务可能会失效,导致预期的回滚或提交行为未能按预期执行。以下是一些可能导致 `@Transactional` 在 delete 方法中不生效的原因及其解决方案。 ### 1. 异常型问题 默认情况下,Spring 的事务管理仅对未检查异常(unchecked exceptions),即继承自 `RuntimeException` 或 `Error` 的异常进行回滚。对于已检查异常(checked exceptions),例如 `IOException`、`SQLException` 等,事务不会自动回滚[^3]。因此,如果 delete 方法抛出的是已检查异常,需要显式指定 `rollbackFor` 属性以确保事务能够正确回滚。 ```java @Transactional(rollbackFor = Exception.class) public void deleteWithRollbackOnCheckedException() throws Exception { // 执行 delete 操作 // 如果发生 checked exception,则会回滚 } ``` ### 2. 自调用问题(Self-invocation) 当在一个内部调用带有 `@Transactional` 注解的方法时,由于 Spring AOP 代理机制的限制,事务可能不会生效。这是因为 Spring 使用基于代理的 AOP 实现,默认情况下只有外部调用才会经过代理对象,从而触发事务管理逻辑。为了解决这个问题,可以考虑重构代码,将事务方法移到另一个 bean 中,或者使用 `AopContext.currentProxy()` 来获取当前代理对象并进行自我调用。 ```java @Service public class MyService { @Autowired private MyService selfProxy; @Transactional public void deleteOperation() { // 删除操作 } public void triggerDelete() { ((MyService) AopContext.currentProxy()).deleteOperation(); // 使用代理调用 } } ``` ### 3. 非 public 方法 Spring 的事务管理功能依赖于代理模式,这意味着只有 public 方法才能被正确地代理和增强。如果尝试在非 public 方法上使用 `@Transactional` 注解事务管理将不会生效。确保所有需要事务支持的方法都是 public 访问级别的。 ### 4. 数据源配置问题 确保数据源配置正确,并且启用了事务管理。在 Spring 配置文件中,应该包含 `<tx:annotation-driven />` 元素以启用注解驱动的事务管理。此外,还需要正确配置 `PlatformTransactionManager` bean。 ```xml <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> ``` ### 5. SQL 语句问题 某些数据库操作可能不会触发事务管理,比如 DDL 语句(CREATE, ALTER, DROP)。这些操作通常具有隐式的提交行为,即使它们位于一个事务块内。确保 delete 操作不是与这语句混合使用的。 ### 总结 要解决 `@Transactional` 在 delete 操作中不生效的问题,首先应检查是否是因为异常型不当导致的回滚失败,然后确认是否存在自调用问题,接着验证方法访问权限是否为 public,最后检查数据源和事务管理器的配置是否正确。通过以上步骤,大多数关于 `@Transactional` 不生效的问题都可以得到解决。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值