java - 了解为 Join 表上的一对多和多对一生成的查询

标签 java sql hibernate

我正在关注 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 PersonAddressAddress 之间。

对于 many-to-one 最初它在 PersonAddressAddress 之间有 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/

相关文章:

java.lang.NoClassDefFoundError : org/slf4j/impl/StaticLoggerBinder

java - 随机无法识别 Maven 依赖项

java - Azure 认知服务检测错误 : Unable to resolve host "centralus.api.cognitive.microsoft.com"

java - 线程受 Thread.yield() 影响吗?

spring - 非事务性请求尝试使用 Derby 获得锁

SQL为每个类别获取1条随机记录

java - 像 a[1][1][1][1]....[1] 这样的 Java 支持多少维数组?

sql - Proc SQL 并通过单个变量删除重复项

MySQL 使用多列进行搜索

sql - pl/sql函数调用了多少次?