与我的相关 先前的问题, ,我想确保加载所有子对象,因为我有多个线程可能需要访问数据(从而避免延迟加载异常)。我知道执行此操作的方法是在查询(EJB QL)中使用“fetch”关键字。像这样:

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

假设模型具有 Order 类有一组 OrderLines 在里面。

我的问题是,似乎需要“distinct”关键字,否则我似乎会得到一个 Order 对于每个 OrderLine. 。我做的事正确吗?

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

有帮助吗?

解决方案

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

如果没有映射,我不确定我是否理解您的问题。对于您描述的用例,左连接获取应该是您所需要的。当然,如果订单行有一个订单作为其父级,您将获得每个订单行的订单。

其他提示

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

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

@OneToMany(fetch=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.eger。这意味着它总是渴望的,尤其是网络前端加载了一切 - 但是也许这是您要做的,这是您所做的吗?我似乎还记得我们以前尝试过,然后变得非常缓慢的网页 - 但这也许意味着我们应该使用二级缓存?

如果您仍然感兴趣,我在这个帖子中回答了类似的问题 如何序列化hibernate集合.

基本上你使用一个名为 推土机 它将 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 在上线时可能有不同的看法......

我还重新设计了一些东西,以便数据库工作位于主线程上并具有实体管理器。

克里斯

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

     <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top