【发布时间】:2012-01-19 09:42:01
【问题描述】:
我正在 eclipselink JPA 2 上运行测试,以确定延迟加载集合的工作方式。我假设,如果你加载一个实体,那么首先加载所有急切的元素,然后在 JPA 会话中,当你请求它们或触摸它们时加载惰性元素(以某种方式引用它们,就像获取惰性集合的大小一样)。我遇到的问题是:当我从会话中分离实体时,延迟集合被加载,并且可用,即使我没有要求它?我要么误解了 JSR,要么这是 eclipselink 中的正常行为。通过使用休眠,我知道这不会发生。
EntityManager em = emf.createEntityManager();
AloadTest at1 = em.find(AloadTest.class, pkLazy);
serializeObject(at1,"InSessionLazy");
em.detach(at1);
em.close();
如果我在调试中运行它,并观察我的惰性元素,我可以看到当我访问我的“at1”对象时它们没有加载,但是当我越过 em.detach(at1) 行时,惰性元素实体已加载。
我的 AloadTest CD 中有一个已定义的惰性集合。像这样:...
@OneToMany(fetch = javax.persistence.FetchType.LAZY, cascade = CascadeType.PERSIST, /*, cascade = CascadeType.ALL, */mappedBy = "aloadtest")
public Set<CloadLazyMultitest> getCloadLazyMultitest() {
return cloadLazyMultitest;
}
public void setCloadLazyMultitest(Set<CloadLazyMultitest> cloadLazyMultitest) {
this.cloadLazyMultitest = cloadLazyMultitest;
}
提前致谢,但如果我没有要求,我认为不应该加载我的惰性集合。
编辑:我做了你的测试 James,你对间接测试是正确的:
logger.info(" ARE WE LAZY LOADED BEFORE :"+((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated());
em.detach(at1);
logger.info(" ARE WE LAZY LOADED AFTER :"+((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated());
我的记录器的输出:
17:14:16.707 [main] INFO c.c.t.j.t.JpaI3EagerAndLazyLoadingTest - ARE WE LAZY LOADED BEFORE :false
17:14:16.723 [main] 信息 c.c.t.j.t.JpaI3EagerAndLazyLoadingTest - 我们是否延迟加载:true
我的意思是?为什么我要加载惰性集合,我不要求集合,只要求父实体。如果我有 2 或 10 个集合链,每个集合都注释为惰性集合,会发生什么?我认为这将是一个相当大的开销。在 Hibernate 之前它从来都不是问题,但是由于 eclipselink 现在是 JPA 参考,我必须基于此构建一个解决方案。
当然可以分离对象,使其“脏”,进行一些处理并重新附加到新会话。我在“长时间对话”环境中思考更多,可能是无状态会话 bean 和网络前端?
【问题讨论】:
-
你确定不是调试器在你背后调用你集合的方法(例如它的 toString 方法)? serializeObject 方法有什么作用?
-
序列化对象直接序列化我的对象,当我反序列化这个对象时,它不包含延迟加载的集合,这与预期的一样。它不是调试器,因为我在后面的代码中循环分离的对象,并且加载了集合。 IE。这种自动加载集合的行为发生在我通过调试器发送它之前。
标签: jpa eclipselink