【问题标题】:Differences between JPA predicate using Entity and property使用实体和属性的 JPA 谓词之间的差异
【发布时间】:2022-01-20 04:41:18
【问题描述】:

假设我有以下实体类:

@Entity public class MyEntity {
    @Id private String id;
    @ManyToOne private MyOtherEntity myOtherEntity;
}

@Entity public class MyOtherEntity {
    @Id private String id;
    @Column private String name;
}

现在我想做一个查询来获取所有链接到某个MyOtherEntityMyEntitys,我想知道以下3个谓词之间的区别:

cb.equal(root.get(MyEntity_.myOtherEntity), myOtherEntity);
cb.equal(root.get(MyEntity_.myOtherEntity).get(MyOtherEntity_.id), myOtherEntity.getId());
cb.equal(root.get(MyEntity_.myOtherEntity).get(MyOtherEntity_.name), myOtherEntity.getName());

在每种情况下生成的 SQL 会是什么样子?哪一种效率最高?

【问题讨论】:

    标签: java hibernate jpa


    【解决方案1】:

    首先,我建议在开发过程中尝试在 Hibernate 中启用 SQL 日志记录 - 请参阅 here。了解 Hibernate 为您的 JPA 查询创建的确切语句是非常宝贵的,例如您有机会发现 N+1 查询问题、过度连接等。

    话虽如此,在您的情况下,语句应如下所示:

    • cb.equal(root.get(MyEntity_.myOtherEntity), myOtherEntity)SELECT ... FROM MyEntity WHERE MyEntity.myOtherEntity_id = ?。在这种情况下,Hibernate 通常知道优化并避免不必要的连接。

    • cb.equal(root.get(MyEntity_.myOtherEntity).get(MyOtherEntity_.id), myOtherEntity.getId()) → 应该如上;再次,Hibernate 应该知道 .get(MyOtherEntity_.id) 已经在表中并避免不必要的连接。

      我已经看到 Hibernate 按照我在上述案例中描述的方式工作。一定要启用 SQL 日志来验证,可能有您自己的用例的详细信息使其行为方式不同!

    • cb.equal(root.get(MyEntity_.myOtherEntity).get(MyOtherEntity_.name), myOtherEntity.getName()) → 肯定会创建一个连接,因为它在MyEntity 表中找不到myOtherEntity.nameSELECT ... FROM MyEntity e JOIN MyOtherEntity oe ON ... WHERE oe.name = ?

    【讨论】:

    • 哈哈,你很清楚我发现设置 SQL 日志记录很困难,因此提出了这个问题。感谢您的详细意见!
    • 是的,我知道记录日志很痛苦,但绝对值得!祝你好运:)
    猜你喜欢
    • 1970-01-01
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多