一对一 映射有两种方式:
主键关联: id 对应 id 两个主键必须相同
外键关联: id 对应 xxxid 专门设置一个外键属性 (推荐使用)
外键关联方式
例如:下面的例子IdCard 表会有一个专门的外键属性 personId 对应 person 主键id
IdCard.java
public class IdCard {
private Integer id;
private String number;
private Person person; // 关联的公民
IdCard.hbm.xml
<?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 package="cn.itcast.i_hbm_oneToOne">
<class name="IdCard" table="idCard">
<id name="id">
<generator class="native"></generator>
</id>
<property name="number"/>
<!-- person属性,Person类型。
表达的是本类与Person的一对一。
采用基于外键的一对一映射方式,本方有外键方。 -->
<many-to-one name="person" class="Person" column="personId" unique="true"></many-to-one>
</class>
</hibernate-mapping>
Person.java
public class Person {
private Integer id;
private String name;
private IdCard idCard; // 关联的身份证
Person.hbm.xml
<?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 package="cn.itcast.i_hbm_oneToOne">
<class name="Person" table="person">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>
<!-- idCard属性,IdCard类型。
表达的是本类与IdCard的一对一。
采用基于外键的一对一映射方式,本方无外键方。
property-ref属性:
写的是对方映射中外键列对应的属性名。
-->
<one-to-one name="idCard" class="IdCard" property-ref="person"/>
</class>
</hibernate-mapping>
第二种方式:
主键关联
其他一样只是,映射文件不同
IdCard.hbm.xml
... ...
<hibernate-mapping package="cn.itcast.i_hbm_oneToOne2">
<class name="IdCard" table="idCard2">
<id name="id">
<!-- 当使用基于主键的一对一映射时,
有外键方的主键生成策略一定要是foreign。
参数property:
生成主键值时所根据的对象。
-->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="number"/>
<!-- person属性,Person类型。
表达的是本类与Person的一对一。
采用基于主键的一对一映射方式,本方有外键方。 -->
<one-to-one name="person" class="Person" constrained="true"></one-to-one>
</class>
</hibernate-mapping>
Person.hbm.xml
... ...
<hibernate-mapping package="cn.itcast.i_hbm_oneToOne2">
<class name="Person" table="person2">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"/>
<!-- idCard属性,IdCard类型。
表达的是本类与IdCard的一对一。
采用基于主键的一对一映射方式,本方无外键方。
-->
<one-to-one name="idCard" class="IdCard"></one-to-one>
</class>
</hibernate-mapping>
测试代码
package cn.itcast.i_hbm_oneToOne;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;
public class App {
private static SessionFactory sessionFactory = new Configuration()//
.configure()//
.addClass(Person.class)// 添加Hibernate实体类(加载对应的映射文件)
.addClass(IdCard.class)// 添加Hibernate实体类(加载对应的映射文件)
.buildSessionFactory();
// 保存,有关联关系
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 新建对象
Person person = new Person();
person.setName("张三");
IdCard idCard = new IdCard();
idCard.setNumber("100000011X");
// 关联起来
// person.setIdCard(idCard);
idCard.setPerson(person);
// 保存
session.save(person);
session.save(idCard);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 获取,可以获取到关联的对方
@Test
public void testGet() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 获取一方,并显示另一方信息
// Person person = (Person) session.get(Person.class, 1);
// System.out.println(person);
// System.out.println(person.getIdCard());
IdCard idCard = (IdCard) session.get(IdCard.class, 1);
System.out.println(idCard);
System.out.println(idCard.getPerson());
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 解除关联关系:一对一中,只能有外键方可以维护关联关系。
@Test
public void testRemoveRelation() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 从有外键方解除关系,可以。
// IdCard idCard = (IdCard) session.get(IdCard.class, 1);
// idCard.setPerson(null);
// 从无外键方解除关系,不可以。
Person person = (Person) session.get(Person.class, 1);
person.setIdCard(null);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 删除对象,对关联对象的影响
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// a, 如果没有关联的对方:能删除。
// b, 如果有关联的对方且可以维护关联关系(有外键方),他就会先删除关联关系,再删除自己。
// c, 如果有关联的对方且不能维护关联关系(无外键方),所以会直接执行删除自己,就会有异常。
IdCard idCard = (IdCard) session.get(IdCard.class, 1);
session.delete(idCard);
// Person person = (Person) session.get(Person.class, 1);
// session.delete(person);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}