国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java的Hibernate框架中的雙向主鍵關聯與雙向外鍵關聯

2019-11-26 14:10:33
字體:
來源:轉載
供稿:網友

一、雙向主鍵關聯
雙向的主鍵關聯其實是單向一對一主鍵關聯的一種特殊情況,只不過要在關聯對象的兩端的映射文件中都要進行<one-to-one>的配置,另外還要在主映射的主鍵一端采用foreign外鍵關聯屬性。
這里同樣使用Person和IdCard來討論,一個人對應著一個唯一的身份證,而且一個身份證也唯一映射著一個人,所以這就產生了雙向的關聯關系,Person的主鍵同樣也是IdCard的主鍵,分別是主鍵的同時也是外鍵,這種關聯關系成為雙向一對一映射,表現到關系模型中可如下圖:

2016618181616061.png (592×196)

圖中的兩個表采用了主鍵關聯,person的主鍵是idCard的主鍵,所以它們之間構成了朱外鍵的約束關系,并且保證唯一性,映射到對象模型中,轉變為person類和idCard類的一對一關系,如下圖:

2016618181641381.png (414×131)

這種一對一的關系上篇文章中也有講到用的是<one-to-one>標簽,另外這種一對一映射又是雙向的,所以要在兩個對象之間同時配置<one-to-one>,首先來看idCard對應的類代碼和映射文件代碼。

1、IdCard對應的信息
IdCard.java類,IdCard類和Person類之間有一對一的關聯關系所以要在IdCard類中添加對應的Person屬性,這是為了能在映射文件中的外鍵中添加對應的屬性,設置對應的外鍵關聯類。

package com.src.hibernate;  public class IdCard {      //id屬性   private int id;   public int getId() {     return id;   }   public void setId(int id) {     this.id = id;   }      //卡號屬性   private String cardNo;   public String getCardNo() {     return cardNo;   }   public void setCardNo(String cardNo) {     this.cardNo = cardNo;   }      //卡號對應的人   private Person person;   public Person getPerson(){     return person;   }   public void setPerson(Person person){     this.person=person;   } } 

IdCard.hbm.xml映射文件,在映射文件中添加外鍵屬性person,并添加對應的<one-to-one>標簽,目的是強制約束person類來實現一對一的映射關系,最后在映射中將constrained屬性設為true,保證強制約束關系。

<?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-15 23:47:00 by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping>   <class name="com.src.hibernate.IdCard" table="IDCARD">     <id name="id" type="int" column="personId">       <generator class="foreign">         <param name="property">person</param>       </generator>     </id>          <property name="cardNo" type="string" column="cardno"></property>     <one-to-one name="person" constrained="true"></one-to-one>   </class> </hibernate-mapping> 

2、Person對應的信息
Person.java類,在該類中除了添加基本的屬性外還要添加對應的IdCard類作為屬性,因為它們之間是一對一的雙向關聯關系,所以在Person類中同樣要添加IdCard類,相同的道理IdCard類中同樣添加了Person類屬性。

package com.src.hibernate;  public class Person {      //id號   private int id;   public int getId() {     return id;   }   public void setId(int id) {     this.id = id;   }      //姓名   private String name;   public String getName() {     return name;   }   public void setName(String name) {     this.name = name;   }      //idCard   private IdCard idcard;   public IdCard getIdcard() {     return idcard;   }   public void setIdcard(IdCard idcard) {     this.idcard = idcard;   } } 

Person.hbm.xml映射文件,該文件中主鍵生成策略沒有特殊的要求,因為它和IdCard類相互制約的關系,它的主鍵和外鍵都是IdCard的主鍵,另外因為是一對一關系所以要在映射文件中添加<one-to-one>標簽來標示。

<?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-15 23:47:00 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"></generator>     </id>          <property name="name" type="string" column="personName"></property>   <!--   one-to-one標簽指示Hibernate如何加載其關聯對象,默認根據主鍵加載,也就是拿到關系字段值,根據對端的主鍵來加載關聯對象    -->   <one-to-one name="idcard"></one-to-one>   </class> </hibernate-mapping> 

3、Hibernate映射文件
上面的類和映射文件配置好后接下來要在Hibernate.cfg.xml中配置與數據庫映射的信息,需要將兩個配置文件添加到Hibernate配置文件中,這樣在生成對應的數據庫時才能找到對應的生成項。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration>   <session-factory>     <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>     <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_one2one_pk1</property>     <property name="hibernate.connection.username">root</property>     <property name="hibernate.connection.password">1234</property>     <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>          <mapping resource="com/src/hibernate/Person.hbm.xml"/>     <mapping resource="com/src/hibernate/IdCard.hbm.xml" ></mapping>   </session-factory> </hibernate-configuration> 

 4、生成結果
配置完成后就可以將上面的內容生成對應的數據庫了,在數據庫中它會按照配置的內容生成相應的表結構,在表中有相應的外鍵和主鍵字段。生成表結構時Hibernate會在控制臺輸出相應的SQL語句,如下:

alter table IDCARD drop foreign key FK806F76ABAC038CD8 drop table if exists IDCARD drop table if exists PERSON create table IDCARD (personId integer not null, cardno varchar(255), primary key (personId)) create table PERSON (personId integer not null auto_increment, personName varchar(255), primary key (personId)) alter table IDCARD add index FK806F76ABAC038CD8 (personId), add constraint FK806F76ABAC038CD8 foreign key (personId) references PERSON (personId) 

生成的表結構如下圖:

2016618182053824.png (677×394)

在兩張表中同時生成了personId主鍵,并且也是相應的外鍵,它同時限制約束了兩張表的主鍵相同且唯一。

5、寫入加載測試
生成表后測試下對表的寫入和從表中讀取數據,編寫相應的測試類,測試采用的是單元測試,編寫對應的測試方法。
5.1 寫入測試
在寫入到數據庫時一定要注意寫入的兩個對象都要轉化到對應的Trainent狀態,否則會出現狀態轉化的錯誤,測試代碼如下:

public void testSave1(){   Session session=null;   try{     //創建一個會話對象     session=HibernateUtils.getSession();     //開啟會話事務     session.beginTransaction();          //創建person對象,并保存     Person person=new Person();     person.setName("zhangsan");     session.save(person);          //創建idCard對象,并保存     IdCard idcard=new IdCard();     idcard.setCardNo("1111111111111");     idcard.setPerson(person);     session.save(idcard);          //提交事務,修改數據庫     session.getTransaction().commit();        }catch(Exception e){     //打印錯誤信息     e.printStackTrace();     //業務回滾     session.getTransaction().rollback();   }finally{     //關閉會話     HibernateUtils.closeSession(session);   } } 

插入的數據如下圖:

2016618182112300.png (677×394)

5.2 加載測試
編寫加載方法,因為關聯關系是雙向的,所以相應的加載操作應該是通過一端加載另一端,也就是獲取對應的Person類,并通過Person類來獲取對應的IdCard信息,相反的也要成立,代碼如下:

public void testLoad1(){   Session session=null;   try{     //創建一個會話對象     session=HibernateUtils.getSession();     //開啟會話事務     session.beginTransaction();          //獲取person對象,并保存     Person person=(Person)session.load(Person.class,5);     System.out.println("IdCard.Id: "+person.getIdcard().getId());     System.out.println("IdCard.cardno: "+person.getIdcard().getCardNo());          //創建idCard對象,并保存     IdCard idcard=(IdCard)session.load(IdCard.class, 5);     System.out.println("Person.Id: "+idcard.getPerson().getId());     System.out.println("Person.name: "+idcard.getPerson().getName());          //提交事務,修改數據庫     session.getTransaction().commit();        }catch(Exception e){     //打印錯誤信息     e.printStackTrace();     //業務回滾     session.getTransaction().rollback();   }finally{     //關閉會話     HibernateUtils.closeSession(session);   } } 

運行上面的測試方法,在控制臺打印的相關內容如下:

2016618182218465.png (982×182)

二、雙向外鍵關聯
雙向的外鍵關聯可以理解為外鍵關聯的一種特殊情況,這種特殊主要是由于它是一種雙向的對應關系,在前篇文章中提到如果想要在一張表中添加一個外鍵字段的話可以使用<many-to-one>標簽,它會關系模型中生成對應的外鍵列。這里想要實現雙向的外鍵關聯就必須使用該標簽。
1、對象模型
先來看對象模型,人和身份證屬于一對一的關系,一個人對應著一個身份,所以它們之間的多重性是一對一的,并且這種對應關系是雙向的。所以它的對象模型同雙向主鍵一對一是相同的,如下圖:

2016618182236440.png (414×131)

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

2016618182252322.png (650×210)

它們之間的對應關系就是上圖中看到的,person表中有idCard表的主鍵,形成了一對一的外鍵關聯關系,而且是雙向的,也就是說通過person能夠獲取到idCard,另外通過idCard也能獲取到person。
Person對象和IdCard對象內的代碼同上篇文章中的對象代碼一致,不在做代碼羅列,唯一不同的是映射文件中的配置問題。
3、映射文件
idCard.hbm.xml映射文件,idCard表不是映射的主表,所以在做一對一的映射時需要使用的是<one-to-one>標簽來配置,并且需要制定person關系模型中的外鍵屬性,具體代碼如下:

<?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標明屬性唯一。

<?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語句如下:

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語句首先是創建的表,在建表時指定了主鍵列,創建完成后修改了兩個表指定外鍵屬性,形成一對一的關系。

2016618182310444.png (683×291)

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

//加載對象,使用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);   } } 

生成的內容:

2016618182332548.png (299×94)

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

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

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 同心县| 吐鲁番市| 广德县| 锦州市| 白朗县| 亚东县| 南投县| 吉安市| 玉林市| 涟水县| 宁津县| 定陶县| 垣曲县| 普定县| 新余市| 若羌县| 青神县| 铜鼓县| 建水县| 竹北市| 湖北省| 库车县| 朝阳区| 汾西县| 鸡东县| 沙河市| 阿合奇县| 台东市| 拜城县| 江门市| 常德市| 封丘县| 庆元县| 马关县| 临清市| 泸州市| 东丽区| 通海县| 东方市| 云安县| 莱芜市|