如何获得在Hibernate中使用JPA标准API摆脱N + 1

梅德Senkovich:

我是从使用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);
}

我得到正确的结果,所有的AB记录正确检索。但是,迁移之后,我的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] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

使用JPA和Hibernate加载没有N + 1笛卡尔积的递归对象图

如何获得n-1号

在Couchbase N1Ql @query中使用IN子句或使用Couchbase JPA中的findAll(keys)

如何使用Spring Data JPA + Hibernate + PostgresSQL禁用L1会话缓存

OneToOne JPA / Hibernate急于加载导致N + 1选择

Spring JPA + Hibernate OneToOne关系进行n + 1个查询

如何从 A1 Notation 获得结果并在公式中使用它?

JPQL并使用Hibernate选择1:n关系

如何使用标准偏差为(n-1)的BBands函数?

如何使用JPA从1自动生成ID?

如何摆脱eth0:1?

JPA @OneToMany 1 - 1 .. *关系

如何获得 1 小时前

获得以下形式的向量:[1,1,1,1]

R-在maxent模型中使用5倍交叉验证时,如何获得1个“摘要”预测图而不是5?

SpringRoo 2.0.RC1 - 如何在 entityFormatExpression 中使用日期日历字段并获得正确的格式

使用 1:M 关系创建 1:1

如何在实体框架中获得1:n关系

如何在Hibernate / JPA中使用@Formula

如何使用WebAPI获得像/ api / libraries / 1 / books / 2 / dosomething这样的REST API路由?q = params?

JPA Critera API联接3表获得1类型

如何使用Rust chrono获得1天的持续时间?

如何使用ElasticSearch在0和1之间获得评分?

如何在Winform应用程序中使用colorPickerUIAdv1控件在C#中使用Syncfusion来获得rgb格式的选定颜色值

如何在PHP中使用FCM HTTP v1 API

使用1:n DeleteActions

在编程中使用(a |(a + 1))

如何在Erlang中打印嵌套列表:[[1],[1、1],[1、1、1]]?

如何在Spring Boot和Couch base -N1QL查询中使用'IN'操作器