情况: "父"实体有多个"子"实体(@OneToMany, @Lazy) - 双向关系。实体上没有外键("Child#parentId")字段。
目标: 通过使用子查询检索完全加载的父集合来避免N+1问题。如果我理解子查询的理论,这是我的目标(2个结果SQL查询):
select * from Parent ...;
select * from Child where parent_id in ...;
问题1: 如何最好实现这个目标? 你能提供JPQL/HSQL和Criteria的示例吗?
问题2(额外题): API是否可以将第二个查询分成“批次” - 例如将批次限制为500:如果第一个查询加载了1000个Parents,则2a.加载500个Parents的Children,2b.加载下一个500个。
我已尝试过:
两者都会产生SQL JOINs,似乎我不能在没有JOIN的情况下使用Child的外键。
// 2nd query:
criteria
.createAlias("parent", "p")
.add(Property.forName("p.id")
.in(parentCriteria.setProjection(Projections.property("id"))))
.list();
// 2nd query (manual):
criteria
.createAlias("parent", "p")
.add(Property.forName("p.id").in(parentIdList))
.list();
更新 (2015-04-05)
我检查了这个方法,并通过提示确定它确实可以在EclipseLink中工作:
query.setHint("eclipselink.batch.type", "EXISTS");
这个链接http://blog.ringerc.id.au/2012/06/jpa2-is-very-inflexible-with-eagerlazy.html表明在Hibernate中无法实现此功能,建议手动获取。但是,我无法理解如何通过HQL或Criteria实现,特别是如何获取仅存在于数据库上的child.parent_id列而不在Entity上的值,即避免由child.parent.id引起的JOIN。