【发布时间】:2017-05-31 11:04:14
【问题描述】:
我正在使用 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;
}
生成的带有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 它执行多重选择,两者都是 EAGER 的定义)。
【问题讨论】:
-
两个查询确实具有相同的行为,至少从人员数据在两者中相同的角度来看。您是否有特定的代码有问题?
-
加载 Person 后,它必须具有有效的 Address 实例或 null。 ManyToOne 只有在使用编织创建 Address 子类时才能偷懒。您确定没有第二次查询选择地址,也许它没有记录?
-
嗨@TimBiegeleisen,是的,我有代码(模拟在那里)。遗憾的是,我无法分享代码,但我可以在我的 github 中创建一个示例并分享。
-
@KlausGroenbaek,我敢肯定。此特定结果在 Eclipse 的“显示”选项卡中重现,在“调试”期间,它适用于同一应用程序中的任何实体。
-
我用 EclipseLink 2.5.2 (JavaSE) 做了一个测试,使用 em.find() 和 em.createQuery() 没有区别,日志完全一样。您是否对两个调用都使用相同的 EntityManager,如果是,您是否记得在两者之间调用 EntityManager.clear() 来清除缓存的实体(因为我忘记了,然后查询根本没有生成 SQL)。跨度>
标签: java hibernate hibernate-entitymanager