使用 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 = ?
假设我有以下实体 类:
@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 = ?