Hibernate中实现一对一映射有基于外键的方式和基于主键的方式。由于基于主键方式的映射在实现删除等操作时存在的问题且不够灵活,一般建议使用基于外键的方式实现。
以个人与身份证的关系为例(主要看映射文件的配置和实体类):
基于外键的方式(只有有外键方可以维护关联关系):
package test.hibernate.hbmOneToOne;
public class Person {
private Integer id;
private String name;
private IDCard idCard;
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 IDCard getIdCard() {
return idCard;
}
public void setIdCard(IDCard idCard) {
this.idCard = idCard;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "[Person:id=" + id + ",name=" + name + "]";
}
}
package test.hibernate.hbmOneToOne;
public class IDCard {
private Integer id;
private String IDNumber;
private Person person;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getIDNumber() {
return IDNumber;
}
public void setIDNumber(String iDNumber) {
IDNumber = iDNumber;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "[IDCard:id="+id+",IDNumber="+IDNumber+"]";
}
}
<?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="test.hibernate.hbmOneToOne">
<class name="Person" table="person">
<id name="id" type="integer" column="id">
<generator class="native" />
</id>
<property name="name" />
<one-to-one name="idCard" class="IDCard" property-ref="person"></one-to-one>
</class>
</hibernate-mapping>
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="test.hibernate.hbmOneToOne">
<class name="IDCard" table="idCard">
<id name="id" type="integer" column="id">
<generator class="native" />
</id>
<property name="IDNumber" />
<many-to-one name="person" class="Person" column="personId" unique="true">
</many-to-one>
</class>
</hibernate-mapping>
测试类
package test.hibernate.hbmOneToOne;
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)//
.buildSessionFactory();
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 构建对象
Person person = new Person();
person.setName("张三");
IDCard idCard = new IDCard();
idCard.setIDNumber("377489392002121X");
// 关联起来
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, 2);
System.out.println(person);
System.out.println(person.getIdCard());
IDCard idCard = (IDCard) session.get(IDCard.class, 2);
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);
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 删除,只能做有外键方到无外键方的单向关联
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// Person person=(Person) session.get(Person.class, 2);
// session.delete(person);//删除失败,有personId外键,抛出异常
IDCard idCard = (IDCard) session.get(IDCard.class, 3);
session.delete(idCard);// 卡删了,人还在
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}
基于主键的方式(双方都不可以维护关联关系,映射文件配置有所不同):
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="test.hibernate.hbmOneToOne2">
<class name="Person" table="person2">
<id name="id" type="integer" column="id">
<generator class="native" />
</id>
<property name="name" />
<one-to-one name="idCard" class="IDCard"></one-to-one>
</class>
</hibernate-mapping>
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="test.hibernate.hbmOneToOne2">
<class name="IDCard" table="idCard2">
<id name="id" type="integer" column="id">
<!--
当使用基于主键的一对一映射时,有外键方的主键
生成策略 一定要是foreign。
参数property:生成主键值时所根据的对象。
-->
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="IDNumber" />
<!-- constrained外键约束 -->
<one-to-one name="person" class="Person" constrained="true">
</one-to-one>
</class>
</hibernate-mapping>
package test.hibernate.hbmOneToOne2;
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)//
.buildSessionFactory();
@Test
public void testSave() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// 构建对象
Person person = new Person();
person.setName("张三");
IDCard idCard = new IDCard();
idCard.setIDNumber("377489392002121X");
// 关联起来
person.setIdCard(idCard);
idCard.setPerson(person);
// 保存
// session.save(person);
session.save(idCard);
// --------------------------------------------
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, 3);
person.setIdCard(null);//数据库中的数据没有改变
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
// 删除
@Test
public void testDelete() throws Exception {
Session session = sessionFactory.openSession();
session.beginTransaction();
// --------------------------------------------
// IDCard idCard = (IDCard) session.get(IDCard.class, 2);
// session.delete(idCard);//正常
Person person=(Person) session.get(Person.class, 3);
session.delete(person);//抛异常,id作为外键
// --------------------------------------------
session.getTransaction().commit();
session.close();
}
}