gpt4 book ai didi

java - 使用 Hibernate 实体管理器中的 find 和 createQuery 的不同 SQL

转载 作者:行者123 更新时间:2023-11-30 02:41:04 25 4
gpt4 key购买 nike

我正在使用 Hibernate 3.3.0.GA,我注意到一些奇怪的行为,但没有记录(我认为)。

我注意到entityManager.find解决EAGER我的实体与 entityManager.createQuery 的关系不是。

例如,如果我有一个实体:

@Entity
public class Person {

@Id
private int id;

private String name;

@ManyToOne //EAGER by default in JPA
private Address address;

}

生成的 SQL entityManager.find(Person.class, 1L) :

select
person0_.id as id1_1_,
person0_.address_id as address3_1_1_,
person0_.name as name1_1_,
address1_.id as id2_0_
from
Person person0_
left outer join
Address address1_
on person0_.address_id=address1_.id
where
person0_.id=?

生成的 SQL 为 entityManager.createQuery("SELECT p FROM Person where id = 1") :

select
person0_.id as id1_,
person0_.address_id as address3_1_,
person0_.name as name1_
from
Person person0_
where
person0_.id=?

那么,有没有关于为什么会发生这种情况的解释?对我来说,两者都需要具有相同的行为。

工作示例

我在我的存储库中创建了一个示例,使用 Hibernate 4.1.6.Final 显示该问题:https://github.com/dherik/hibernate-find-em-so-question 。只需使用 mvn clean install控制台将打印查询。

已更新

@KlausGroenbaek 表示 EclipseLink 2.5.2 在这两种方法中具有相同的行为。他也做了一个 Hibernate 示例,并在两种方法中获得了类似的结果( find 它执行连接获取, createQuery 它执行多个选择,根据定义都是 EAGER )。

最佳答案

我查看了您的示例,修复后,它的工作方式与 HiberNate 5.2.5 find() 使用连接和 createQuery 使用多个选择完全相同。

您在示例中没有看到这一点的原因是因为数据库中没有数据,find 仍然会执行连接,但因为数据库中没有 Person,所以不会。不需要查找任何地址,因此第二个选择丢失。

但是,您会注意到,即使您将数据添加到示例中,选择的地址也不会显示。这是因为当您使用 find() 时,该地址已经在持久性上下文中,因此无需再次加载它 - 事实上,JPA 必须为该地址返回完全相同的 Java 实例,如果它已经加载到持久性上下文中。如果您插入 em.clear() 或使用不同的持久性上下文 (EntityManager),您将看到选择,因为地址尚未加载。

您的示例只是一个示例,但是绝对禁止在字段中存储应用程序管理的 EntityManager 的方式,当您自己管理它们时,它们应该始终是局部变量。如果您使用容器管理的 EntityManager (Spring JavaEE),则在使用 @PersistenceContext 注入(inject)时它们可以是字段,但这只是因为注入(inject)的 EntityManager 是存储状态的代理,它是 ThreadLocal。

我从 2009 年开始广泛使用 JPA,一开始我犯了很多错误,因为我不明白 Persistence Context 到底是什么,所以我有重叠的 EntityManager,未维护的双向关系,而且我没有完全理解了解实体状态,或容器与应用程序管理的 EntityManager。其中大部分是我通过艰难的方式学到的(对我来说就是调试和阅读 EclipseLink 源代码);回想起来,我绝对应该买一本书来了解全局,而不是通过随机谷歌搜索我认为问题所在来解决问题。对于任何没有阅读过 JPA 文档、一本好书或部门文章的人,请帮自己一个忙,并从我的错误中学习。

关于java - 使用 Hibernate 实体管理器中的 find 和 createQuery 的不同 SQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41679264/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com