【Hibernate框架】關聯映射(一對一關聯映射)

1、整理思路:html

         以前,小編總結過Mybatis的關聯映射,接下來,再來總結一下hibernate的相關的關聯映射,直接上圖:java

這張圖,就是小編整理總結整個Hibernate的關聯映射的一個大體思路。sql

 

2、名詞解釋「session

一、單向關聯:很簡單,就是一個對象依賴於另外一個對象。app

二、雙向關聯:兩個對象互相依賴。ssh

 

3、一對一(one-to-one)關聯映射:oop

       所謂的一對一,大白話理解就是一個物件擁有的某種附屬物件能並且只能擁有一件。舉個例子就是做爲學生,一個學生只能擁有一個有效的學生證,一個堂堂正正的中國公民也只能擁有一張有效的身份證。這就是一對一。接下來,咱們就利用在職學生爲例,說一下一對一映射。測試

 

在Hibernate中有兩種方式能實現一對一映射,分別是:fetch

一、主鍵關聯;this

二、惟一外鍵關聯。

 

4、逐一介紹:

4.一、一對一單向關聯映射

4.1.一、一對一單向關聯映射——主鍵關聯

核心:一個對象依賴於另外一個對象。舉例:根據學生,找到對應的有效學生證。

Po對象設計:

StudentCard.Java:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class StudentCard{  
  2.        private int id;  
  3.        private String cardNo;  
  4.        //getter\setter方法  
  5. }  
Student.java:

 

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class Student{  
  2.      private int id;  
  3.      private String name;  
  4.      private StudentCard studentCard;  
  5.      //getter\setter  
  6. }  

 

 

映射文件:

StudentCard.hbm.xml

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.StudentCard" table="t_studentCard">  
  3.         <id name="id">  
  4.             <generator class="native"/>  
  5.         </id>  
  6.         <property name="cardNo"/>  
  7.     </class>  
  8. </hibernate-mapping>  

 

Student.hbm.xml

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.Person" table="t_student">  
  3.         <id name="id" type="int">  
  4.             <generator class="foreign">  
  5.                 <param name="property">studentCard</param>  
  6.             </generator>  
  7.         </id>  
  8.         <one-to-one name="studentCard" constrained="true"/>  
  9.         <property name="name"/>  
  10.     </class>  
  11. </hibernate-mapping>  

 

分析:核心<one-to-one name="studentCard" constrained="true"/>,表示一個Student對應一個StudentCard。constrained=」true」表示t_student表的主鍵上同時有個外鍵指向被關聯的表(t_studentCard)的主鍵,會對錶t_student建立約束,約束t_student的id只能跟studentCard的主鍵同樣,也就是說,Student上的id既是主鍵也是外鍵。

測試

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. session.beginTransaction();  
  2. StudentCard studentCard=new StudentCard();  
  3. studentCard.setCardNo("12050242013");//我在學校裏的學號  
  4. Student student=new Student();  
  5. student.setName("Davie");  
  6. person.setstudentCard(student);  
  7. session.save(person);  
  8. session.getTransaction().commit();  

 

這時,會先插入一條StudentCard信息,而後再插入Student信息:

 

[sql]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. insert into t_studentCard (cardNo) values (?)  
  2. insert into t_student (name, id) values (?, ?)  
4.2.二、一對一單向關聯映射——惟一外鍵關聯

 

核心:惟一外鍵關聯,就是給一對一關聯關係中某個對象加一個外鍵。舉例:給Student表添加一個外鍵,指向StudentCard的主鍵,並且外鍵惟一,這樣也就達到了一對一映射的效果。

 

Po對象設計:

StudentCard.java:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class StudentCard{  
  2.     private int id;  
  3.     private String cardNo;  
  4.     //getter\setter方法  
  5. }  

 

 

Student.java:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class Student{  
  2.       private int id;  
  3.       private String name;  
  4.       private StudentCard studentCard;  
  5.       //getter\setter  
  6. }  
映射文件:

 

 

StudentCard.hbm.xml

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.StudentCard" table="t_studentCard">  
  3.         <id name="id">  
  4.             <generator class="native"/>  
  5.         </id>  
  6.         <property name="cardNo"/>  
  7.     </class>  
  8. </hibernate-mapping>  
Student.hbm.xml

 

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.Person" table="t_student">  
  3.         <id name="id" type="int">  
  4.             <generator class="foreign">  
  5.                 <param name="property">studentCard</param>  
  6.             </generator>  
  7.         </id>  
  8.         <many-to-one name="studentCard" unique="true"/><!--unique="true"會對此外鍵生成惟一約束-->  
  9.         <property name="name"/>  
  10.     </class>  
  11. </hibernate-mapping>  

 

分析:

       這裏與主鍵關聯還有點不同,t_student的主鍵生成策略是native,再也不以未見形式關聯到t_studentCard的主鍵,用<many-to-one>標籤與t_idcard創建多對一的關係,這樣就能夠在t_student中生成一個外鍵關聯到t_studentCard的主鍵。

       這時候若是還用上面的測試代碼進行測試,就會報錯:「org.hibernate.TransientObjectException: object references an unsaved transient instance」

由於t_student的主鍵生成策略是native,和t_studentCard無關,而studentCard並無變成TransientObject,因此,咱們必需要先將studentCard變成持久化對象:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. session.beginTransaction();  
  2. StudentCard studentCard=new StudentCard();  
  3. studentCard.setCardNo("12050242013");//我在學校裏的學號  
  4. session.save(studentCard);  
  5. Student student=new Student();  
  6. student.setName("Davie");  
  7. person.setstudentCard(student);  
  8. session.save(person);  
  9. session.getTransaction().commit();  

 

4.二、一對一雙向關聯映射

4.2.1一對一雙向關聯映射——主鍵關聯

核心:兩個對象之間,相互依賴

Po對象

 

StudentCard.java

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class StudentCard{  
  2.    private int id;  
  3.    private String cardNo;  
  4.    private Student student;  
  5.    //getter\setter方法  
  6. }  

 

Student.java

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class Student{  
  2.     private int id;  
  3.     private String name;  
  4.     private StudentCard studentCard;  
  5.     //getter\setter  
  6. }  

 

配置文件:           

 

StudentCard.hbm.xml

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.StudentCard" table="t_studentCard">  
  3.         <id name="id">  
  4.             <generator class="native"/>  
  5.         </id>  
  6.         <property name="cardNo"/>  
  7.         <one-to-one name="student" fetch="join">  
  8. <!--fetch值爲select時,能夠實現懶加載,並且這裏constrained不能爲true,不然會兩張表主鍵相互依賴,致使死循環-->  
  9.     </class>  
  10. </hibernate-mapping>  

 

Student.hbm.xml

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.Person" table="t_student">  
  3.         <id name="id" type="int">  
  4.             <generator class="foreign">  
  5.                 <param name="property">studentCard</param>  
  6.             </generator>  
  7.         </id>  
  8.         <one-to-one name="studentCard" constrained="true"/>  
  9.         <property name="name"/>  
  10.     </class>  
  11. </hibernate-mapping>  

 

測試如上,咱們查出Student時,Student.studentCard能夠獲取學生證信息。當咱們查出StudentCard時,StudentCard.student能夠獲取學生信息。可是也正是由於他們之間是這種關係,沒有相互的約束,因此當咱們執行:

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. session.beginTransaction();  
  2. Student student=new Student();  
  3. student.setName("Davie");  
  4. StudentCard studentCard=new StudentCard();  
  5. studentCard.setCardNo("12050242013");            
  6. studentCard.setPerson(person);  
  7. session.save(studentCard);  
  8. session.getTransaction().commit();  

 

session只會save(studentCard),而不會save(student);

 

 

4.2.2一對一雙向關聯映射——惟一外鍵關聯

直接上配置了:

Po對象設計:

StudentCard.java

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class StudentCard{  
  2.    private int id;  
  3.    private String cardNo;  
  4.    private Student student;  
  5.    //getter\setter方法  
  6. }  

 

Student.java

 

[java]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. public class Student{  
  2.     private int id;  
  3.     private String name;  
  4.     private StudentCard studentCard;  
  5.      //getter\setter  
  6. }  

 

配置文件:

StudentCard.hbm.xml

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.StudentCard" table="t_studentCard">  
  3.         <id name="id">  
  4.             <generator class="native"/>  
  5.         </id>  
  6.         <property name="cardNo"/>  
  7.         <one-to-one name="student" property-ref="studentCard">  
  8.     </class>  
  9. </hibernate-mapping>  
Student.hbm.xml

 

 

[html]  view plain copy
 print?在CODE上查看代碼片派生到個人代碼片
  1. <hibernate-mapping package="org.hibernate.test" >  
  2.     <class name="com.ssh.hibernate.Person" table="t_student">  
  3.         <id name="id" type="int">  
  4.             <generator class="foreign">  
  5.                 <param name="property">studentCard</param>  
  6.             </generator>  
  7.         </id>  
  8.         <one-to-one name="studentCard" constrained="true"/>  
  9.         <property name="name"/>  
  10.     </class>  
  11. </hibernate-mapping>  

 

一張身份證只對應一位公民,因此用<one-to-one>標籤,property-ref="studentCard"指t_studentCard的主鍵與t_student中的studentCard字段對應。

 

       到此,關於一對一映射的相關知識告一段落,可是你們要知道,惟一外鍵關聯其實就是多對一關聯的一種特殊狀況,因此當咱們需求變了,要求有一對一變成多對一的時候,咱們該怎麼辦呢?其實很簡單,直接把外鍵惟一的約束幹掉就能夠了,是否是方便不少呢?

相關文章
相關標籤/搜索