假设项目和出价是实体:一个项目有很多出价。它们在 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();
这说明了为什么对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();