一对一关联指两个表之间的记录是一一对应的关系。分为两种:外键关联和主键关联。
(1)外键关联
比如一家公司(Company)和它所在的地址(Address)。在业务逻辑中要求一家公司只有唯一的地址,一个地址也只有一家公司。下图表现为外键关联关系。
对于基于外键的
1-1
关联,其外键可以存放在任意一边,
在需要存放外键一端,增加
many-to-one
元素
。为
many-to-one
元素增加
unique=
“
true
”
属性来表示为
1-1
关联,并用
name
属性来指定关联属性的属性名
另一端需要使用
one-to-one
元素,该元素使用
property-ref(
可以不加
)
属性指定使用
被关联实体主键以外的字段作为关联字段
示例代码:
Company.java bean对象
public class Company implements java.io.Serializable {
private Integer id;
private String name;
//一家公司对应一个地址
private Address address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
Address.java
public class Address implements java.io.Serializable{
private Integer id;
private String city;
private String country;
//一个地址含有一家公司
private Company company;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Company getCompany() {
return company;
}
public void setCompany(Company company) {
this.company = company;
}
}
Company.hbm.xml 映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.one2onefk.Company" table="companyfk">
<id name="id" type="integer">
<column name="id"/>
<generator class="increment"/>
</id>
<property name="name" type="string">
<column name="name"/>
</property>
<!-- 一对一外键关联
many-to-one:使用many-to-one
unique="true":设置companyfk表的外键唯一 addressid integer unique,
-->
<many-to-one name="address" column="addressid" unique="true"/>
</class>
</hibernate-mapping>
Address.hbm.xml 映射配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.one2onefk.Address" table="addressfk">
<id name="id" type="integer">
<column name="id"/>
<generator class="increment"/>
</id>
<property name="city" type="string">
<column name="city"/>
</property>
<property name="country" type="string">
<column name="country"/>
</property>
<!-- 映射一对一
property-ref(互相引用):company属性管理的address这个属性
property-ref的值为Company这个类中的address属性(可以不加)
-->
<one-to-one name="company" property-ref="address"/>
</class>
</hibernate-mapping>
App.java 测试代码
public class App {
private static SessionFactory sf=null;
static{
Configuration config=new Configuration();
config.configure("cn/itcast/one2onefk/hibernate.cfg.xml");
config.addClass(Company.class);
config.addClass(Address.class);
sf=config.buildSessionFactory();
}
/*
* 知识点1:测试保存
*/
@Test
public void saveCompanyAndAddress(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
Company c=new Company();
c.setName("长城");
Address address=new Address();
address.setCity("上海");
address.setCountry("中国");
//建立关联
c.setAddress(address);
address.setCompany(c);
//保存
session.save(address);
session.save(c);
tx.commit();
session.close();
}
//知识点2:测试唯一性
@Test
public void testUnique(){
Session session=sf.openSession();
Transaction tx=session.beginTransaction();
Company c=new Company();
c.setName("天空网");
//获取一号地址
Address address=(Address)session.get(Address.class, 1);
//建立关联
c.setAddress(address);
address.setCompany(c);
//不能保存
session.save(c);
tx.commit();
session.close();
}
}
(2)主键关联
一对一的另一种解决方式就是主键关联,在这种关联关系中,要求两个对象的主键必须保持一致,一方既是主键又是外键,通过两个表的主键建立关联关系,无须外键参与。
基于主键的映射策略
:
指一端的主键生成器使用
foreign
策略
,
表明根据
”
对方
”
的主键来生成自己的主键,自己并不能独立生成主键
. <param>
子元素指定使用当前持久化类的哪个属性作为
“
对方
”
采用
foreign
主键生成器策略的一端增加
one-to-one
元素映射关联属性,其
one-to-one
属性还应增加
constrained=
“
true
”
属性;另一端
(company)
增加
one-to-one
元素映射关联属性。
constrained(
约束
):
指定为当前持久化类对应的数据库表的主键添加一个外键约束,引用被关联的对象
(
“
对方
”
)
所对应的数据库表主键
示例代码, java bean类 和 测试代码与(1)中一样, 不同的只有映射配置文件。
Address.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.one2onepk.Address" table="addresspk">
<id name="id" type="integer">
<column name="id"/>
<!--
foreign:表示addresspk表的主键的生成参照另一个表(companypk的)主键
这里addresspk表的主键值来源于companypk表的主键,不是该addresspk表自己生成
-->
<generator class="foreign">
<!--
property:该Address类对应表主键的生成,参照该类中的属性company
-->
<param name="property">company</param>
</generator>
</id>
<property name="city" type="string">
<column name="city"/>
</property>
<property name="country" type="string">
<column name="country"/>
</property>
<!--one-to-one配置Address和Company的一对一关联
constrained="true":为addresspk增加外键约束
-->
<one-to-one name="company" constrained="true"/>
</class>
</hibernate-mapping>
Company.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.one2onepk.Company" table="companypk">
<id name="id" type="integer">
<column name="id"/>
<generator class="increment"/>
</id>
<property name="name" type="string">
<column name="name"/>
</property>
<!-- 配置Company和地址的一对一关联 -->
<one-to-one name="address"/>
</class>
</hibernate-mapping>