前面两篇博文里记录了Hibernate级联操作的一对多关联关系和一对多双向自身关联关系,这一篇记录的是一对一关联关系,例如一个人对应一张身份证,一对一的关系又可以分为共用主键的方式和一对多的特殊情况(使用外键关联)这两种,下面分别记录这两种方式,
一、共用主键的一对一关系
这里举例人和身份证的一对一关系,共用主键即certificate表中的id值,用的是person表中的id,下面是两张表的结构:
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(); } } }上面的代码执行后,在数据库中查询的信息如下:
可以看到,在保存person对象的时候,hibernate自动为person表生成了uuid类型的id,并且将该id用在了certificate表,所以上面的两个表中对应的两条数据的id是一样的,这就是一对一关联关系中的一种:共用主键
二、使用外键关联的一对一关系,这种一对一的关系是一对多关系的一种特殊情况,从下面的配置文件中就可以看出来,这里就不放java bean的代码了,还是有两个实体类:Person和Certificate,他们含有如下图所示的成员变量:
下面是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,这种形式的一对一关联关系,是一对多的关联关系的特例,即一对多的“多”的那一方,只有唯一的一个与“一”的那一方相对,下一篇将记录多对多的关联关系。
源码下载点击这里