【Hibernate步步爲營】--雙向關聯一對一映射詳解(二)

很不好意思,有兩天時間沒有更新博客文章了,不寫文章的日子還真是感覺很空洞啊,養成了寫文章的惡習想改也改不掉啊。說點題外話,前兩天收到一位朋友的私信,邀請筆者寫一篇有關OWS的文章,用來研究圖標工具的一種技術,很榮幸收到這位朋友的邀請,但是因爲這幾天開發的項目着急上線所以暫時沒有時間去研究,只能等這週末了,利用週末的時間來研究然後更新類似的技術文章。

         回到文章的正題,上篇文章討論了雙向主鍵關聯,它其實是一對一主鍵關聯的一種特殊情況,想要實現雙向的關聯就必須在映射文件的兩端同時配置<one-to-one>,另外還要在主映射的一端採用foreign外鍵關聯屬性。繼續討論雙向關聯的情況,在雙向關聯中還有一種外鍵關聯沒有討論,接下來將會詳細討論雙向外鍵關聯。


二、雙向外鍵關聯


        雙向的外鍵關聯可以理解爲外鍵關聯的一種特殊情況,這種特殊主要是由於它是一種雙向的對應關係,在前篇文章中提到如果想要在一張表中添加一個外鍵字段的話可以使用<many-to-one>標籤,它會關係模型中生成對應的外鍵列。這裏想要實現雙向的外鍵關聯就必須使用該標籤。


  1、對象模型


        先來看對象模型,人和身份證屬於一對一的關係,一個人對應着一個身份,所以它們之間的多重性是一對一的,並且這種對應關係是雙向的。所以它的對象模型同雙向主鍵一對一是相同的,如下圖:


    2、關係模型


        對應的關係模型會發生很大的變化,一對一的外鍵關聯關係會在一張表中生成對應的外鍵,拿到人和身份證上來說也就是人的關係模型中會有一個身份證號的主鍵列,它們之間形成了雙向的一對一的情況,如下圖:


         它們之間的對應關係就是上圖中看到的,person表中有idCard表的主鍵,形成了一對一的外鍵關聯關係,而且是雙向的,也就是說通過person能夠獲取到idCard,另外通過idCard也能獲取到person。

         Person對象和IdCard對象內的代碼同上篇文章中的對象代碼一致,不在做代碼羅列,唯一不同的是映射文件中的配置問題。


   3、映射文件


         idCard.hbm.xml映射文件,idCard表不是映射的主表,所以在做一對一的映射時需要使用的是<one-to-one>標籤來配置,並且需要制定person關係模型中的外鍵屬性,具體代碼如下:

[html] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0"?> 
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
  4. <!-- Generated 2014-5-18 22:27:43 by Hibernate Tools 3.4.0.CR1 --> 
  5. <hibernate-mapping> 
  6.     <class name="com.src.hibernate.IdCard" table="IDCARD"> 
  7.         <id name="id" type="int"> 
  8.             <generator class="native" /> 
  9.         </id> 
  10.         <property name="cardNo" type="java.lang.String"> 
  11.             <column name="CARDNO" /> 
  12.         </property> 
  13.          
  14.         <one-to-one name="person" property-ref="idCard"></one-to-one> 
  15.     </class> 
  16. </hibernate-mapping> 
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-5-18 22:27:43 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.src.hibernate.IdCard" table="IDCARD">
        <id name="id" type="int">
            <generator class="native" />
        </id>
        <property name="cardNo" type="java.lang.String">
            <column name="CARDNO" />
        </property>
        
        <one-to-one name="person" property-ref="idCard"></one-to-one>
    </class>
</hibernate-mapping>

        Person.hbm.xml映射文件,person表是映射的主表,需要在該表中添加一個外鍵屬性列來標示idCard表,所以這裏需要使用<many-to-one>標籤,在person對象中生成相應的外鍵,並且還要使用unique標明屬性唯一。

[html] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
  1. <?xml version="1.0"?> 
  2. <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
  3. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
  4. <!-- Generated 2014-5-18 22:27:43 by Hibernate Tools 3.4.0.CR1 --> 
  5. <hibernate-mapping> 
  6.     <class name="com.src.hibernate.Person" table="PERSON"> 
  7.         <id name="id" type="int" column="personId"> 
  8.             <generator class="native" /> 
  9.         </id> 
  10.         <property name="name" type="java.lang.String"> 
  11.             <column name="NAME" /> 
  12.         </property> 
  13.          
  14.         <many-to-one name="idCard" column="idCardNo" unique="true" not-null="true"></many-to-one> 
  15.     </class> 
  16. </hibernate-mapping> 
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-5-18 22:27:43 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.src.hibernate.Person" table="PERSON">
        <id name="id" type="int" column="personId">
            <generator class="native" />
        </id>
        <property name="name" type="java.lang.String">
            <column name="NAME" />
        </property>
        
        <many-to-one name="idCard" column="idCardNo" unique="true" not-null="true"></many-to-one>
    </class>
</hibernate-mapping>

      對象的映射文件配置完成,接下來生成關係模型,SQL語句如下:

[sql] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
  1. alter table PERSON drop foreign key FK8C768F55794A52CA 
  2. drop table if exists IDCARD 
  3. drop table if exists PERSON 
  4. create table IDCARD (id integer not null auto_increment, CARDNO varchar(255), primary key (id)) 
  5. create table PERSON (personId integer not null auto_increment, NAME varchar(255), idCardNo integer not null unique, primary key (personId)) 
  6. alter table PERSON add index FK8C768F55794A52CA (idCardNo), add constraint FK8C768F55794A52CA foreign key (idCardNo) references IDCARD (id) 
alter table PERSON drop foreign key FK8C768F55794A52CA
drop table if exists IDCARD
drop table if exists PERSON
create table IDCARD (id integer not null auto_increment, CARDNO varchar(255), primary key (id))
create table PERSON (personId integer not null auto_increment, NAME varchar(255), idCardNo integer not null unique, primary key (personId))
alter table PERSON add index FK8C768F55794A52CA (idCardNo), add constraint FK8C768F55794A52CA foreign key (idCardNo) references IDCARD (id)

        生成的SQL語句首先是創建的表,在建表時指定了主鍵列,創建完成後修改了兩個表指定外鍵屬性,形成一對一的關係。

         編寫測試方法,採用單元測試,加載兩個類的對象,並分別從對象的一端獲取另一個對象

[java] view plaincopyprint?在CODE上查看代碼片派生到我的代碼片
  1. //加載對象,使用IdCard對象裝載person對象 
  2. public void testLoad1(){ 
  3.     Session session=null
  4.      
  5.     try
  6.         session=HibernateUtils.getSession(); 
  7.         session.beginTransaction(); 
  8.          
  9.         //獲取IdCard對象,在IdCard中獲取與該對象唯一關聯的person對象 
  10.         IdCard idcard=(IdCard)session.load(IdCard.class,1); 
  11.         System.out.println("person.Id= "+idcard.getPerson().getId()); 
  12.         System.out.println("idCard.person.name= "+idcard.getPerson().getName()); 
  13.          
  14.         //獲取Person對象,在Person對象中獲取與它唯一關聯的IdCard對象 
  15.         Person person=(Person)session.load(Person.class,1); 
  16.         System.out.println("idCard.id: "+person.getIdCard().getId()); 
  17.         System.out.println("idCard.cardNo: "+person.getIdCard().getCardNo()); 
  18.          
  19.         //提交事務 
  20.         session.getTransaction().commit(); 
  21.     }catch(Exception e){ 
  22.         e.printStackTrace(); 
  23.         session.getTransaction().rollback(); 
  24.     }finally
  25.         HibernateUtils.closeSession(session); 
  26.     } 
//加載對象,使用IdCard對象裝載person對象
public void testLoad1(){
	Session session=null;
	
	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();
		
		//獲取IdCard對象,在IdCard中獲取與該對象唯一關聯的person對象
		IdCard idcard=(IdCard)session.load(IdCard.class,1);
		System.out.println("person.Id= "+idcard.getPerson().getId());
		System.out.println("idCard.person.name= "+idcard.getPerson().getName());
		
		//獲取Person對象,在Person對象中獲取與它唯一關聯的IdCard對象
		Person person=(Person)session.load(Person.class,1);
		System.out.println("idCard.id: "+person.getIdCard().getId());
		System.out.println("idCard.cardNo: "+person.getIdCard().getCardNo());
		
		//提交事務
		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

        生成的內容:




        對比兩種映射關係,主鍵和外鍵兩種映射,都是雙向的映射關係,需要在對象的兩端同時配置映射關係,不同的是主鍵只需要使用<one-to-one>因爲它不需要生成屬性列,但是必須對錶的主鍵採用foreign的主鍵生成策略,並標示外鍵對象;外鍵的生成策略則需要採用<many-to-one>標籤來生成新的外鍵列。


結語


      雙向關聯中的一對一映射至此已經討論完成,兩篇文章主要討論了雙向關聯中的兩種用法,其實還是很簡單的,記住一句話想要生成外鍵就使用<many-to-one>標籤,如果唯一那就添加unique屬性,<one-to-one>標籤只是指明瞭一對一的關係它只是指明一個對象如何加載另一個對象並不在關係模型中添加新列。下篇文章將會對一對多關聯展開討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章