Hibernate学习之级联操作3——一对一关联关系

前面两篇博文里记录了Hibernate级联操作的一对多关联关系和一对多双向自身关联关系,这一篇记录的是一对一关联关系,例如一个人对应一张身份证,一对一的关系又可以分为共用主键的方式和一对多的特殊情况(使用外键关联)这两种,下面分别记录这两种方式,

一、共用主键的一对一关系

这里举例人和身份证的一对一关系,共用主键即certificate表中的id值,用的是person表中的id,下面是两张表的结构:

Hibernate学习之级联操作3——一对一关联关系_第1张图片

Hibernate学习之级联操作3——一对一关联关系_第2张图片

person表中有两个字段:id和name,certificate表中也是两个字段:id和cetificate_number,这两个表通过共用id关联起来,即通过person表中的id,可以查到certificate表中对应id的cetificate_number,下面是两个实体类,Person.java和Certificate.java:

package com.test.model;

public class Person {

	private String id;
	private String name;
	private Certificate idCard;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Certificate getIdCard() {
		return idCard;
	}

	public void setIdCard(Certificate idCard) {
		this.idCard = idCard;
	}

}


package com.test.model;

public class Certificate {

	private String id;
	private String number;
	private Person person;
	
	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public Person getPerson() {
		return person;
	}

	public void setPerson(Person person) {
		this.person = person;
	}

}
由于person和certificate是一对一的关系,一个人对应一个身份证,一个身份证也只对应一个人,所以在Person类中包含了一个Certificate类型的成员变量,在Certificate类中包含了一个Person类的成员变量,下面是两个类的hbm文件:

Person.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Person" table="person">
        <id name="id" unsaved-value="null" column="id">
            <generator class="uuid">
            </generator>
        </id>
        
        <property name="name" type="string">
        	<column name="name" length="20"></column>
        </property>
        
        <one-to-one name="idCard" fetch="join" class="com.test.model.Cetificate" cascade="all" ></one-to-one>
    </class>
</hibernate-mapping>

上面的Person.hbm.xml文件中需要注意的有:id指定了uuid类型,则插入数据时会自动为id字段生成uuid,one-to-one标签指定了一对一的类为Cetificate类且cascade属性为all,即对于person表的增删改查都会级联到certificate表

Certificate.hbm.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Cetificate" table="cetificate">
    
        <id name="id" type="string" column="id">
            <generator class="foreign" >
            	<param name="property">person</param>
            </generator>
        </id>
        
        <property name="number" column="cetificate_number" type="string"></property>
        
        <one-to-one name="person" class="com.test.model.Person" cascade="none" constrained="true" fetch="join"></one-to-one>
    </class>
</hibernate-mapping>
上面的配置文件中需要注意的是,cetificate表的id配置了foreign属性,且里面的param标签中配了person,这里的意思是,cetificate表的id来自于person表的id

下面是测试代码:

package com.test;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.test.model.Certificate;
import com.test.model.Person;

public class TestMain {

	public static void main(String[] args) {
		Person person = new Person();
		person.setName("zhangsan");
		Certificate card = new Certificate();
		card.setNumber("2134987123498298");
		card.setPerson(person);
		person.setIdCard(card);
		Session session = HibernateSessionFactory.getSession();
		Transaction trans = session.beginTransaction();
		try {
			session.save(person);
			trans.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			trans.rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
	}

}
上面的代码执行后,在数据库中查询的信息如下:

Hibernate学习之级联操作3——一对一关联关系_第3张图片

可以看到,在保存person对象的时候,hibernate自动为person表生成了uuid类型的id,并且将该id用在了certificate表,所以上面的两个表中对应的两条数据的id是一样的,这就是一对一关联关系中的一种:共用主键

二、使用外键关联的一对一关系,这种一对一的关系是一对多关系的一种特殊情况,从下面的配置文件中就可以看出来,这里就不放java bean的代码了,还是有两个实体类:Person和Certificate,他们含有如下图所示的成员变量:

         Hibernate学习之级联操作3——一对一关联关系_第4张图片

下面是Person.hbm.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Person" table="person">
        <id name="id" unsaved-value="null" column="id">
            <generator class="uuid">
            </generator>
        </id>
        
        <property name="name" type="string">
        	<column name="name" length="20"></column>
        </property>
        
        <one-to-one name="cer" fetch="join" class="com.test.model.Certificate" cascade="all" ></one-to-one>
    </class>
</hibernate-mapping>
这里的Person.hbm.xml与公用主键的方式中Person.hbm.xml没有区别,区别在于Certificate.hbm.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 
    Mapping file autogenerated by MyEclipse Persistence Tools
-->
<hibernate-mapping>
    <class name="com.test.model.Certificate" table="certificate">
        <id name="id" column="id">
            <generator class="uuid">
            </generator>
        </id>
        
        <property name="number" type="string">
        	<column name="number" length="20"></column>
        </property>
        
        <many-to-one name="person" class="com.test.model.Person" unique="true" cascade="none" column="person_id"></many-to-one>
    </class>
</hibernate-mapping>
在Certificate.hbm.xml文件中,指定了many-to-one标签,看似多对一的关系,实际上有了unique="true"的条件后,就变成了一对一的关系了,即一张身份证只能对应一个人,执行下面的测试代码后:

package com.test;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.test.model.Certificate;
import com.test.model.Person;

public class Test {

	public static void main(String[] args) {
		Person person = new Person();
		person.setName("lisi");
		
		Certificate cer = new Certificate();
		cer.setNumber("9817234987");
		cer.setPerson(person);
		person.setCer(cer);
		
		Session session = HibernateSessionFactory.getSession();
		Transaction trans = session.beginTransaction();
		try {
			session.save(person);
			trans.commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			trans.rollback();
		} finally {
			HibernateSessionFactory.closeSession();
		}
		
	}

}
在数据库中查看信息如下图所示:


可以看到,这两张表通过外键的形式关联起来了,certificate表中的person_id参照了person表的id,这种形式的一对一关联关系,是一对多的关联关系的特例,即一对多的“多”的那一方,只有唯一的一个与“一”的那一方相对,下一篇将记录多对多的关联关系。

源码下载点击这里




你可能感兴趣的:(Hibernate,级联,一对一关联关系)