多对一(many to one)
单向many-to-one关联是最常见的单向关联关系。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<many-to-one name="address" column="addressId" not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key
基于外键关联的单向一对一关联和单向多对一关联几乎是一样的。唯一的不同就是单向一对一关联中的外键字段具有唯一性约束。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<many-to-one name="address" column="addressId" unique="true" not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
基于主键关联的单向一对一关联通常使用一个特定的id生成器。(请注意,在这个例子中我们掉换了关联的方向。)
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
</class>
<class name="Address">
<id name="id" column="personId"><generator class="foreign">
<param name="property">person</param></generator></id>
<one-to-one name="person" constrained="true"/>
</class>
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
基于外键关联的单向一对多关联是一种很少见的情况,并不推荐使用。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<set name="addresses">
<key column="personId" not-null="true"/>
<one-to-many class="Address"/></set>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
create table Person ( personId bigint not null primary key )
create table Address ( addressId bigint not null primary key, personId bigint not null )
我们认为对于这种关联关系最好使用连接表。
8.3. 使用连接表的单向关联(Unidirectional associations with join tables)
基于连接表的单向一对多关联 应该优先被采用。请注意,通过指定unique="true",我们可以把多样性从多对多改变为一对多。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId" unique="true" class="Address"/></set>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
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 )
基于连接表的单向多对一关联在关联关系可选的情况下应用也很普遍。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<join table="PersonAddress" optional="true">
<key column="personId" unique="true"/>
<many-to-one name="address" column="addressId" not-null="true"/></join>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
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 )
基于连接表的单向一对一关联非常少见,但也是可行的。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<join table="PersonAddress" optional="true">
<key column="personId" unique="true"/>
<many-to-one name="address" column="addressId" not-null="true" unique="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
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 )
最后,还有 单向多对多关联.
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId" class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
</class>
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 )
8.4. 双向关联(Bidirectional associations)
8.4.1. 一对多(one to many) / 多对一(many to one)
双向多对一关联 是最常见的关联关系。(这也是标准的父/子关联关系。)
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<many-to-one name="address" column="addressId" not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
<set name="people" inverse="true">
<key column="addressId"/>
<one-to-many class="Person"/></set>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
基于外键关联的双向一对一关联也很常见。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<many-to-one name="address" column="addressId" unique="true"not-null="true"/>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
<one-to-one name="person" property-ref="address"/>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null unique )
create table Address ( addressId bigint not null primary key )
基于主键关联的一对一关联需要使用特定的id生成器。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<one-to-one name="address"/>
</class>
<class name="Address">
<id name="id" column="personId">
<generator class="foreign">
<param name="property">person</param></generator></id>
<one-to-one name="person" constrained="true"/>
</class>
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
8.5. 使用连接表的双向关联(Bidirectional associations with join tables)
8.5.1. 一对多(one to many) /多对一( many to one)
基于连接表的双向一对多关联。注意inverse="true"可以出现在关联的任意一端,即collection端或者join端。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<set name="addresses" table="PersonAddress">
<key column="personId"/>
<many-to-many column="addressId" unique="true" class="Address"/></set>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
<join table="PersonAddress" inverse="true" optional="true">
<key column="addressId"/>
<many-to-one name="person" column="personId" not-null="true"/></join>
</class>
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 )
基于连接表的双向一对一关联极为罕见,但也是可行的。
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<join table="PersonAddress" optional="true">
<key column="personId" unique="true"/>
<many-to-one name="address" column="addressId" not-null="true" unique="true"/>
</join>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
<join table="PersonAddress" optional="true" inverse="true">
<key column="addressId" unique="true"/>
<many-to-one name="address" column="personId" not-null="true" unique="true"/>
</join>
</class>
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 )
最后,还有 双向多对多关联.
<class name="Person">
<id name="id" column="personId"><generator class="native"/></id>
<set name="addresses">
<key column="personId"/>
<many-to-many column="addressId" class="Address"/></set>
</class>
<class name="Address">
<id name="id" column="addressId"><generator class="native"/></id>
<set name="people" inverse="true">
<key column="addressId"/>
<many-to-many column="personId" class="Person"/></set>
</class>
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 )