小编典典

了解在联接表上为一对多和多对一生成的查询

sql

我正在跟踪关于连接表的一对多和多对一单向关联的休眠文档

我试图通过创建如下的Person&Address实体来实现一个简单的示例:

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: 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表中获取记录以获取所有Persons,然后获取其在PersonAddress和之间具有JOIN的地址Address

其中,作为many-to-one最初它有LEFT OUTER
JOIN之间PersonAddressAddress得到Person记录,然后将其打Address表,从获得的记录Address表。

因此,我的疑问是,为什么many-to-one案件没有one-to- many采用仅点击Person表格的相同方法,因为最初我试图仅提取HQL中的Person实体。请帮助我理解这一点。


阅读 187

收藏
2021-05-16

共1个答案

小编典典

对于OneToMany情况,一个人有一个地址集合。集合可以有0,一个或多个地址。该集合懒惰地填充。因此,当从数据库中加载人员时,将执行第一个查询以获取人员的字段(姓名等)。Hibernate尚不知道此人是否有地址,因此不在乎。它将地址集合设置为惰性集合。第一次在此惰性集合上调用方法时,将执行第二个查询以加载人员的所有地址并填充该集合。

对于ManyToOne情况,一个人的字段地址类型为Address。当您加载一个人时,Hibernate应该将此字段初始化为什么。如果将其设置为null并且您要求提供地址,则即使该人有地址,它也将返回null。如果将其设置为惰性地址代理,而您要求提供地址,则即使该人没有地址,它也将返回非空代理,这也是错误的。因此,Hibernate必须知道此人是否有地址。如果没有,则将该字段设置为null。如果有一个,它将地址设置为地址代理。这就是执行附加的左外部联接的原因:知道此人是否有地址(以及该地址的ID是什么,如果有的话)。

2021-05-16