Eclipselink Lazy Loading
我正在eclipselink JPA 2上运行测试,以确定集合的延迟加载的工作方式。我假设,如果您加载一个实体,那么首先会加载所有渴望的元素,然后在JPA会话中,当您请求或触摸它们时会加载惰性元素(以某种方式引用它们,例如获取懒惰的收藏的大小)。我的问题是这样的:当我从会话中分离实体时,即使我没有要求,延迟集合也会被加载并且可用。我或者误解了JSR,或者这是eclipselink中的正常行为。通过使用hibernate模式,我知道这不会发生。
1 2 3 4 5 6 7 | 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中有一个已定义的惰性集合。像这样:...
1 2 3 4 5 6 7 | @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进行了测试,您对间接测试是正确的:
1 2 3 4 5 | 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()); |
输出到我的记录器:
1 | 17:14:16.707 [main] INFO c.c.t.j.t.JpaI3EagerAndLazyLoadingTest - ARE WE LAZY LOADED BEFORE :false |
17:14:16.723 [main] INFO c.c.t.j.t.JpaI3EagerAndLazyLoadingTest-在:true
之后我们是否延迟加载
我的意思是?为什么我要加载惰性集合,我不要求集合,仅是父实体。如果我有2个或10个集合的链,每个集合都标注为惰性集合,会发生什么情况?我认为这将是相当大的开销。 Hibernate以前从来都不是问题,但是由于eclipselink现在是JPA的引用,因此我必须基于此构建解决方案。
当然可以分离对象,使其变得"脏",进行一些处理并将其重新连接到新会话。我在"长期对话"环境中考虑更多问题,可能是无状态会话bean和Web前端?
在查看最新的EclipseLink代码时,似乎detach()不会触发惰性集合。您是否应该分离触发它?
通常,EclipseLink允许您在关闭EntityManger之后访问LAZY关系,因此,即使您分离了该对象,它仍然可以访问这些关系(除非您对其进行序列化)。
您可以使用
检查是否实例化了关系
1 | ((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated() |
在detach()调用之前和之后进行检查。
我不确定为什么要使用分离,这是一种非常罕见的方法,它基本上可以用于从持久性上下文中删除对象,以避免将其更改写入数据库。
EclipseLink允许在连接仍然可用时加载惰性关系,如此处所述:
http://forums.oracle.com/forums/thread.jspa?messageID=1706796