10

考虑这种情况:

  • 我已经通过休眠加载了一个父实体
  • Parent 包含一个很大且延迟加载的 Children 集合
  • 在用户查看父数据时,在此初始加载后关闭休眠会话
  • 用户可以选择查看lazy Children集合的内容
  • 我现在希望加载该集合

加载此集合的方式/最佳方式是什么?

  • 假设 session-in-view 不是一个选项,因为只有在用户查看了 Parent 并决定查看 Children 之后才会获取 Children 集合。
  • 这是一项服务,可通过基于 Web 和桌面的客户端远程访问。

谢谢。

4

3 回答 3

10

可以使用 Hibernate.initialize(parent.getCollection()) 加载惰性集合,但需要将父对象附加到活动会话。

此解决方案采用父实体和延迟加载字段的名称,并返回完全加载集合的实体。

不幸的是,由于父需要重新附加到新打开的会话,我不能使用对惰性集合的引用,因为这将引用实体的分离版本;因此 fieldName 和反射。出于同样的原因,这必须返回附加的父实体。

所以在OP场景下,可以在用户选择查看惰性集合时进行这个调用:

Parent parentWithChildren = dao.initialize(parent,"lazyCollectionName");

方法:

public Entity initialize(Entity detachedParent,String fieldName) {
    // ...open a hibernate session...
    // reattaches parent to session
    Entity reattachedParent = (Entity) session.merge(detachedParent); 

    // get the field from the entity and initialize it
    Field fieldToInitialize = detachedParent.getClass().getDeclaredField(fieldName);
    fieldToInitialize.setAccessible(true);
    Object objectToInitialize = fieldToInitialize.get(reattachedParent);

    Hibernate.initialize(objectToInitialize);
    return reattachedParent;
}
于 2009-07-01T14:35:29.397 回答
3

我正在对用户正在查看的内容做出一些假设,但似乎您只想在用户已经查看过父级并且真的想要查看子级时才想检索子级。

为什么不尝试打开一个新会话并由其父级获取子级?类似于...的东西

criteria = session.createCriteria(Child.class);
criteria.add(Restrictions.eq("parent", parent));
List<Child> children = criteria.list();
于 2009-07-01T14:20:23.297 回答
0

Hibernate 以与普通字段不同的方式处理集合。

在我的工作中,我们通过根据具体情况初始化我们需要的初始加载中的字段来解决这个问题。例如,在一个被事务包围的外观加载方法中,您可能有:

public Parent loadParentWithIntent1(Long parentId)
{
  Parent parent = loadParentFromDAO();

  for (Child c : parent.getChildren())
  {
    c.getField1();
  }
}

我们对每个意图都有不同的外观调用。这基本上可以满足您的需求,因为您会在需要时加载这些特定字段,而这只是在加载时将它们放入会话中。

于 2009-07-01T14:36:31.940 回答