8.4.1. 一对多(one to many)/多对一(many to one)
双向多对一关联 是最常见的关联关系。下面的例子解释了这种标准的父/子关联关系。
模型:多个人(Person)对应一个地址(Address)。
实体:
public class Person1nfk_sx implements Serializable {
private int personid;
private String name;
private int age;
private Address1nfk_sx address1nfk_sx;
public class Address1nfk_sx implements Serializable {
private int addressid;
private String addressdetail;
private Set Person=new HashSet();
映射:
<class name="Person">
<id name="id" column="personId">
<generator class="native"/>
</id>
<!--映射关联属性,column属性指定外键列名-->
column="addressId"
not-null="true"/>
</class>
<class name="Address">
<generator class="native"/>
</id>
<!--映射集合属性,关联到持久化类--> <!--column用于指定外键列名-->
<key column="addressId"/>
<!--映射关联类-->
</set>
</class>
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" 来对另一端反向操作。
<class name="Person">
<id name="id"/>
<many-to-one name="address"
column="addressId"
not-null="true"
insert="false"
update="false"/>
</class>
<class name="Address">
<id name="id"/>
<list name="people">
<key column="addressId" not-null="true"/>
<list-index column="peopleIdx"/>
<one-to-many class="Person"/>
</list>
</class>
假若集合映射的 <key> 元素对应的底层外键字段是 NOT NULL 的,那么为这一 key 元素定义 notnull="
true" 是很重要的。不要仅仅为可能的嵌套 <column>元素定义 not-null="true",<key> 元素
也是需要的。
8.4.2. 一对一(One-to-one)
基于外键关联的双向一对一关联也很常见。
模型:一个地址对应一个人。
实体:
private Long id;
private String name;
private Address address;
private Long id;
private Person person;
private String detail;
映射:
<class name="Person">
<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">
<generator class="native"/>
</id>
<!-- cascade="all":在保存person对象的时候,级联保存person对象关联的address对象 -->
</class>
<class name="Address">
<id name="id" column="personId">
<!-- class="foreign": 一对一主键映射中,使用另外一个相关联的对象的标识符 -->
<param name="property">person</param>
</generator>
</id>
<!-- 表示在address表存在一个外键约束,外键参考相关联的表person -->
constrained="true"/>
</class>
create table Person ( personId bigint not null primary key )
create table Address ( personId bigint not null primary key )
alter table address add constraint FK_Reference_2 foreign key (id)
references person (id) on delete restrict on update restrict;8.5. 使用连接表的双向关联(Bidirectional associationswith join tables)
8.5.1. 一对多(one to many)/多对一(many to one)
下面是一个基于连接表的双向一对多关联的例子。注意 inverse="true" 可以出现在关联的任意一端,即 collection 端或者 join 端。
模型:一个人(Person)对应多个地址(Address)。
实体:
public class Person1ntab_sx {
|
private int personid;
|
private String name;
|
private int age;
|
private Set addresses=new HashSet();
|
|
public class Address1ntab_sx {
|
private int addressid;
|
private String addressdetail;
|
private Person1ntab_sx person1ntab_sx;
|
映射:
<id name="id" column="personId">
<generator class="native"/>
</id>
<!--映射集合属性,关联到持久化类-->
<!--table="PersonAddress"指定了连接表的名字-->
<!--column="personid"指定连接表中关联当前实体类的列名-->
<key column="personId"/>
<!--unique="true"表示当前实体类是"1",不是"n"-->
<many-to-many column="addressId" unique="true" class="Address"/></set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<!--映射关联属性,column属性指定外键列名-->
<join table="PersonAddress" inverse="true" optional="true">
<many-to-one name="person"
column="personId"
not-null="true"/>
</join>
</class>
连接表中多方(address)还有1方(person)引用。
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 )
8.5.2. 一对一(one to one)
基于连接表的双向一对一关联也是可行的,但极为罕见。
模型:一个人对应一个地址。
实体:
public class Person11tab_sx {
|
private int personid;
|
private String name;
|
private int age;
|
private Address11tab_sx address11tab_sx;
|
|
public class Address11tab_sx {
|
private int addressid;
|
private String addressdetail;
|
private Person11tab_sx person11tab_sx;
|
|
<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="person"
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 )
8.5.3. 多对多(many-to-many)
下面是一个双向多对多关联的例子。
模型:一个人可对应多个地址,一个地址也可以对应多个人。
实体:
public class Personnn_sx {
private int personid;
private String name;
private int age;
private Set addresses=new HashSet();
public class Addressnn_sx {
private int addressid;
private String addressdetail;
private Set persons = new HashSet();
映射:
<id name="id" column="personId">
<generator class="native"/>
</id>
<!--映射集合属性,关联到持久化类-->
<!--table="PersonAddress"指定了连接表的名字-->
<set name="addresses" table="PersonAddress">
<!--column="personid"指定连接表中关联当前实体类的列名-->
<key column="personId"/>
<!--column="addressid"是连接表中关联本实体的外键-->
class="Address"/>
</set>
</class>
<class name="Address">
<id name="id" column="addressId">
<generator class="native"/>
</id>
<!--table="PersonAddress"是双向多对多的连接表-->
<set name="people" inverse="true" table="PersonAddress">
<!--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 )