JPA 延迟加载的 ManyToOne 关系何时可以在事务之外加载?

When can a JPA lazy-loaded ManyToOne relationship be loaded outside of a transaction?

我有一个 JAX-RS 资源 class。它调用加载实体的无状态 EJB(我们称之为 Parent)。

Parent 与另一个实体(我们称之为 Child)有 @ManyToOne 关系,并且配置为具有 LAZY.[=25= 的获取类型]

没有额外的事务注释出现在任何东西上,因此无状态 EJB 具有在必要时启动事务并在其业务方法完成后提交事务的默认行为。

在调试器中,我观察到 EJB 返回的 Parent 具有 null 作为 Child 的值,正如我所怀疑的那样。因此延迟加载工作正常。

我的资源 class 然后构建一个 Response 并将控制权移交给 JAX-RS 内部。同样,没有交易打开。

序列化后,显示的 JSON(在我的例子中)包含 Child 的所有字段。 JAX-RS 内部的某些东西在某种程度上 "inflating" Child 在事务之外引用。

我在调试器中观察到,在 JAX-RS 接管控制之后的某个时刻,Child 引用确实变成了非 null.

我认为 Child 应该保留 null 或者应该抛出某种异常以表明有人试图访问延迟加载的字段。显然我误解了什么。

在什么情况下,分离的 JPA 实体可以在事务之外拥有其延迟加载的关系"inflated"?

如果重要的话,我将通过 Glassfish 4.1 和 EclipseLink 2.5.2(再次通过 Glassfish 4.1)使用 Jersey 2.10.4。

如果它真的是 "detached" 则没有上下文,因此没有加载。如果它仍在上下文中,那么显然它可以加载字段。这是根据 JPA 规范。

当然,除非您正在使用某些特定于供应商的选项,否则您没有遵循 JPA 规范,因此不能在任何其他 JPA 实现中依赖它...

如果您只是读取实体,则无需启动事务。例如下面的代码不需要事务:​​

ParentEntity pe = entityManager.find(ParentEntity.class,1);
List<ChildEntity> childs = pe.getChildList();
System.out.println(childs.size());

但是,请记住,只要您在事务之外,就无法保留对这些实体的任何更改。