You need to enable JavaScript to run this app. Spring JPA @Transactional事务场景下新增实例查询不到问题求助
优惠活动
大模型
产品
解决方案
定价
更多

Spring JPA @Transactional事务场景下新增实例查询不到问题求助

问题成因

  • 事务未提交导致数据不可见:method_m1标注的@Transactional会开启一个新事务,method_m2使用Propagation.REQUIRED传播级别会直接加入该事务,你在method_m2中执行save或saveAndFlush操作,仅会将实体存入JPA持久化上下文、将对应的插入SQL同步到数据库执行,但整个事务要等到method_m1完全执行结束才会正式提交,未提交的变更对其他事务完全不可见。这也是你尝试saveAndFlush仍然无效的核心原因——flush不等于commit,只是把变更同步到数据库的事务中,没有提交前外部还是读不到。
  • 异步逻辑脱离Spring事务管控:audit方法上标注的@Transactional(propagation = Propagation.REQUIRES_NEW)只会作用于同步调用的方法逻辑,你在方法内部通过CompletableFuture.runAsync提交的异步任务运行在独立线程中,完全脱离Spring AOP的代理范围,该事务注解不会对异步代码块生效。即使你将事务配置作用到异步线程,新开的事务也受数据库默认隔离级别(通常为READ_COMMITTED)限制,无法读取到method_m1未提交的用户数据。

解决方案

可根据业务场景选择适配方案:

  • 若审计不需要异步执行:直接去掉CompletableFuture.runAsync异步包装,让审计逻辑运行在method_m1的现有事务中,可直接读取到JPA上下文中的用户实体,不需要查询数据库,也不会出现找不到用户的问题。
  • 若必须保留异步审计逻辑:通过Spring事务同步机制,在method_m1的事务提交完成后再触发异步审计任务,示例代码如下:
public void audit(Result result){
    // 校验当前是否存在活动事务
    if (TransactionSynchronizationManager.isActualTransactionActive()) {
        // 注册事务回调,在事务提交完成后执行逻辑
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
            @Override
            public void afterCommit() {
                CompletableFuture.runAsync(() -> {
                    User user = userRepository.findById(result.get().getId())
                        .orElseThrow(() -> new UserNotFoundException("user not found, userId :" + result.get().getId()));
                    // 其余审计逻辑
                });
            }
        });
    }
}
  • 不推荐方案:调整数据库隔离级别为READ_UNCOMMITTED允许脏读,会引发大量数据一致性问题,仅可用于极端非核心业务场景。

内容的提问来源于stack exchange,提问作者Shekhar Khairnar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.09 20:36:03