了解在Join表上为一对多和多对一生成的查询 [英] Understanding the queries generated for one-to-many and many-to-one on Join table
问题描述
我正在关注 hibernate文档,用于与连接表的一对多和多对一单向关联。
I am following the hibernate documentation for one-to-many and many-to-one Unidirectional associations with join tables.
我试图实现一个简单的例子通过创建人与人像这样的地址实体:
I tried to implement a simple example by creating Person & Address entity like this:
Person has an id and name property with setters & getters
Address has an id and name property with setters & getters
我在文档中给出了一对多的映射文件,也有很多 - 一对一。然后我创建了一个小程序来获取 Person
实体和相应的地址
这样的实体:
I have the same mapping file given in the documentation for one-to-many and also many-to-one. Then I created a small program to get Person
entities and the corresponding Address
entities like this:
对于一对多
:
for (Person person : list) {
System.out.println(person.getId());
for (Address address : person.getAddresses()) {
System.out.println(address);
}
}
对于下面生成的hibernate查询:
For this hibernate generated below queries:
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
表中获取记录,以获取所有人员,然后获取 PersonAddress $ c之间的JOIN地址$ c>和
地址
。
From the generated queries, for one-to-many
initially the query was to get records from Person
table to get all Persons then for getting the addresses it had JOIN between PersonAddress
and Address
.
对于多对一
,最初它在 PersonAddress之间有LEFT OUTER JOIN
和地址
获取人
记录然后点击地址
表从地址
表中获取记录。
Where as for many-to-one
initially it had LEFT OUTER JOIN between PersonAddress
and Address
to get Person
records then it hit the Address
table to get the records from Address
table.
所以我怀疑是为什么多对一
案例没有按照一对多
的方法,仅按 Person
表因为最初我试图只获取我的HQL中的Person实体。请帮助我理解这一点。
So my doubt is why the many-to-one
case has not followed the same approach of one-to-many
by hitting only Person
table because initially I am trying to fetch only Person entities in my HQL. Please help me in understanding this.
推荐答案
对于OneToMany案例,一个人有一组地址。该集合可以有0个,一个或多个地址。这个系列懒洋洋地填充。因此,当从数据库加载人员时,执行第一个查询以获取人员的字段(名称等)。 Hibernate还不知道这个人是否有地址,而且不关心。它将地址集合设置为惰性集合。第一次在这个惰性集合上调用一个方法时,会执行第二个查询来加载该人的所有地址并填充该集合。
For the OneToMany case, a person has a collection of addresses. The collection could have 0, one or more addresses. This collection is populated lazily. So, when a person is loaded from the database, a first query is executed to get the fields of the person (name, etc.). Hibernate doesn't know yet if the person has addresses or not, and it doesn't care. It sets the addresses collection to a lazy collection. The first time a method is called on this lazy collection, a second query is executed to load all the addresses of the person and populate the collection.
对于ManyToOne案例a person的字段地址类型为Address。当你加载一个人时,Hibernate应该将该字段初始化为什么。如果它将它设置为null并且您要求该地址,则它将返回null,即使该人有一个地址,这是错误的。如果它将它设置为一个惰性地址代理并且你要求该地址,它将返回非空代理,即使该人没有地址,这也是错误的。所以Hibernate必须知道这个人是否有地址。如果没有,则将该字段设置为null。如果有,则将地址设置为地址代理。这就是为什么要执行额外的左外连接的原因:知道该人是否有地址(以及该地址的ID是什么),如果有的话。
For the ManyToOne case a person has a field address of type Address. When you load a person, what should Hibernate initialize this field to. If it sets it to null and you ask for the address, it will return null, even if the person has an address, which is wrong. If it sets it to an lazy address proxy and you ask for the address, it will return the non-null proxy even if the person doesn't have an address, which is also wrong. So Hibernate has to know if the person has or doesn't have an address. If it doesn't have one, it sets the field to null. If it has one, it sets the address to an address proxy. That's the reason why an additional left outer join is executed: to know if the person has an address or not (and what the ID of this address is, if any).
这篇关于了解在Join表上为一对多和多对一生成的查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!