我正在对eclipselink JPA 2进行测试,以确定一个集合的延迟加载是如何工作的。我假设,如果你加载一个实体,那么首先加载所有的eager元素,然后,在JPA会话中,当你要求它们时加载懒惰元素,或触摸它们(以某种方式参考它们,比如获取懒惰集合的大小)。我遇到的问题是:当我从会话中分离实体时,懒惰的集合被加载,并且可用,即使我没有要求它?我要么误解了JSR,要么这是eclipselink中的正常行为。从使用hibernate,我知道这不会发生。
EntityManager em = emf.createEntityManager();
AloadTest at1 = em.find(AloadTest.class, pkLazy);
serializeObject(at1,"InSessionLazy");
em.detach(at1);
em.close();
如果我在调试中运行它,并观察我的懒惰元素,我可以看到它们在我访问'at1'对象时没有加载,但是当我跨过em.detach(at1)行时,懒惰实体已加载。
我的AloadTest C.D中有一个已定义的惰性集合。如此:......
@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;
}
提前致谢,但如果我没有要求,我认为我的懒人收藏品不应该加载。
编辑:我做了你的测试詹姆斯,你对间接测试是正确的: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 [主要] INFO c.c.t.j.t.JpaI3EagerAndLazyLoadingTest - 我们在以后懒散地加载:真实
我的意思是?为什么我加载了懒惰的集合,我不要求集合,只是父实体。如果我有一个2或10个集合链,每个集合都注释为惰性集合会发生什么?我认为这将是一个相当大的开销。它在Hibernate之前从未成为问题,但由于eclipselink现在是JPA引用,我必须基于此构建解决方案。
当然可以分离对象,使其“脏”,进行一些处理并重新连接到新会话。我在更长的对话环境中思考更多,可能是无状态会话bean和网络前端?
答案 0 :(得分:2)
在查看最新的EclipseLink代码时,似乎detach()似乎不会触发延迟集合。你应该分离是否会触发它?
通常,EclipseLink允许您在关闭EntityManger后访问LAZY关系,因此即使您分离了对象,它仍然可以访问关系(除非您将其序列化)。
您可以使用
检查关系是否已实例化((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated()
在分离()调用之前和之后检查。
我不确定你为什么使用分离,这是一种非常罕见的方法,它基本上可以用来从持久化上下文中驱逐一个对象,以避免将其更改写入数据库。
答案 1 :(得分:2)
EclipseLink允许加载延迟关系,只要连接仍然可用,如下所述: http://forums.oracle.com/forums/thread.jspa?messageID=1706796