了解在Join表上为一对多和多对一生成的查询 [英] Understanding the queries generated for one-to-many and many-to-one on Join table

查看:347
本文介绍了了解在Join表上为一对多和多对一生成的查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在关注 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 地址

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆