您的位置:首页 > 其它

Hibernate 映射一对一关联关系

2016-02-24 16:56 260 查看
之前介绍组成关系时,已介绍了Customer类与Address类,Address类是组件类,没有OID,数据库中没有对应的表, Address对象的生命周期依赖于Customer对象的生命周期。Customer类中定义了两个值类型的homeAddress属性和comAddress属性:

private Address homeAddress;

private Address comAddress;
但也可以将Address设计成实体类,此时,数据库中存在ADDRESSES表,Address类有单独的OID,Customer类与Address类之间为一对一的关联关系。
Hibernate提供两种映射一对一关联关系的方法:按照外键映射和按照主键映射。

1.按照外键映射

CUSTOMERS表的两个外键HOME_ADDRESS_ID和COM_ADDRESS_ID都参照ADDRESSES表的主键。

数据库表:

create table CUSTOMERS (
ID bigint not null,
NAME varchar(15),
HOME_ADDRESS_ID bigint unique,
COM_ADDRESS_ID bigint unique,
primary key (ID),
foreign key (HOME_ADDRESS_ID) references ADDRESSES(ID),
foreign key (COM_ADDRESS_ID) references ADDRESSES(ID)
);

create table ADDRESSES(
ID bigint not null,
CITY varchar(128),
STREET varchar(128),
PROVINCE varchar(128),
ZIPCODE varchar(6),
primary key(ID)
);

Customer.java:
public class Customer implements Serializable {
private Long id;
private String name;
private Address homeAddress;
private Address comAddress;
constructor...(); getter()...;setter()...;
}

Customer.hbm.xml:
<hibernate-mapping >
<class name="mypack.Customer" table="CUSTOMERS" >
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>

<property name="name" column="NAME" type="string" />

<many-to-one name="homeAddress"
class="mypack.Address"
column="HOME_ADDRESS_ID"
cascade="all"
unique="true"
/>

<many-to-one name="comAddress"
class="mypack.Address"
column="COM_ADDRESS_ID"
cascade="all"
unique="true"
/>

</class>
</hibernate-mapping>
<many-to-one>元素的unique为true,表明每个Customer对象都有唯一的homeAddress和comAddress对象。
Address.java:

public class Address
4000
implements Serializable {
private Long id;
private String street;
private String city;
private String province;
private String zipcode;
private Customer customer;

constructor...(); getter()...;setter()...;
}
Address.hbm.xml:
<hibernate-mapping >
<class name="mypack.Address" table="ADDRESSES" >
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>

<property name="city" column="CITY" type="string" />
<property name="province" column="PROVINCE" type="string" />
<property name="street" column="STREET" type="string" />
<property name="zipcode" column="ZIPCODE" type="string" />

<one-to-one name="customer"
class="mypack.Customer"
property-ref="homeAddress"
/>

</class>
</hibernate-mapping>
<one-to-one>元素的property-ref属性为"homeAddress",表明建立了从homeAddress对象到Customer对象的关联。
只能用<one-to-one>元素对Address类的customer属性映射一次,已映射homeAddress对象与Customer对象的双向关联,不能同时再映射Customer对象与comAddress对象的双向关联。

解决办法:把Address类定义为抽象类,创建HomeAddress和ComAddress子类,在HomeAddress.hbm.xml和ComAddress.hbm.xml中分别用<one-to-one>元素来映射各自的customer属性。

默认情况下,多对一关联采用延迟检索策略,一对一关联采用迫切左连接检索策略。

2.按照主键映射

ADDRESSES表的ID即作为主键,又作为外键参照CUSTOMERS表的主键,即ADDRESSES表与CUSTOMERS表共享主键。

数据库表:

create table CUSTOMERS (
ID bigint not null,
NAME varchar(15),
primary key (ID)
);

create table ADDRESSES(
ID bigint not null,
STREET varchar(128),
CITY varchar(128),
PROVINCE varchar(128),
ZIPCODE varchar(6),
primary key (ID),
foreign key (ID) references CUSTOMERS(ID)
);

Customer.java:
public class Customer implements Serializable {
private Long id;
private String name;
private Address address;

constructor...(); getter()...;setter()...;
}
Customer.hbm.xml:
<hibernate-mapping >
<class name="mypack.Customer" table="CUSTOMERS" >
<id name="id" type="long" column="ID">
<generator class="increment"/>
</id>

<property name="name" column="NAME" type="string" />

<one-to-one name="address"
class="mypack.Address"
cascade="all"
/>

</class>
</hibernate-mapping>

Address.java:
public class Address implements Serializable {
private Long id;
private String street;
private String city;
private String province;
private String zipcode;
private Customer customer;

constructor...(); getter()...;setter()...;
}
Address.hbm.xml:
<hibernate-mapping >
<class name="mypack.Address" table="ADDRESSES" >
<id name="id" type="long" column="ID">
<generator class="foreign">
<param name="property">customer</param>
</generator>
</id>

<property name="city" column="CITY" type="string" />
<property name="province" column="PROVINCE" type="string" />
<property name="street" column="STREET" type="string" />
<property name="zipcode" column="ZIPCODE" type="string" />

<one-to-one name="customer"
class="mypack.Customer"
constrained="true"
/>

</class>
</hibernate-mapping>
<one-to-one>元素的constrained属性为true,表明ADDRESSES表的ID主键同时作为外键参照CUSTOMERS表,此时其OID必须使用foreign标识符生成策略。
使用foreign标识符生成策略,Hibernate会保证Address对象与关联的Customer对象共享同一个OID。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: