【发布时间】:2017-08-14 00:27:44
【问题描述】:
这个问题的上下文在spring-boot中,使用spring-data-jpa和hibernate。
同事写了一个@Service,并将服务方法注解为@Transactional。服务方法加载一个实体,然后点击一个一对多的延迟加载集合 (fetch = FetchType.LAZY)。服务方法由一些自定义委托人调用,我将在后面讨论。当从 @RestController 端点调用时,这可以正常工作。
当我从骆驼路由(再次通过自定义委托)调用服务时,它遇到了延迟初始化异常。
在挖掘中,发现服务实现了一个接口,自定义委托人查找服务(它被注入所以有适当的代理)并调用一个方法
在实际上是 java-8 默认方法的接口上。然后这个默认方法在本地调用@Transactional 方法。
所以有问题:- 这是一个本地方法调用,所以 @Transactional 注释的方面/代理没有完成(我们使用 aspectJAutoProxy)所以该方法不在事务中调用,所以惰性 -加载应该失败。并仔细检查,还通过@Scheduled 注释进行了尝试:相同的行为。像它应该的那样呕吐。
我的问题:那么为什么从@RestController 调用它时会起作用?这让我发疯了!
rest 控制器端点上没有事务注释。
我使用TransactionSynchronizationManager.isActualTransactionActive() 向服务添加了一些调试代码,它表明在任何情况下都不存在事务,即使通过控制器端点调用也是如此。
那么为什么延迟加载在从控制器调用时会起作用? 我转储了所有 SQL,并且在任何时候都没有加载惰性集合,因此它们不在任何休眠缓存中。
我记得有一次读到延迟加载是一个提示,而不是一个命令,但仍然......为什么它在那种情况下有效?
【问题讨论】:
-
您是否使用 Open session in View (OSIV)?
-
感谢 Ali,不使用 OSIV。有一个过滤器可以从数据库加载标头中指定的经过身份验证的用户,但该事务在休息控制器代码执行之前关闭。为了验证,服务中的 TransactionSynchronisationManager.isActualTransactionActive() 说是假的。
-
你找到答案了吗?它也困扰着我。我有一个 dao 层,我在其中加载东西,当我在控制器中迭代它时,它会延迟加载而不是失败(我想要)
-
抱歉,马里奥,一直没有时间解决这个问题。而关于 java8 默认方法的原始问题中的所有废话都与此无关。我随后在最简单的情况下遇到了同样的问题:延迟加载在不应该的情况下通过休息控制器工作;它不能通过其他代码路径工作(这很好)。
-
@MarioB 找到答案!
标签: spring hibernate spring-data-jpa