hibernate 多
映射的关联关系
7.2. 单向关联(Unidirectional associations)
7.2.1. 多对一(many-to-one)
单向 many-to-one 关联是最常见的单向关联关系。
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
7.2.2. 一对一(One-to-one)
基于外键关联的单向一对一关联和单向多对一关联几乎是一样的。唯一的不同就是单向一对一关
联中的外键字段具有唯一性约束。
create table Person ( personId bigint not null primary key, addressId bigint not null
unique )
create table Address ( addressId bigint not null primary key )
基于主键关联(外键作为主键?)的单向一对一关联通常使用一个特定的 id 生成器,然而在这个例子中我们掉换了
关联的方向:
person
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
7.2.3. 一对多(one-to-many)
基于外键关联的单向一对多关联是一种很少见的情况,我们不推荐使用它。
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key, personId bigint not
null )
我们认为对于这种关联关系最好使用连接表。
7.3. 使用连接表的单向关联(Unidirectional
associations with join tables)
7.3.1. 一对多(one-to-many)
基于连接表的单向一对多关联 应该优先被采用。请注意,通过指定unique="true",我们可以把多样性从多对多改变为一对多。
create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId not null, addressId bigint not null primary
key )
create table Address ( addressId bigint not null primary key )
7.3.2. 多对一(many-to-one)
基于连接表的单向多对一关联在关联关系可选的情况下应用也很普遍。例如:
create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null primary key, addressId bigint
not null )
create table Address ( addressId bigint not null primary key )
7.3.3. 一对一(One-to-one)
基于连接表的单向一对一关联也是可行的,但非常少见。
create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null primary key, addressId bigint
not null
unique )
create table Address ( addressId bigint not null primary key )
7.3.4. 多对多(many-to-many)
最后,这里是一个单向多对多关联的例子。
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null,
primary key
(personId, addressId) )
create table Address ( addressId bigint not null primary key )
7.4. 双向关联(Bidirectional associations)
7.4.1. 一对多(one to many)/多对一(many to one)
双向多对一关联 是最常见的关联关系。下面的例子解释了这种标准的父/子关联关系。
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
如果你使用 List(或者其他有序集合类),你需要设置外键对应的 key 列为 not null。Hibernate
将从集合端管理关联,维护每个元素的索引,并通过设置 update="false" 和 insert="false" 来对
另一端反向操作。
假若集合映射的
元素对应的底层外键字段是 NOT NULL 的,那么为这一 key 元素定义 notnull="
true" 是很重要的。不要仅仅为可能的嵌套 元素定义 not-null="true", 元素
也是需要的。
7.4.2. 一对一(One-to-one)
基于外键关联的双向一对一关联也很常见。
create table Person ( personId bigint not null primary key, addressId bigint not null
unique )
create table Address ( addressId bigint not null primary key )
基于主键关联的一对一关联需要使用特定的 id 生成器:
person
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
7.5. 使用连接表的双向关联(Bidirectional associations
with join tables)
7.5.1. 一对多(one to many)/多对一(many to one)
下面是一个基于连接表的双向一对多关联的例子。注意 inverse="true" 可以出现在关联的任意一
端,即 collection 端或者 join 端。
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not
null primary key )
create table Address ( addressId bigint not null primary key )
7.5.2. 一对一(one to one)
基于连接表的双向一对一关联也是可行的,但极为罕见。
create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null primary key, addressId bigint
not null
unique )
create table Address ( addressId bigint not null primary key )
7.5.3. 多对多(many-to-many)
下面是一个双向多对多关联的例子。
create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null,
primary key
(personId, addressId) )
create table Address ( addressId bigint not null primary key )
7.6. 更复杂的关联映射
更复杂的关联连接极为罕见。通过在映射文档中嵌入 SQL 片断,Hibernate 也可以处理
更
为复杂的情况。比如,假若包含历史帐户数据的表定义了 accountNumber、
effectiveEndDate 和
effectiveStartDate 字段,按照下面映射:
case when effectiveEndDate is null then 1 else 0 end
那么我们可以对目前(current)实例(其 effectiveEndDate 为 null)使用这样的关
联映射:
'1'
在更复杂的例子中,假想 Employee 和 Organization 之间的关联是通过一个
Employment 中间表维护的,而中间表中填充了很多历史雇员数据。那“雇员的最新雇主”这个关
联(最新雇主就是具有最新的 startDate 的那个)可以这样映射:
select employeeId, orgId
from Employments
group by orgId
having startDate = max(startDate)
使用这一功能时可以充满创意和灵活性,但通常更加实用的是用 HQL 或条件查询来处理
这些情
况。