我是从使用Hibernate API的标准向JPA标准API迁移我们的DAO。我有几个类@ManyToOne
有:
@Entity
@Table(name = "A_TABLE", schema="SCHEMA_NAME")
public class A {
@ManyToOne
@JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '1' OR B.B_CODE = '2') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
private B b1;
@ManyToOne
@JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '3' OR B.B_CODE = '4') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
private B b2;
...
}
@Entity
@Table(name = "B_TABLE", schema="SCHEMA_NAME")
public class B {
}
在查询中我使用JoinType.LEFT
,以摆脱默认生成的CROSS JOIN
的:
if (LEFT_OUTER_JOIN_ENTITIES.contains(field)) {
path = ((From) path).join(field, JoinType.LEFT);
} else {
path = path.get(field);
}
我得到正确的结果,所有的A
和B
记录正确检索。但是,迁移之后,我的N + 1问题:所有的B
记录都检索一个接一个,尽管使用LEFT OUTER JOIN
的中生成的查询。先前(使用休眠标准API时)休眠能够满足查询,而无需在生成的SQL同一连接的n + 1。
谢谢你的任何想法和帮助!
UPDATE作为使用的一个例子if-else
是“b1.fieldName”上述搜索我会得到如下:
criteriaBuilder.equal(root.join("b1", JoinType.LEFT).get("someFiled"), 42)
在N + 1的问题来自于默认EAGER抓取策略的的@ManyToOne
关联。
所以,你需要切换到FetchType.LAZY
,像这样:
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '1' OR B.B_CODE = '2') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
private B b1;
@ManyToOne(fetch = FetchType.LAZY)
@JoinFormula("(SELECT * FROM (SELECT B.B_ID FROM SCHEMA_NAME.B_TABLE B WHERE B.A_ID = B_ID AND (B.B_CODE = '3' OR B.B_CODE = '4') ORDER BY B.B_CREATED_TIMESTAMP DESC) WHERE ROWNUM = 1)")
private B b2;
如果你想自动自动检测N + 1个问题可能会影响应用程序的其他部分,看看这篇文章。
如果您需要与标准API预先抓取,那么你应该使用fetch
代替join
。
if (LEFT_OUTER_JOIN_ENTITIES.contains(field)) {
path = ((From) path).fetch(field, JoinType.LEFT);
} else {
path = path.get(field);
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句