繁体   English   中英

使用来自Hibernate实体管理器的find和createQuery的不同SQL

[英]Different SQL using find and createQuery from Hibernate entity manager

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

我注意到, entityManager.createQuery无法解析我的实体的EAGER关系,而entityManager.find无法解决。

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

@Entity
public class Person {

     @Id
     private int id;

     private String name;

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

}

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

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=?

以及使用entityManager.createQuery("SELECT p FROM Person where id = 1")生成的SQL:

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提取,而createQuery则进行多次选择,从定义createQuery都是EAGER )。

我查看了您的示例,并对其进行了修复,其工作原理与HiberNate 5.2.5 find()使用createQuery并且createQuery使用多个选择一样。

在您的示例中看不到该信息的原因是因为您的数据库中没有DATA ,find仍然进行联接,但是由于DB中没有Person,因此不需要查找任何Address,因此第二选择丢失。

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

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

自2009年以来,我已经广泛使用了JPA,一开始我犯了很多错误,因为我不完全了解持久性上下文是什么,所以我有重叠的EntityManager,未维护的双向关系,而且我还没有完全理解实体状态,或容器与应用程序托管的EntityManager。 我从中学到了很多困难的方法(对我来说,这是调试和阅读EclipseLink源代码)。 回顾过去,我绝对应该买一本书以获取全局,而不是通过随机搜索我所遇到的问题来解决问题。 对于没有读过JPA文档,一本好书或一篇专业文章的人,请帮自己一个忙,并从我的错误中学习。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM