Eclipselink 延迟加载
我正在 eclipselink JPA 2 上运行测试,以确定集合的延迟加载如何工作。我假设,如果您加载一个实体,那么首先加载所有急切元素,然后,在 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 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;
}
提前致谢,但我认为如果我没有要求的话,不应该加载我的惰性集合。
编辑:我做了你的测试詹姆斯,你对间接测试的看法是正确的:
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] INFO cctjtJpaI3EagerAndLazyLoadingTest - ARE WE LAZY LOADED AFTER :true
我的观点是?为什么我会加载惰性集合,我不要求集合,只要求父实体。如果我有一个包含 2 个或 10 个集合的链,每个集合都注释为惰性集合,会发生什么?我认为这将是一笔相当大的开销。以前使用 Hibernate 从来都不是问题,但由于 eclipselink 现在是 JPA 参考,我必须基于此构建一个解决方案。
当然,可以分离一个对象,使其变得“脏”,进行一些处理并重新附加到新会话。我在“长时间对话”环境中思考更多,可能是无状态会话 bean 和 Web 前端?
I am running a test on eclipselink JPA 2, to determine how lazy loading of a collection is working. I have assumed, the if you load an entity, then all eager elements are loaded first of all, then, within the JPA session, the lazy elements are loaded when you ask for them, or touch them (refer to them in some way, like getting the size of a lazy collection). The problem I have is this: when I detach the entity from the session, the lazy collection is loaded, and is available, even though I didn't ask for it?? I either mis-understand the JSR, or this is normal behaviour in eclipselink. From using hibernate, I know this does not happen.
EntityManager em = emf.createEntityManager();
AloadTest at1 = em.find(AloadTest.class, pkLazy);
serializeObject(at1,"InSessionLazy");
em.detach(at1);
em.close();
If I run this in a debug, and watch my lazy elements, I can see they are not loaded when I access my 'at1' object, but the minute I step over the em.detach(at1) line, the lazy entities are loaded.
I have a defined lazy collection in my AloadTest C.D. as such:...
@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;
}
Thanks in advance, but I do not think my lazy collection should be loaded if I havent asked for it.
EDIT: I did your test James, and your are correct about the indirection test:
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());
And the output to my logger:
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 - ARE WE LAZY LOADED AFTER :true
My point is? why am I getting lazy collections loaded, I dont ask for the collection, just the parent entity. What would happen if I had a chain of 2 or 10 collections, each annotated as a lazy collection? I think it would be quite an overhead. Its never been an issue before with Hibernate, but as eclipselink is now the JPA refernce, I have to build a solution based on this.
Surely its ok to detach an object, to make it 'dirty', do some processing and re-attach to a new session. I am thinking more in a 'long conversation' environment, probably stateless session beans and a web front?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在查看最新的 EclipseLink 代码时,似乎 detach() 不会触发惰性集合。你应该分离触发它吗?
一般来说,EclipseLink 允许您在关闭 EntityManger 后访问 LAZY 关系,因此即使您分离了对象,它仍然可以访问关系(除非您序列化它)。
该关系是否已实例化
您可以使用在 detach() 调用之前和之后检查
。我不确定您为什么要使用分离,这是一种非常罕见的方法,它基本上可用于从持久性上下文中驱逐对象,以避免其更改被写入数据库。
In looking at the latest EclipseLink code, it doesn't seem like detach() will trigger the lazy collection. Are you should detach is triggering it?
In general EclipseLink allows you to access LAZY relationships after closing the EntityManger, so even though you detached the object, it will still have access to the relationships (unless you serialize it).
You can check if the relationship is instantiated using,
Check this before and after the detach() call.
I'm not sure why you are using detach, it is a pretty rare method, it basically can be used to expel an object from the persistence context to avoid its changes being written to the database.
只要连接仍然可用,EclipseLink 就允许加载惰性关系,如下所述:
http://forums.oracle.com/forums/thread.jspa?messageID=1706796
EclipseLink allows loading lazy relationships as long as the connection is still available, as described here:
http://forums.oracle.com/forums/thread.jspa?messageID=1706796