【问题标题】:How to selectively load hibernate entity while still initializing (not loading) lazy collection如何在仍然初始化(不加载)惰性集合的同时有选择地加载休眠实体
【发布时间】:2017-08-11 09:38:06
【问题描述】:

考虑遵循简单的实体模型

class Order{
  int id;
  String description;
  //one to one eager load with join column specified
  Detail details;
  //one to many lazy load with mapped by specified
  Collection<Item> items;
}

class Detail{
}

class Item{
  String name;
  //reference to order
}

现在,假设要求是通过某些标准(例如,匹配的描述)加载所有带有商品详细信息的订单。很简单,我写了一个类似“来自描述...的订单”的 hql。例如,这会加载 1000 个实体,并且项目集合是延迟加载的。我通过调用 size 在会话中强制加载它们。

这当然导致了 N+1 问题,所以我决定对项目使用批量获取。刚刚在项目集合上添加了批量大小注释,并且预期的查询要少得多。

但是,我对“详细信息”根本不感兴趣,但由于它是一对一的急切加载,因此每个订单都有一个查询来始终加载它。我只是想取消这些查询。

为了解决这个问题,我尝试在没有详细信息的情况下进行选择,但我不确定如何在查询中包含项目(集合),以便以与我选择全部相同的方式加载它(即,延迟加载,然后可以在以后的调用中利用批处理大小)。一些建议是在 where 子句中使用 join ,但这会使用空数组列表初始化我的集合(而不是像延迟加载那样使用 PersistentBag)。

寻找解决方案。

【问题讨论】:

  • 为什么不让Detail 懒加载?
  • 应用程序的其他部分依赖于默认(急切)加载。此外,使 1-1 成为延迟加载的所有解决方案都非常重要(字节码检测等),我不想冒险破坏现有代码。

标签: java hibernate jpa lazy-loading


【解决方案1】:

一种可能的解决方案如下:

  • 创建一个包含查询结果的 POJO。示例:

    public class OrderResult {
        private String description;
        private String itemName;
        // ... more fields, if any
    
        public OrderResult(String desc, String itemName) {
            this.description = desc;
            this.itemName = itemName;
        }
    
        // getters & setters
    }
    
  • 使用构造函数表达式创建 JPQL 查询:

    List<OrderResult> resultList = entityManager.createQuery("SELECT NEW OrderResult(o.description, i.name) FROM Order o JOIN o.items i where <condition>", OrderResult.class).getResultList();
    

因此,您将获得OrderResult 实例列表,其中仅包含您感兴趣的信息。

注意 1:您说的是 HQL,但 HQL 是 Hibernate 特定的遗留查询语言。由于 Hibernate 是 JPA 的实现,并且您使用 JPA 标记了您的问题,因此该解决方案也应该在您的环境中工作。

注意 2:在解决方案中,我使用所谓的 JPQL 构造函数表达式,它在 select 子句中使用 NEW 定义。 NEW 运算符的参数必须是完全限定的类名,例如,如果将 OrderResult 类放在包 com.mycompany.myproject.order 中,则表达式应如下所示:

SELECT NEW com.mycompany.myproject.order.OrderResult(...) FROM ...

注意 3:这只是为了提示您如何实现解决方案,应视为伪代码。

【讨论】:

  • 但是您的解决方案没有考虑项目集合。我想要订单详细信息中的项目,据我所知,我不能在构造函数参数中包含集合。还是我错过了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
  • 2010-11-11
  • 1970-01-01
相关资源
最近更新 更多