springboot基于多线程的事务有效性

  1. 业务场景
    一个上报数据的接口,因为上报数据需要快速返回,上报方不关心上报结果,并且,需要同时进行多张表的存储操作,要保证多张表同时存储成功,否则将会产生脏数据。
  2. 事务为什么会失效
在 Java 中,`@Transactional` 注解通常与事务管理器一起使用,用于标记一个方法应该被包装在一个事务中执行。在同一类中,`@Transactional` 注解可能会失效或不起作用的一些常见情况包括:

1. **自调用问题:** 如果一个带有 `@Transactional` 注解的方法在同一个类中被另一个方法内部直接调用(而不是通过代理对象调用),事务注解可能会失效。这是因为 Spring 使用代理对象来实现事务管理,如果方法直接被调用而不是通过代理对象,事务注解将不会生效。

2. **非公共方法调用问题:** 如果带有 `@Transactional` 注解的方法是私有的、受保护的或默认访问权限的,并且被同一类中的公共方法调用,事务注解可能会失效。因为 Spring AOP 代理只会围绕公共方法创建代理。

3. **异步方法问题:** 如果带有 `@Transactional` 注解的方法是异步方法(使用 `@Async` 注解标记),事务注解可能会失效。这是因为异步方法会在一个新的线程中执行,而事务上下文可能无法正确传播到新的线程中。

4. **事务传播问题:** 如果同一类中的方法使用不同的事务传播行为(如 `REQUIRES_NEW`),事务注解可能会失效。这是因为事务传播行为会影响事务的范围和生命周期。

5. **编译时代理问题:** 如果在同一类中使用了 `this` 关键字来调用带有 `@Transactional` 注解的方法,事务可能会失效。因为 Spring 默认使用基于代理的 AOP,而 `this` 关键字会绕过代理对象。

在这些情况下,`@Transactional` 注解可能会失效,因此在设计和使用事务时需要注意以上情况,确保事务能够正确生效并达到预期的效果。
  1. 在启动类添加注解
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement // 事务托管注解
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

  1. 在主方法
    @Transactional
    public void master(Request req) {
    
        // 异步处理数据,自定义事务,防止事务失效
        CompletableFuture.runAsync(() -> {
			// 这行代码将获取到的事务状态对象赋值给 transactionStatus 变量,以便后续对事务的操作和管理,这里的事务指spring事务
            TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());
            try {
                // 保存数据
                this.save(req);
                // 提交事务
                transactionManager.commit(transactionStatus);
            } catch (Exception e) {
            	// 如果有异常事务失效要回滚
                transactionManager.rollback(transactionStatus);
                //  这里可以自定义异常抛出去
                throw new BusinessLogicException(e.getMessage());
            }
        });
    }
  1. 在被调用的方法(想保证事务的方法,例如mysql的存储)
 /**
     * Propagation.REQUIRES_NEW 表示当前方法会挂起当前事务(如果存在的话),并开启一个新的事务来执行。这样无论外部事务是否成功,内部事务都会独立执行,互不影响。
     * 配置为 Exception.class 表示任何继承自 Exception 的异常都会触发事务回滚操作。如果方法中抛出了这些异常之一,事务会回滚到之前的状态。
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public void save(Request req) {
        	// 执行表一存储
       
      	    // 执行表二存储
        }
    }
  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值