【Java】Hibernate(五)关联映射之一对一

 【One to one】

       一对一关联映射包括主键关联,唯一外键关联两种,其中又分单向映射和双向映射两种。
                     

【主键单向】

       每个人都有对应自己身份的身份证,这是唯一的,这就是现实生活中最常见的一对一的例子。想通过Person得知对应的IDcard,对象图形中,关联是有方向的,只能通过Person找到IdCard。关联图形中,主键关联映射,就是让两个实体的主键一样。
主键关联的意思就是让两个对象具有相同的主键值,表名它们之间的一对一对应的关系,数据库表不会有额外的字段来维护它们之间的关系,仅仅通过表的主键来关联。但是主键的扩展性不太好,实际应用少。

                         

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 >
	<class name="com.bjpowernode.hibernate.Person" table="t_Person">
		<id name="id">
			<generator class="foreign">
			  <param name="property">idCard</param>
		    </generator>
		</id>
		<property name="name"/>
				
		<one-to-one name="idCard" constrained="true"/>
	</class>
</hibernate-mapping>

       <one-to-one> 指示Hibernate如何加载其关联对象,默认根据主键加载,也就是拿到关系字段值,根据对端主键来加载关联对象。其中 constrained="true" 表示 当前主键(person主键)还是一个外键,参照了对端的主键(idCard主键),会生成外键约束语句。采用foreign映射策略才能取得关联对象的标识。

One2OneTest代码:

package com.bjpowernode.hibernate;
import org.hibernate.Session;
import junit.framework.TestCase;


public class One2OneTest extends TestCase {
	
	public void testSave1(){
		Session session=null;
		try{
			session=HibernateUtils.getSession();
			session.beginTransaction();
			
			IdCard idCard = new IdCard();
			idCard.setCardNo("111111111111111");
			
			Person person=new Person();
			person.setName("辛巴");
			//建立关联
			person.setIdCard(idCard);
			//保存维护关系的那一端
			session.save(person);
			
			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();
			
			Person person=(Person)session.load(Person.class, 1);
			System.out.println("person.name="+person.getName());
			System.out.println("person.cardNo="+person.getIdCard().getCardNo());
			
			session.getTransaction().commit();
			
		}catch(Exception e){
			e.printStackTrace();
			session.getTransaction().rollback();
			
		}finally{
			HibernateUtils.closeSession(session);
		}
	}

}

       在运行testSave1时,没有抛出transientObjectException。这是由一对一关联映射的特性决定的,它必须先保存关联对象IdCard,这样它采用foreign映射策略才能取得关联对象的标识,也就是它默认了cascade属性。

       因为person端维护了关系,所以运行testLoad1,查person的时候就能顺带也把idcard查出来。


【主键双向】


       想通过Person找到对应的IDcard,也想通过IDcard找到对应的Person,使用主键双向。如下图:

                                                                                                                                 

       主键双向映射,需要在 idcard端加入< one- to -one >标签,指示hibernate将关联对象person根据主键加载上来。< one- to -one > 不修改数据库,只是告诉Hibernate如何加载数据。不影响存储,只影响加载。而我们以后要介绍的<Many- to -one> 是会修改数据库的,需要加字段。

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 >
	<class name="com.bjpowernode.hibernate.IdCard" table="t_idCard">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="cardNo"/>
		<!-- 指示hibernate将关联对象person根据主键加载上来 -->
		<one-to-one name="person"/>				
	</class>
</hibernate-mapping>


【唯一外键单向】

       我们想通过Person得知对应的IDcard,也可以使用单向唯一外键关联映射,其实是多对一特例,这种方法相对主键关联扩展性要好一些,所以也比较常用。

                                                


       具体实现需要在Person.hbm.xml动手脚。采用<many- to- one> 标签来映射,指定多一端unique 为 true ,限制多的一端多重性为一即可。


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 >
	<class name="com.bjpowernode.hibernate.Person" table="t_Person">
		<id name="id">
			<generator class="native"/>
			 
		</id>
		<property name="name"/>
		<!-- 多对一特例 -->
		<many-to-one name="idCard" unique="true"/>	
	</class>
</hibernate-mapping>

【 唯一外键双向】 

       想通过Person找到对应的idCard,也根据idCard找到对应的Person,还想扩展性好一些,那就使用唯一外键双向关联。
                                             

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 >
	<class name="com.bjpowernode.hibernate.Person" table="t_Person">
		<id name="id">
			<generator class="native"/>
			 
		</id>
		<property name="name"/>
		<many-to-one name="idCard" unique="true"/>
	
	</class>
</hibernate-mapping>


       在Person一端依旧使用<many-to-one>即多对一的特例来实现一对一。

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 >
	<class name="com.bjpowernode.hibernate.IdCard" table="t_idCard">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="cardNo"/>
		<one-to-one name="person" property-ref="idCard"/>
		
	</class>
</hibernate-mapping>

       在IdCard一端,则采用 <one- to- one> 标签映射,必须指定 <one- to- one> 标签中的property-ref属性为关系字段的名称。这样使用了唯一外键,实现了双向关联。

【小结】

       关于一对一,本文一共介绍了4种关联情况,常用的是唯一外键单双向管理。希望能对看官有帮助,下篇继续看hibernate的关联大法~


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值