代码之家  ›  专栏  ›  技术社区  ›  Paul Adamson

如何在会话关闭后使用Hibernate访问延迟加载的字段?

  •  8
  • Paul Adamson  · 技术社区  · 17 年前

    考虑这种情况:

    • 我已通过Hibernate加载父实体
    • 父级包含子级的集合,这些子级是大的且延迟加载的
    • 当用户查看父数据时,此初始加载之后将关闭休眠会话。
    • 用户可以选择查看Lazy Children集合的内容
    • 我现在想把收藏装进去

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

    • 假设视图中的会话不是一个选项,因为只有在用户查看父级并决定查看子级之后才会获取子级集合。
    • 这是一项服务,将由基于Web和桌面的客户端远程访问。

    谢谢。

    3 回复  |  直到 17 年前
        1
  •  3
  •   zmf    17 年前

    我正在对用户所看到的内容做一些假设,但似乎您只希望在用户已经查看了父级并确实希望看到子级的情况下检索子级。

    为什么不试着打开一个新的会话,并由他们的父母来获取孩子呢?有点像…

    criteria = session.createCriteria(Child.class);
    criteria.add(Restrictions.eq("parent", parent));
    List<Child> children = criteria.list();
    
        2
  •  7
  •   Paul Adamson    17 年前

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

    此解决方案获取父实体和惰性加载字段的名称,并返回集合已完全加载的实体。

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

    因此,在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;
    }
    
        3
  •  0
  •   bwobbones    17 年前

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

    在我的工作中,我们只是通过在初始负载中初始化字段来解决这个问题,我们需要逐个实例地进行初始化。例如,在由事务包围的外观加载方法中,您可能拥有:

    public Parent loadParentWithIntent1(Long parentId)
    {
      Parent parent = loadParentFromDAO();
    
      for (Child c : parent.getChildren())
      {
        c.getField1();
      }
    }
    

    对于每个意图,我们有不同的外观要求。这基本上实现了您所需要的,因为当您以任何方式需要这些特定字段时,您都会加载它们,而这只会在加载时将它们放入会话中。