分离时惰性(未加载)集合上的 JPA 调用方法在 Eclipselink 中无法按预期工作

JPA call method on lazy (not loaded) collection when detached not working as expected in Eclipselink

最近我对 JPA 进行了一些试验,以尝试更多地了解整个框架。我正在使用 Eclipselink 作为 JPA 提供程序。

我有两个具有延迟加载的 @OneToMany 关系的实体(一个人有很多地址)。

当我加载一个人实体时,将其分离,然后尝试访问(未加载的)地址……它很有魅力。调试时可以看到在执行地址列表的size()方法时执行了数据库查询。

我不明白为什么会这样。我希望有某种例外。在过去的几天里,我已经阅读了很多关于 jpa 之类的东西(即 this link),但是所有的一切都指向我的结论是它不应该工作。

任何人都可以解释为什么这样做吗?

@Stateless
public class Test {
    @PersistenceContext(unitName="TestPU") EntityManager em;

    public void test() {
        Person person = em.find(Person.class, 1);

        System.out.println(person);

        System.out.println("em.contains(person): " + em.contains(person);

        em.detach(person);

        System.out.println("em.contains(person): " + em.contains(person);

        person.getAddresses().size();

        System.out.println("em.contains(person): " + em.contains(person);

        System.out.println(person);

    }
}

生成的日志将是

DEBUG: SELECT ... from PERSON WHERE (id = ?)
Person{id=1, name=Test, addresses={IndirectList: not instantiated}}
em.contains(person): true
em.contains(person): false
DEBUG: SELECT ... FROM ADDRESSES where (address_fk = ?)
em.contains(person): false
Person{id=1, name=Test, addresses={[Address{id=10, city=Testcity}]}}

如所述here 分离从上下文中删除实体,使其不再受管理。由于上下文仍然可用,如果需要,仍然可以获取未触发的惰性集合,EclipseLink 认为这比抛出异常更有价值。这被认为是 EclipseLink 的一个特性,并且是 JPA 规范允许的,尽管其他提供者默认情况下不启用该行为。