java 如何在会话关闭后使用休眠访问延迟加载的字段?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1069310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I access lazy-loaded fields after the session has closed, using hibernate?
提问by Paul Adamson
consider this scenario:
考虑这种情况:
- I have loaded a Parent entity through hibernate
- Parent contains a collection of Children which is large and lazy loaded
- The hibernate session is closed after this initial load while the user views the Parent data
- The user may choose to view the contents of the lazy Children collection
- I now wish to load that collection
- 我已经通过休眠加载了一个父实体
- 父级包含一个大且懒加载的子级集合
- 当用户查看父数据时,休眠会话在初始加载后关闭
- 用户可以选择查看lazy Children集合的内容
- 我现在希望加载该集合
What are the ways / best way of loading this collection?
加载此集合的方式/最佳方式是什么?
- Assume session-in-view is not an option as the fetching of the Children collection would only happen after the user has viewed the Parent and decided to view the Children.
- This is a service which will be accessed remotely by web and desktop based client.
- 假设 session-in-view 不是一个选项,因为只有在用户查看了 Parent 并决定查看 Children 之后才能获取 Children 集合。
- 这是一项可以通过基于 Web 和桌面的客户端远程访问的服务。
Thanks.
谢谢。
采纳答案by zmf
I'm making some assumptions about what the user is looking at, but it seems like you only want to retrieve the children if the user has already viewed the parent and really wants to see the children.
我正在对用户正在查看的内容做出一些假设,但是如果用户已经查看了父级并且真的想查看子级,您似乎只想检索子级。
Why not try opening a new session and fetching the children by their parent? Something along the lines of ...
为什么不尝试打开一个新会话并由他们的父母接孩子?类似于...
criteria = session.createCriteria(Child.class);
criteria.add(Restrictions.eq("parent", parent));
List<Child> children = criteria.list();
回答by Paul Adamson
The lazy collection can be loaded by using Hibernate.initialize(parent.getCollection()) except that the parent object needs to be attached to an active session.
除了父对象需要附加到活动会话之外,可以使用 Hibernate.initialize(parent.getCollection()) 加载惰性集合。
This solution takes the parent Entity and the name of the lazy-loaded field and returns the Entity with the collection fully loaded.
此解决方案采用父实体和延迟加载字段的名称,并返回集合完全加载的实体。
Unfortunately, as the parent needs to be reattached to the newly opened session, I can't use a reference to the lazy collection as this would reference the detached version of the Entity; hence the fieldName and the reflection. For the same reason, this has to return the attached parent Entity.
不幸的是,由于父级需要重新附加到新打开的会话,我不能使用对惰性集合的引用,因为这将引用实体的分离版本;因此 fieldName 和反射。出于同样的原因,这必须返回附加的父实体。
So in the OP scenario, this call can be made when the user chooses to view the lazy collection:
所以在OP场景下,可以在用户选择查看lazy collection时进行这个调用:
Parent parentWithChildren = dao.initialize(parent,"lazyCollectionName");
The Method:
方法:
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;
}
回答by bwobbones
Hibernate handles collections in a different way that normal fields.
Hibernate 以不同于普通字段的方式处理集合。
At my work we get around this by just initialising the fields in the initial load that we need on a case by case basis. For example, in a facade load method that is surrounded by a transaction you might have:
在我的工作中,我们通过根据具体情况在初始加载中初始化我们需要的字段来解决这个问题。例如,在一个被事务包围的外观加载方法中,你可能有:
public Parent loadParentWithIntent1(Long parentId)
{
Parent parent = loadParentFromDAO();
for (Child c : parent.getChildren())
{
c.getField1();
}
}
and we have a different facade call for each intent. This essentially achieves what you need because you'd be loading these specific fields when you need them any way and this just puts them in the session at load time.
我们对每个意图都有不同的外观调用。这基本上实现了您的需要,因为您将在需要时以任何方式加载这些特定字段,而这只是在加载时将它们放入会话中。

