延迟加载有效,但不应该

时间:2017-03-22 03:46:22

标签: spring hibernate spring-data-jpa

这个问题的上下文在spring-boot中,使用spring-data-jpa和hibernate。

一位同事写了@Service并用@Transactional注释了服务方法。服务方法加载实体,然后命中一对多延迟加载的集合(fetch = FetchType.LAZY)。服务方法由一些自定义委托者调用,我将回过头来。从@RestController端点调用时,此工作正常。

当我从camel路由(再次通过自定义委托者)调用服务时,它会使用延迟初始化异常进行禁止。

在挖掘时,发现该服务实现了一个接口,自定义委托者查找该服务(它被注入以便具有适当的代理)并调用方法 在接口上实际上是一个java-8默认方法。然后,此默认方法在本地调用@Transactional方法。

因此存在问题: - 这是一个LOCAL方法调用,因此@Transactional注释的方面/代理未完成(我们使用aspectJAutoProxy),因此该方法不会在事务,所以延迟加载应该失败。并仔细检查,也通过@Scheduled注释尝试了它:相同的行为。 Barfs喜欢它。

我的问题:那么为什么从@RestController调用时它会起作用?这让我疯了!

其余控制器端点上没有事务性注释。

我使用TransactionSynchronizationManager.isActualTransactionActive()向服务添加了一些调试代码,它表明在任何情况下都没有事务,即使通过控制器端点调用也是如此。

那么为什么从控制器调用时延迟加载会起作用? 我抛弃了所有SQL,并且在任何时候都没有加载lazy-collection,因此它们不在任何休眠缓存中。

我记得曾经读过懒惰加载是一个提示,而不是一个命令,但仍然......为什么它会在那个案例中起作用?

2 个答案:

答案 0 :(得分:1)

经过多次困惑之后,他们偶然发现了答案:

sprint-boot通过OpenEntityManagerInView拦截器在我们的背后做一个开放的实体管理器。不知道这是怎么回事。

请参阅Vlad Mihalcea https://stackoverflow.com/a/48222934/208687

的优秀答案

答案 1 :(得分:0)

当你的方法在返回方法之后注释到事务性hibernate会话关闭时,如果从方法返回的对象有懒惰,懒惰属性没有加载,你得到会话关闭的异常。您可以在查询中使用fetch或使用OSIV

相关问题