一对一主键关联映射是hibernate关联映射中比较重要的一种,使用于两个关系比较紧密的对象之间的关联,一对一不说,一般还要共存亡。hibernate的做法是让两个实体对象的id保持相同。
人和身份证是典型的一对一关联映射的例子。
1.实体模型:

此处单向是由person加载idcard,所以Person中要保存IdCard的对象。
2.关系模型:
表person 表idCard
----------------------- --------------------------
| id | name | | id | cardNo |
------------------------ --------------------------
3.实体类:
IdCard.java
public class IdCard {
private Integer id;
private String cardNo;
//一系列的setter.getter方法
}
private Integer id;
private String cardNo;
//一系列的setter.getter方法
}
Person.java
public class Person {
private Integer id;
private String name;
private IdCard idCard;
//一系列的setter.getter方法
}
private Integer id;
private String name;
private IdCard idCard;
//一系列的setter.getter方法
}
4.映射文件:
IdCard.hbm.xml
<class name="com.sxt.hibernate.one2one.entity.IdCard" table="sxt_hibernate_idCard">
<id name="id" length="4">
<generator class="native"></generator>
</id>
<property name="cardNo" length="10"></property>
</class>
<id name="id" length="4">
<generator class="native"></generator>
</id>
<property name="cardNo" length="10"></property>
</class>
Person.hbm.xml
<class name="com.sxt.hibernate.one2one.entity.Person" table="sxt_hibernate_person">
<id name="id" length="4">
<!-- person的主键来源于idCard,也就是共享idCard的主键 -->
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name" length="10"></property>
<!--one-to-one标签的含义,指示Hibernate如何加载它的关联对象,默认根据主键加载。
constrained="true"的含义,表明当前主键上存在一个约束,person的主键作为外键参照了idCard,
这里在进行person对象操作时,要求idCard不 能为null
-->
<one-to-one name="idCard" constrained="true"></one-to-one>
</class>
<id name="id" length="4">
<!-- person的主键来源于idCard,也就是共享idCard的主键 -->
<generator class="foreign">
<param name="property">idCard</param>
</generator>
</id>
<property name="name" length="10"></property>
<!--one-to-one标签的含义,指示Hibernate如何加载它的关联对象,默认根据主键加载。
constrained="true"的含义,表明当前主键上存在一个约束,person的主键作为外键参照了idCard,
这里在进行person对象操作时,要求idCard不 能为null
-->
<one-to-one name="idCard" constrained="true"></one-to-one>
</class>
5.hibernate配置文件:
hibernate.cfg.xml
<session-factory>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:ORCL10</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">scott</property>
<property name="hibernate.connection.password">yf123</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="com/sxt/hibernate/one2one/entity/IdCard.hbm.xml"/>
<mapping resource="com/sxt/hibernate/one2one/entity/Person.hbm.xml"/>
</session-factory>
<property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:ORCL10</property>
<property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="hibernate.connection.username">scott</property>
<property name="hibernate.connection.password">yf123</property>
<property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="com/sxt/hibernate/one2one/entity/IdCard.hbm.xml"/>
<mapping resource="com/sxt/hibernate/one2one/entity/Person.hbm.xml"/>
</session-factory>
6.测试方法:
test.java
public static void main(String[] args) {
Session session = HibernateUtils.getSession();
Transaction t = session.beginTransaction();
try {
/**
* 测试插入操作
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
person.setIdCard(idCard);
//不会出现TransientObjectException异常,因为一对一主键关联映射中默认了cascad属性
session.save(person);*/
/**
* 测试加载操作
*/
Person p=(Person)session.load(Person.class, 1);
System.out.println(p);
System.out.println(p.getIdCard());
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
t.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}
Session session = HibernateUtils.getSession();
Transaction t = session.beginTransaction();
try {
/**
* 测试插入操作
*/
/* IdCard idCard = new IdCard();
idCard.setCardNo("1234567890");
Person person = new Person();
person.setName("张三");
person.setIdCard(idCard);
//不会出现TransientObjectException异常,因为一对一主键关联映射中默认了cascad属性
session.save(person);*/
/**
* 测试加载操作
*/
Person p=(Person)session.load(Person.class, 1);
System.out.println(p);
System.out.println(p.getIdCard());
t.commit();
} catch (HibernateException e) {
e.printStackTrace();
t.rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}
7.测试结果:(打印对象时,我覆盖了Person和IdCard类的toString()方法)
Hibernate: select hibernate_sequence.nextval from dual
Person:张三
Idcard:1234567890
Hibernate: insert into sxt_hibernate_idCard (cardNo, id) values (?, ?)
Hibernate: insert into sxt_hibernate_person (name, id) values (?, ?)
Person:张三
Idcard:1234567890
Hibernate: insert into sxt_hibernate_idCard (cardNo, id) values (?, ?)
Hibernate: insert into sxt_hibernate_person (name, id) values (?, ?)