[英]JPA entity manager createQuery from entity, different package but same name
[英]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.