Java的Hibernate框架中的雙向主鍵聯系關系與雙向外鍵聯系關系。本站提示廣大學習愛好者:(Java的Hibernate框架中的雙向主鍵聯系關系與雙向外鍵聯系關系)文章只能為提供參考,不一定能成為您想要的結果。以下是Java的Hibernate框架中的雙向主鍵聯系關系與雙向外鍵聯系關系正文
1、雙向主鍵聯系關系
雙向的主鍵聯系關系實際上是單向一對一主鍵聯系關系的一種特別情形,只不外要在聯系關系對象的兩頭的映照文件中都要停止<one-to-one>的設置裝備擺設,別的還要在主映照的主鍵一端采取foreign外鍵聯系關系屬性。
這裡異樣應用Person和IdCard來評論辯論,一小我對應著一個獨一的身份證,並且一個身份證也獨一映照著一小我,所以這就發生了雙向的聯系關系關系,Person的主鍵異樣也是IdCard的主鍵,分離是主鍵的同時也是外鍵,這類聯系關系關系成為雙向一對一映照,表示到關系模子中可以下圖:
圖中的兩個表采取了主鍵聯系關系,person的主鍵是idCard的主鍵,所以它們之間組成了朱外鍵的束縛關系,而且包管獨一性,映照到對象模子中,改變為person類和idCard類的一對一關系,以下圖:
這類一對一的關系上篇文章中也有講到用的是<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)
生成的表構造以下圖:
在兩張表中同時生成了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); } }
拔出的數據以下圖:
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); } }
運轉下面的測試辦法,在掌握台打印的相干內容以下:
2、雙向外鍵聯系關系
雙向的外鍵聯系關系可以懂得為外鍵聯系關系的一種特別情形,這類特別重要是因為它是一種雙向的對應關系,在前篇文章中提到假如想要在一張表中添加一個外鍵字段的話可使用<many-to-one>標簽,它會關系模子中生成對應的外鍵列。這裡想要完成雙向的外鍵聯系關系就必需應用該標簽。
1、對象模子
先來看對象模子,人和身份證屬於一對一的關系,一小我對應著一個身份,所以它們之間的多重性是一對一的,而且這類對應關系是雙向的。所以它的對象模子同雙向主鍵一對一是雷同的,以下圖:
2、關系模子
對應的關系模子會產生很年夜的變更,一對一的外鍵聯系關系關系會在一張表中生成對應的外鍵,拿到人和身份證下去說也就是人的關系模子中會有一個身份證號的主鍵列,它們之間構成了雙向的一對一的情形,以下圖:
它們之間的對應關系就是上圖中看到的,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語句起首是創立的表,在建表時指定了主鍵列,創立完成後修正了兩個表指定外鍵屬性,構成一對一的關系。
編寫測試辦法,采取單位測試,加載兩個類的對象,並分離從對象的一端獲得另外一個對象
//加載對象,應用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>標簽只是指清楚明了一對一的關系它只是指明一個對象若何加載另外一個對象其實不在關系模子中添加新列。下篇文章將會對一對多聯系關系睜開評論辯論。