使用 Entity 和 属性 的 JPA 谓词之间的差异

Differences between JPA predicate using Entity and property

假设我有以下实体 类:

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

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

现在我想查询所有MyEntity链接到某个MyOtherEntity,我想知道以下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 看起来如何?哪个最有效?

首先,我建议不厌其烦地在开发时启用 SQL 登录 Hibernate - 请参阅 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) 已经在 table 中并避免不必要的连接。

    我已经看到 Hibernate 以我为上述情况描述的方式工作。绝对启用 SQL 日志记录来验证,可能有您自己的用例的详细信息使其以不同的方式运行!

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