一对一关联映射有两种方式:主键关联和外键关联
以夫妻为例(Husband----Wife)
单向关联实体类:
Husband.java
package com.java.hibernate;
public class Husband {
private int id;
private String name;
private Wife wife;
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Wife.java
package com.java.hibernate;
public class Wife {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
双向关联实体类:
Husband.java
package com.java.hibernate;
public class Husband {
private int id;
private String name;
private Wife wife;
public Wife getWife() {
return wife;
}
public void setWife(Wife wife) {
this.wife = wife;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Wife.java
package com.java.hibernate;
public class Wife {
private int id;
private String name;
private Husband husband;
public Husband getHusband() {
return husband;
}
public void setHusband(Husband husband) {
this.husband = husband;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
单向主键关联:
Husband映射文件:
<?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.java.hibernate.Husband" table="t_husband">
<id name="id">
<!-- 采用foreign生成策略,forgeign会取得关联对象的标识 -->
<generator class="foreign">
<!-- property只关联对象 -->
<param name="property">wife</param>
</generator>
</id>
<property name="name"></property>
<!--
one-to-one指示hibernate如何加载其关联对象,默认根据主键加载
也就是拿到关系字段值,根据对端的主键来加载关联对象
constrained="true表示,当前主键(husband的主键)还是一个外键
参照了对端的主键(wife的主键),也就是会生成外键约束语句
-->
<one-to-one name="wife" constrained="true"/>
</class>
</hibernate-mapping>
Wife映射文件:
<?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.java.hibernate.Wife" table="t_wife">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>
测试类
package com.java.hibernate;
import junit.framework.TestCase;
import org.hibernate.Session;
public class Test extends TestCase{
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Wife wife = new Wife();
wife.setName("昆凌");
Husband husband = new Husband();
husband.setName("周杰伦");
//建立关联
husband.setWife(wife);
//没有抛出TransientObjectException
//是由一对一关联映射的特性决定的,它必须先保存关联对象wife
//这样它采用foreign映射策略才能取得关联对象的标识
//也就是它默认了cascade属性
session.save(husband);
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();
Wife wife = new Wife();
wife.setName("昆凌");
Husband husband = new Husband();
husband.setName("周杰伦");
//建立关联
husband.setWife(wife);
//只能将IdCard保存,不能将Person保存
//因为关系的维护端在Person端,IdCard不知道Person的存在
session.save(wife);
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();
Husband husband = (Husband)session.load(Husband.class, 1);
System.out.println("husband.name=" + husband.getName());
System.out.println("husband.wife=" + husband.getWife().getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}
双向主键关联:
参照单向主键关联,只需修改Wife映射文件:
<?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.java.hibernate.Wife" table="t_wife">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<one-to-one name="husband"></one-to-one>
</class>
</hibernate-mapping>
测试类:
package com.java.hibernate;
import junit.framework.TestCase;
import org.hibernate.Session;
public class Test extends TestCase {
public void testLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Wife wife = (Wife) session.load(Wife.class, 1);
System.out.println(wife.getName());
System.out.println(wife.getHusband().getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}
单向外键关联:
一对一唯一外键关联映射其实是多对一的特例,采用<many-to-one>标签来映射,指定多的一端unique为true,这样就限制了多的一端的多重性唯一,就是这样来映射的。
Husband映射文件
<?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.java.hibernate.Husband" table="t_husband">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<many-to-one name="wife" unique="true"></many-to-one>
</class>
</hibernate-mapping>
Wife映射文件
<?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.java.hibernate.Wife" table="t_wife">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>
测试类
package com.java.hibernate;
import junit.framework.TestCase;
import org.hibernate.Session;
public class Test extends TestCase{
public void testSave1() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Wife wife = new Wife();
wife.setName("昆凌");
Husband husband = new Husband();
husband.setName("周杰伦");
//建立关联
husband.setWife(wife);
//抛出TransientObjectException
//因为IdCard为Transient状态
session.save(husband);
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();
Wife wife = new Wife();
wife.setName("昆凌");
session.save(wife);
Husband husband = new Husband();
husband.setName("周杰伦");
//建立关联
husband.setWife(wife);
session.save(husband);
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();
Husband husband = (Husband)session.load(Husband.class, 2);
System.out.println("husband.name=" + husband.getName());
System.out.println("husband.wife=" + husband.getWife().getName());
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
}
双向外键关联:
一对一唯一外键关联双向采用<one-to-one>标签映射,必须指定<one-to-one>标签中的property-ref属性为关系字段的名称
参照单向外键关联,只需修改Wife映射 文件
<?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.java.hibernate.Wife" table="t_wife">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<one-to-one name="husband" property-ref="wife"></one-to-one>
</class>
</hibernate-mapping>
测试类:
package com.java.hibernate;
import junit.framework.TestCase;
import org.hibernate.Session;
public class Test extends TestCase {
public void testLoad() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Wife wife = (Wife) session.load(Wife.class, 1);
System.out.println(wife.getName());
System.out.println(wife.getHusband().getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
}
}