我正在跟踪关于连接表的一对多和多对一单向关联的休眠文档。
我试图通过创建如下的Person&Address实体来实现一个简单的示例:
Person has an id and name property with setters & getters Address has an id and name property with setters & getters
我有一对多和多对一文档中给出的相同映射文件。然后,我创建了一个小程序来获取Person实体和相应的Address实体,如下所示:
Person
Address
对于one-to-many:
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:
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。
one-to- many
PersonAddress
其中,作为many-to-one最初它有LEFT OUTER JOIN之间PersonAddress并Address得到Person记录,然后将其打Address表,从获得的记录Address表。
因此,我的疑问是,为什么many-to-one案件没有one-to- many采用仅点击Person表格的相同方法,因为最初我试图仅提取HQL中的Person实体。请帮助我理解这一点。
对于OneToMany情况,一个人有一个地址集合。集合可以有0,一个或多个地址。该集合懒惰地填充。因此,当从数据库中加载人员时,将执行第一个查询以获取人员的字段(姓名等)。Hibernate尚不知道此人是否有地址,因此不在乎。它将地址集合设置为惰性集合。第一次在此惰性集合上调用方法时,将执行第二个查询以加载人员的所有地址并填充该集合。
对于ManyToOne情况,一个人的字段地址类型为Address。当您加载一个人时,Hibernate应该将此字段初始化为什么。如果将其设置为null并且您要求提供地址,则即使该人有地址,它也将返回null。如果将其设置为惰性地址代理,而您要求提供地址,则即使该人没有地址,它也将返回非空代理,这也是错误的。因此,Hibernate必须知道此人是否有地址。如果没有,则将该字段设置为null。如果有一个,它将地址设置为地址代理。这就是执行附加的左外部联接的原因:知道此人是否有地址(以及该地址的ID是什么,如果有的话)。