Hibernate(JPA)如何做一个急切的查询,加载所有子对象

关于我之前的问题 ,我想确保所有子对象都被加载,因为我有一个可能需要访问数据的多个线程(因此避免了延迟加载exception)。 我理解这样做的方法是在查询中使用“fetch”关键字(EJB QL)。 喜欢这个:

select distinct o from Order o left join fetch o.orderLines 

假设一个具有Order类的模型,其中包含一组OrderLines

我的问题是似乎需要“distinct”关键字,否则我似乎会收到每个OrderLineOrder 。 我做对了吗?

也许更重要的是,有没有办法拉入所有儿童物品,无论多深? 我们有大约10-15个类,对于服务器,我们将需要所有加载…我避免使用FetchType.EAGER因为这意味着它总是渴望,特别是Web前端加载一切 – 但也许这是要走的路 – 那是你做的? 我似乎记得我们之前尝试过这个,然后得到非常慢的网页 – 但也许这意味着我们应该使用二级缓存?

改变注释是一个坏主意IMO。 因为它不能在运行时更改为惰性。 最好让一切都变得懒惰,并根据需要进行获取。

没有映射,我不确定我是否理解你的问题。 左连接提取应该是您描述的用例所需的全部内容。 如果订单行有一个订单作为其父订单,您当然会收到每个订单行的订单。

我不确定在EJBQL中使用fetch关键字,您可能会将其与注释混淆…

您是否尝试将FetchType属性添加到关系属性中?

@OneToMany(取= FetchType.EAGER)?

看到:

http://java.sun.com/javaee/5/docs/api/javax/persistence/FetchType.html http://www.jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

你尝试过使用结果变换器吗? 如果使用Criteria查询,则可以应用结果转换器(尽管分页和结果转换器存在一些问题 ):

 Criteria c = ((Session)em.getDelegate()).createCriteria(Order.class); c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); c.list(); 

em.getDelegate()是一个只在你使用hibernate时才有效的hack。

也许更重要的是,有没有办法拉入所有儿童物品,无论多深? 我们有大约10-15个类,对于服务器,我们将需要所有加载…我避免使用FetchType.EAGER,因为这意味着它总是渴望,特别是Web前端加载一切 – 但也许这是要走的路 – 那是你做的? 我似乎记得我们之前尝试过这个,然后得到非常慢的网页 – 但也许这意味着我们应该使用二级缓存?

如果你仍然感兴趣,我在这个post中回答了一个类似的问题, 如何序列化hibernate集合 。

基本上,您使用一个名为dozer的实用程序将bean映射到另一个bean,并通过这样做触发所有延迟加载。 可以想象,如果所有集合都被热切地提取,这样会更好。

您可以使用(分离的)条件查询执行类似的操作,并设置获取模式。 例如,

 Session s = ((HibernateEntityManager) em).getSession().getSessionFactory().openSession(); DetachedCriteria dc = DetachedCriteria.forClass(MyEntity.class).add(Expression.idEq(id)); dc.setFetchMode("innerTable", FetchMode.JOIN); Criteria c = dc.getExecutableCriteria(s); MyEntity a = (MyEntity)c.uniqueResult(); 

这只适用于ManyToOne关系,对于他们来说@ManyToOne(fetch = FetchType.EAGER)可能是合适的。

急切地获取多个OneToMany关系是不鼓励和/或不起作用,因为您可以阅读Jeremy发布的链接。 只要想想进行这样一次获取所需的SQL语句……

我所做的是重构代码以保持对象映射到实体管理器,每次我需要刷新时,关闭对象的旧实体管理器并打开一个新对象。 我使用上面的查询而没有获取,因为这对我的需求来说太深了 – 只需在OrderLines中进行普通连接 – 获取使得它更深入。

我只需要几个对象,大约20个,所以我认为拥有20个开放实体管理器的资源开销不是问题 – 尽管DBA在生效时可能有不同的视图……

我还重新处理了一些事情,以便db工作在主线程上并具有实体管理器。

克里斯

如果问题只是LazyInitializationExceptions,则可以通过添加OpenSessionInViewFilter来避免这种情况。
这将允许在视图中加载对象,但无法解决速度问题。

   hibernateFilter  org.springframework.orm.hibernate3.support.OpenSessionInViewFilter    hibernateFilter /*  
Interesting Posts