我正在关注hibernate documentation与关联表的一对多和多对一的单向关联。
我试图通过创建Person& amp;来实现一个简单的例子。像这样的地址实体:
Person has an id and name property with setters & getters
Address has an id and name property with setters & getters
我在文档中给出了相同的映射文件,用于一对多和多对一。然后我创建了一个小程序来获取Person
个实体以及相应的Address
个实体:
one-to-many
:
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=?
many-to-one
:
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=?
从生成的查询中,对于one-to-many
,最初的查询是从Person
表获取记录,以获取所有人员,然后获取PersonAddress
和{{1}之间的JOIN地址}}。
Address
最初它在many-to-one
和PersonAddress
之间有LEFT OUTER JOIN以获取Address
记录,然后它到达Person
表以获取来自Address
表的记录。
所以我怀疑为什么Address
案例没有遵循many-to-one
的相同方法,只打了one-to-many
表,因为最初我试图只获取我的HQL中的Person实体。请帮助我理解这一点。
答案 0 :(得分:3)
对于OneToMany案例,一个人拥有一组地址。该集合可以有0个,一个或多个地址。这个系列懒洋洋地填充。因此,当从数据库加载人员时,执行第一个查询以获取人员的字段(名称等)。 Hibernate还不知道这个人是否有地址,并不关心。它将地址集合设置为惰性集合。第一次在这个惰性集合上调用一个方法时,会执行第二个查询来加载该人的所有地址并填充该集合。
对于ManyToOne案例,某人的字段地址为Address。当你加载一个人时,Hibernate应该将该字段初始化为什么。如果它将它设置为null并且您要求该地址,它将返回null,即使该人有一个地址,这是错误的。如果它将它设置为一个惰性地址代理并且你要求该地址,它将返回非空代理,即使该人没有地址,这也是错误的。所以Hibernate必须知道这个人是否有地址。如果没有,则将该字段设置为null。如果有,则将地址设置为地址代理。这就是为什么要执行额外的左外连接的原因:知道该人是否有地址(以及该地址的ID是什么),如果有的话。