接着上一篇接着说一对一关联映射。
单向一对一唯一外键关联映射
我们先来假设一个场景,从Person中能看到IdCard,也就是在person数据表加上一个外键字段idCard,限制
idCard的唯一性就是一对一外键关联因素;一对一单向唯一外键关联,也就是多对一关联的特例,把多的一端限制为
一,就是一对一唯一外键关联。同多对一关联映射关系一样,在一端加入另一端的并采用<many-to-one>标签,通
过unique="true",这样来限制了多的一端为一。
如下图所示:
Person实体类:同单向一对一主键关联映射的Person实体类一样
Person对象关系映射配置文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.demo.domain.Person" table="person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!-- 采用<many-to-one>标签来映射,指定多的一端unique为true,
这样就限制了多的一端的多重性为一,就是这样来映射的。 -->
<many-to-one name="idCard" unique="true"/>
</class>
</hibernate-mapping>
IdCard实体类:同单向一对一主键关联映射的IdCard实体类一样
IdCard对象关系映射配置文件:同单向一对一主键关联映射的IdCard对象关系映射文件一样
测试类代码:
package com.demo.test;
import org.hibernate.Session;
import com.demo.domain.HibernateUtils;
import com.demo.domain.IdCard;
import com.demo.domain.Person;
import junit.framework.TestCase;
/**
* 单向一对一唯一外键关联(Person--->IdCard)
* @author Administrator
* @date 2016年12月8日
*/
public class One2OneTest extends TestCase {
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("1111111");
Person person = new Person();
person.setName("张三");
//建立一对一关联
person.setIdCard(idCard);
//抛出TransientObjectException
//因为IdCard为Transient状态
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("2222222");
session.save(idCard);
Person person = new Person();
person.setName("张三");
//建立关联
person.setIdCard(idCard);
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Person person = (Person)session.load(Person.class, 2);
System.out.println("person.name=" + person.getName());
System.out.println("person.cardNo=" + person.getIdCard().getCardNo());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}
testSave1()方法
控制台输出:
testSave2()方法
控制台输出:
数据库显示:
testLoad()方法
控制台输出:
双向一对一唯一外键关联映射
我们先来假设一个场景,单向一对一唯一外键关联映射我们已经了解了,双向反过来就是在没有的一端加上就可
以了。我们的IdCard.hbm.xml中采用<one-to-one>标签。
如下图所示:
Person实体类:同单向一对一唯一外键关联映射的Person实体类一样
Person对象关系映射配置文件:同单向一对一唯一外键关联映射的IdCard对象关系映射文件一样
IdCard实体类:同双向一对一主键关联映射的IdCard实体类一样
IdCard对象关系映射配置文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.demo.domain.IdCard" table="idCard">
<id name="id">
<generator class="native"/>
</id>
<property name="cardNo"/>
<!-- 一对一唯一外键关联双向采用<one-to-one>标签映射,
必须指定<one-to-one>标签中的property-ref属性为关系字段的名称 -->
<one-to-one name="person" property-ref="idCard"/>
</class>
</hibernate-mapping>
测试类代码:
package com.demo.test;
import org.hibernate.Session;
import com.demo.domain.HibernateUtils;
import com.demo.domain.IdCard;
import com.demo.domain.Person;
import junit.framework.TestCase;
public class One2OneTest extends TestCase {
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("1111111");
Person person = new Person();
person.setName("张三");
//建立关联
person.setIdCard(idCard);
//抛出TransientObjectException
//因为IdCard为Transient状态
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = new IdCard();
idCard.setCardNo("1111111111111111");
session.save(idCard);
Person person = new Person();
person.setName("张三");
//建立关联
person.setIdCard(idCard);
session.save(person);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Person person = (Person)session.load(Person.class, 2);
System.out.println("person.name=" + person.getName());
System.out.println("person.cardNo=" + person.getIdCard().getCardNo());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
public void testLoad2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
IdCard idCard = (IdCard)session.load(IdCard.class, 1);
System.out.println("idCard.cardNo=" + idCard.getCardNo());
System.out.println("idCard.person.name=" + idCard.getPerson().getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}
testSave1()方法:
控制台输出:
testSave2()方法:
控制台输出:
数据库显示:
testLoad1()方法:
控制台输出:
testLoad2()方法:
控制台输出:
从上述中可以总结出,对于一对一关联映射,主键关联和唯一外键关联单向和双向产生出的表结构是一样的,不
同的是在加载的时候不同。也就是双向一对一关联映射和单向一对一关联映射的相比,只是改变了一对一关联映射的
加载,而没有改变存储。