【问题标题】:Eclipselink Lazy LoadingEclipselink 延迟加载
【发布时间】: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


【解决方案1】:

在查看最新的 EclipseLink 代码时,似乎 detach() 不会触发惰性收集。你应该分离触发它吗?

一般而言,EclipseLink 允许您在关闭 EntityManger 后访问 LAZY 关系,因此即使您分离了对象,它仍然可以访问这些关系(除非您将其序列化)。

你可以检查关系是否被实例化,

((IndirectSet)at1.getCloadLazyMultitest()).isInstantiated()

在 detach() 调用之前和之后检查这个。

我不知道你为什么要使用分离,这是一种非常少见的方法,它基本上可以用来从持久化上下文中驱逐一个对象,以避免将其更改写入数据库。

【讨论】:

  • 您好,我在独立的 J2SE 环境中使用 detach 方法来评估 eclipselink 对于即将到来的项目的优点。我想我们将使用无状态会话 bean 来访问真实环境中的对象。
  • 我的老板给了我一个清单,我正在勾选它们,LazyLoad 测试说我应该获取一个会话,获取一个对象,分离对象,查询惰性集合,它应该抛出一个错误。
  • 嗨,James,我对您进行了间接测试,并编辑了原始问题。
【解决方案2】:

只要连接仍然可用,EclipseLink 就允许加载惰性关系,如下所述: http://forums.oracle.com/forums/thread.jspa?messageID=1706796

【讨论】:

  • 嗨,克里斯,我阅读了链接,但即使您没有要求,IE 也延迟加载集合似乎仍然很奇怪。在分离点。
  • 您的实体是否实现了访问惰性关系的 toString 方法?这会导致它在启用日志记录时被触发,一般不推荐。
  • 嗨,克里斯,不,我不会覆盖 toString(),也不会在测试用例以外的任何地方打印出惰性集合的内容。
  • 只要连接可用,什么意思?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 2013-09-15
  • 2015-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多