我正在关注 hibernate documentation用于与连接表的一对多和多对一单向关联。
我尝试通过创建 Person & Address 实体来实现一个简单的示例,如下所示:
Person has an id and name property with setters & getters
Address has an id and name property with setters & getters
我在一对多和多对一的文档中给出了相同的映射文件。然后我创建了一个小程序来获取 Person
实体和相应的 Address
实体,如下所示:
对于一对多
:
for (Person person : list) {
System.out.println(person.getId());
for (Address address : person.getAddresses()) {
System.out.println(address);
}
}
对于此 hibernate 生成以下查询:
Hibernate: select person0_.personId as personId1_1_
from Person person0_
Hibernate: select addresses0_.personId as personId1_1_0_, addresses0_.addressId as addressId2_2_0_, address1_.addressId as addressId1_0_1_
from PersonAddress addresses0_
inner join Address address1_
on addresses0_.addressId=address1_.addressId
where addresses0_.personId=?
对于多对一
:
List<Person> list = session.createQuery("from Person").list();
for (Person person : list) {
System.out.println(person.getId());
System.out.println(person.getAddress());
}
Hibernate: select person0_.personId as personId1_1_, person0_.name as name2_1_, person0_1_.addressId as addressId2_2_
from Person person0_
left outer join PersonAddress person0_1_
on person0_.personId=person0_1_.personId
Hibernate: select address0_.addressId as addressId1_0_0_, address0_.name as name2_0_0_
from Address address0_
where address0_.addressId=?
从生成的查询中,对于一对多
,最初的查询是从Person
表中获取记录以获取所有人员,然后获取它具有的地址 JOIN PersonAddress
和 Address
之间。
对于 many-to-one
最初它在 PersonAddress
和 Address
之间有 LEFT OUTER JOIN 以获得 Person
记录,然后它会访问 Address
表以从 Address
表中获取记录。
所以我怀疑为什么多对一
案例没有遵循一对多
的相同方法,只命中Person
表,因为最初我试图在我的 HQL 中只获取 Person 实体。请帮助我理解这一点。
最佳答案
对于 OneToMany 的情况,一个人有一个地址集合。该集合可以有 0 个、一个或多个地址。这个集合是懒惰地填充的。因此,当从数据库中加载一个人时,将执行第一个查询以获取该人的字段(姓名等)。 Hibernate 还不知道这个人是否有地址,它不关心。它将地址集合设置为惰性集合。第一次在此惰性集合上调用方法时,将执行第二个查询以加载人员的所有地址并填充集合。
对于 ManyToOne 的情况,一个人有一个 Address 类型的字段地址。当你加载一个人的时候,Hibernate 应该把这个字段初始化成什么。如果它将它设置为 null 并且您询问地址,它会返回 null,即使此人有地址,这是错误的。如果它将其设置为惰性地址代理并且您请求地址,即使此人没有地址,它也会返回非空代理,这也是错误的。所以 Hibernate 必须知道此人是否有地址。如果没有,则将字段设置为空。如果有,它将地址设置为地址代理。这就是执行附加左外连接的原因:了解此人是否有地址(以及该地址的 ID 是什么,如果有的话)。
关于java - 了解为 Join 表上的一对多和多对一生成的查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25756361/