关于springboot中的事务注解

本文解析了SpringBoot项目中事务管理的自动配置原理,并探讨了如何通过配置@Transactional注解来确保不同类型的异常都能触发事务回滚。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前: 在项目运行时,由于某条数据插入失败,发现事务未起作用

看了下启动类并没有加@EnableTransactionManagement注解开启事务

@EnableScheduling
@SpringBootApplication
@MapperScan(basePackages = "com.huofu.koudai.mapper")
@EnableConfigurationProperties(OssProperties.class)
@EnableTransactionManagement
public class AppApplication {

     public static void main(String[] args) {

          SpringApplication.run(AppApplication.class, args);
         }


    @Bean
    public OssTemplate ossTemplate(OssProperties properties) {
        return new OssTemplate(properties);
    }
}

在添加了注解后发现事务仍然不起作用,查阅资料后发现springboot的自动装配自动开启了事务管理

具体流程如下:

查看启动类的核心注解

找到自动装配注解

进入自动装配注解查看选择器

 继续进入选择器,查看选择器所导入的类,找到自动获得的Entity

找到该方法

 此方法传入一个元数据

此方法中的loadFactoryNames方法, 就是加载所有的组件的全限类

进入 loadFactoryNames方法,此方法第一个参数为类型,第二个参数为类加载器,返回值为本类的loadSpringFactories方法

 查看loadSpringFactories方法

getResources获取自动配置组件
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

找到public class AutoConfigurationImportSelector类所在的包,查看它的META-INF文件,找到spring.factories文件:

 进入此文件我们可以看到,事务的自动装配配置类,当Springboot容器启动的时候,首先会扫描此文件,会自动为我们加载事务相关信息

因此,springboot项目并不需要@EnableTransactionManagement注解开启事务

接下来,继续查找事务不生效的原因:

最终查询到在Spring的Transactional的API文档中,有以下一段说明:

If no rules are relevant to the exception, it will be treated like DefaultTransactionAttribute (rolling back on runtime exceptions)

意思是:如果没有与异常相关的规则,它将被视为默认事务属性(即回滚运行时异常)。

因此需要指定注解属性为@Transactional(rollbackFor = Exception.class),这样,便可回滚所有异常.

总结:

① springboot自动装配会自动开启事务,不需要@EnableTransactionManagement注解开启事务

② spring声明式事务,需要在@Transactional注解添加rollbackFor指定回滚类型,否则默认只回滚运行时异常

 

### Spring Boot事务注解 `@Transactional` 失效的场景、原因及解决方案 #### 一、失效场景分析 1. **未通过代理调用方法** 当使用 `@Transactional` 注解的方法被同一类中的其他方法直接调用时,事务并不会生效。这是因为在 Spring 中,`@Transactional` 是基于动态代理实现的,只有外部对象通过代理调用来触发该方法时,事务才会起作用[^2]。 2. **异常类型不匹配** 默认情况下,Spring事务只会在遇到 `RuntimeException` 或其子类时才回滚。如果抛出的是受检异常(Checked Exception),则不会触发事务回滚,除非显式配置了 `rollbackFor` 参数[^1]。 3. **传播行为配置不当** 如果事务的传播行为设置不合理,也可能导致事务失效。例如,当传播行为设为 `PROPAGATION_SUPPORTS` 时,如果没有现有事务,则当前操作将不在事务中执行。 4. **数据库引擎不支持事务** 数据库本身如果不支持事务功能(如 MySQL 的 MyISAM 存储引擎),即使应用层配置了事务,也无法正常工作。因此,应确保使用的存储引擎支持事务,比如 MySQL 的 InnoDB。 5. **异步方法中使用事务** 在同一个方法上同时标注 `@Async` 和 `@Transactional` 导致事务失效的情况较为特殊。原因是 `@Async` 方法会被分配到一个新的线程去执行,而默认情况下,Spring事务上下文仅适用于创建它的原始线程[^4]。 --- #### 二、具体原因解析 - **代理机制限制** Spring 使用 AOP 动态代理技术来拦截带有 `@Transactional` 注解的方法调用,并为其提供事务管理服务。但如果方法是从内部调用而非经过代理对象访问,则无法激活事务逻辑[^2]。 - **异常捕获问题** 若在业务代码中手动捕获并吞掉了所有异常,那么即便设置了事务也不会发生回滚动作,因为框架检测不到任何错误信号[^1]。 - **线程切换影响** 当涉及多线程编程时(例如结合 `@Async` 使用),原生主线程上的事务状态难以传递至新启动的工作线程里,从而造成事务丢失现象[^4]。 --- #### 三、解决方案总结 针对以上提到的各种可能导致 `@Transactional` 注解失效的情形,分别给出如下应对措施: 1. **调整方法调用方式** 确保标记有 `@Transactional` 的方法始终是由外部组件间接调用而不是简单地自我循环引用;必要时可通过引入额外的服务层封装公共逻辑以便正确触发动态代理过程[^2]。 2. **修改回滚策略** 自定义 `@Transactional` 注解参数以覆盖默认行为,允许特定条件下对任意类型的异常均实施回滚处理。例如: ```java @Transactional(rollbackFor = {Exception.class}) ``` 3. **优化事务传播模式** 根据实际需求重新评估每处需开启事务的位置是否有必要更改现有的传播级别设定,避免不必要的嵌套或独立运行状况出现意外后果。 4. **选用合适的数据库驱动与表结构设计** 定期审查生产环境下的数据持久化设施选型情况,确认它们都已启用完整的ACID特性保障能力后再部署上线应用程序[^2]。 5. **分离异步任务与事务边界** 不要在单个函数体内混合声明 `@Async` 和 `@Transactional` 。而是考虑重构代码架构让两者各自单独承担职责范围内的责任领域分开运作[^4]。 --- ### 示例代码展示 下面是一组改进后的样例演示如何规避常见的陷阱: ```java @Service public class OrderService { @Autowired private PaymentService paymentService; /** * 正确做法:通过另一个 Service 类调用带事务的方法 */ public void placeOrder(Long orderId) { try { this.paymentService.charge(orderId); } catch (PaymentFailedException e) { log.error("支付失败", e); throw new TransactionRollbackException(e.getMessage(), e); } } } @Service public class PaymentService { @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class) public void charge(Long orderId) throws PaymentFailedException { // 执行扣款逻辑... if (!isSuccessful()) { throw new PaymentFailedException("模拟支付失败"); } } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值