一尘不染

标准渴望获取联接集合,以避免n + 1个选择

hibernate

假设项目和出价是实体:一个项目有很多出价。它们在 Hibernate 中以典型的父/子关系映射:

<class name="Item" table="ITEM">
  ...
  <set name="bids" inverse="true">
    <key column="ITEM_ID"/>
    <one-to-many class="Bid"/>
  </set>
</class>

在执行此查询后尝试访问每个项目的出价时,如何避免n + 1个选择?

List<Item> items = session.createCriteria(Item.class)
                        .createAlias("bids", "b").
                        .add(Restrictions.gt("b.amount", 100)).
                        .list();

请注意, 我需要 急切 的竞标价格,但 对收款 要有 进一步的限制 (b.amount> 100)

我尝试了以下失败:

List<Item> items = session.createCriteria(Item.class)
                        .setFetchMode("bids", FetchMode.JOIN).
                        .createAlias("bids", "b").
                        .add(Restrictions.gt("b.amount", 100)).
                        .list();

List<Item> items = session.createCriteria(Item.class)
                        .createCriteria("bids")
                        .add(Restrictions.gt("amount", 100)).
                        .list();

阅读 232

收藏
2020-06-20

共1个答案

一尘不染

这说明了为什么对fetch-joined集合添加限制会导致集合未初始化( 请注意 ,没有限制的同一查询会为集合急切地获取数据):

“如果表A和B之间的关系为1:n,并且对B添加了限制,并且希望能尽快获取它,那么问题是当您要从A导航到B时会发生什么。只查看B中符合限制条件的数据,还是应该查看与A相关的所有B?”
在这里看到更多…

但是,使用HQL代替标准,部分获取出价集合

List<Item> items = session.createQuery(
          "from Item i left join fetch i.bids b where b.amount > :amount")
          .setParameter("amount", 100)
          .list();

在我看来,这是不一致的,但这就是它的工作原理

顺便说一句,如果您需要的是父母及其所有子女的清单,而仅是其子女都满足一定限制的父母,那么您可以使用此清单

List<Item> items = session.createQuery(
          "from Item i left join fetch i.bids b " +
          "where not exists (from Bid b where b.item = i and b.amount <= :amount)")
          .setParameter("amount", 100)
          .list();
2020-06-20