【发布时间】:2015-06-03 23:51:19
【问题描述】:
情况:“父”实体有多个“子”实体(@OneToMany、@Lazy)——双向关系。实体上没有外键(“Child#parentId”)字段。
目标:通过使用子选择检索完全加载的父集合来避免 N+1 问题。如果我了解 Subselect 的理论,这就是我的目标(2 个结果 SQL 查询):
select * from Parent ...;
select * from Child where parent_id in ...;
问题 1:实现这一目标的最佳做法是什么?您能否提供 JPQL/HSQL 和 Criteria 的示例?
问题 2(奖励):API 能否将第二个查询划分为“批次” - 例如将批次限制为 500:如果第一个查询加载 1000 个父母,则为 2a。为 500 位父母加载儿童,2b。加载下一个 500。
我试过了:
两者都会导致 SQL JOIN,看来我不能在没有 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 列。也就是说,避免由 child.parent.id 导致的 JOIN。
【问题讨论】:
标签: java hibernate jpa eclipselink jpa-2.0