持久層框架--hibernate(3)

一:關聯關係java

1.關聯關係的方向可分爲單向關聯和雙向關聯sql

單向關聯:假設存在兩張表province表和City表,若是在應用的業務邏輯中,僅須要每一個province實例可以查詢獲得其對應的City實例,而City實例並不須要查詢獲得其對應的province實例;或者反之。數據庫

雙向關聯:既須要每一個province實例可以查詢獲得其對應的City實例,City實例也須要查詢獲得其對應的province實例。session

2.關聯的數量,根據擁有被關聯對象的個數肯定oracle

多對一(many to one):如用戶和組 學生和班級app

一對多(one to many):如用戶和電子郵件工具

多對多(many to many):如學生選課單元測試

一對一(one to one):如用戶和身份證測試

二.單向多對一ui

     單向多對一關聯是最多見的單向關聯關係,如:多個城市屬於同一個省份。之因此叫他多對一而不是一對多,是由於他們之間的關係是多的一方來維護的

多個城市屬於一個省份,咱們用多的一方來維護,因此咱們能夠根據城市能夠知道他在哪一個省份,而不須要知道一個省份裏有哪些城市,這就是所謂的單向的。

多對一映射原理:

在多的一端加入一個外鍵(FK)指向一的一端,它維護的關係是多指向一

一對多映射原理:

在多的一端加入一個外鍵(FK)指向一的一端,它維護的關係是一指向多

2.重要屬性 - cascade(級聯)

級聯的意思是指定兩個對象之間的操做聯動關係,對一個對象執行了操做以後,對其指定的級聯對象也須要執行相同的操做

總共能夠取值爲:all、none、save-update、delete

all-表明在全部的狀況下都執行級聯操做

none-在全部狀況下都不執行級聯操做

save-update-在保存和更新的時候執行級聯操做

delete-在刪除的時候執行級聯操做

三.單向一對多

      所謂單向一對多,就是實體之間的關係由「一」 的一端加載「多」 的一端,關係由「一」的一端來維護,在JavaBean中是在「一」的一端中持有「多」的一端的集合,Hibernate把這種關係反映到數據庫的策略是在「多」的一端的表上加一個外鍵指向「一」 的一端的表的主鍵(PK)。好比Province(省份)和City(城市)之間是一對多的關係。一個省份裏面有不少的城市,站在省份的角度上來看就是一個省份對應多個城市。在一的一端含有一個多的引用的集合(set),咱們能夠根據省份找到它有哪些城市,而不能根據城市找到他對應的省份

四:雙向一對多關聯

      所謂雙向一對多關聯,同時配置單向一對多和單向多對一就成了雙向一對多關聯,上面兩種都是單向的,可是在實際開發過程當中,不少時候都是須要雙向關聯的,它在解決單向一對多維護關係的過程當中存在的缺陷起了必定的修補做用

五.注意事項

1.一對多雙向關聯映:
  在一的一端的集合上使用<key>,在對方表中加入一個外鍵指向一的一端
  在多一端採用<many-to-one>
2.key標籤指定的外鍵字段必須和<many-to-one>指定的外鍵字段一致,不然引用字段錯誤

3.若是在一的一端維護一對多關聯關係,hibernate會發出多餘的Update語句,多以咱們通常在多的一端維護關聯關係
4.關於inverse屬性;
 inverse主要用在一對多,多對對雙向關聯上,inverse能夠設置到<set>集合上,
 默認inverse爲false,因此咱們能夠從一的一端和多的一端來維護關聯關係,若是inverse爲true,咱們只能從多的一端來維護關聯關係,注意:inverse屬性,隻影響存儲(使存儲方向轉變),即持久

5.區分inverse和cascade

Inverse:負責控制關係,默認爲false,也就是關係的兩端都能控制,但這樣會形成一些問題,更新的時候會由於兩端都控制關係,因而重複更新。通常來講有一端要設爲true。
Cascade:負責控制關聯對象的級聯操做,包括更新、刪除等,也就是說對一個對象進行更新、刪除時,其它對象也受影響,好比我刪除一個對象,那麼跟它是多對一關係的對象也所有被刪除。
舉例說明區別:刪除「一」那一端一個對象O的時候,若是「多」的那一端的Inverse設爲true,則把「多」的那一端全部與O相關聯的對象外鍵清空;若是「多」的那一端的Cascade設爲Delete,則把「多」的那一端全部與O相關聯的對象所有刪除。

 

持久化類多的一端City.java
 1 持久化類多的一端City.java
 2 
 3 package com.edu.many2one;
 4 /**
 5  *  持久化類
 6  * @author Administrator
 7  *   多的一端
 8  */
 9 public class City {
10 
11     private Integer id;
12     private String name;
13     
14     //關聯屬性
15     private Province pro;  //必須有
16 
17     public Integer getId() {
18         return id;
19     }
20 
21     public void setId(Integer id) {
22         this.id = id;
23     }
24 
25     public String getName() {
26         return name;
27     }
28 
29     public void setName(String name) {
30         this.name = name;
31     }
32 
33     public Province getPro() {
34         return pro;
35     }
36 
37     public void setPro(Province pro) {
38         this.pro = pro;
39     }
40     
41     
42 }

持久化類一的一端Province.java

 1 持久化類一的一端Province.java
 2 
 3 package com.edu.many2one;
 4 
 5 import java.util.HashSet;
 6 import java.util.Set;
 7 
 8 /**
 9  * 持久化類
10  * @author Administrator
11  *   一的一端
12  */
13 public class Province {
14 
15     private Integer id;
16     private String name;
17     
18     //關聯屬性
19     private Set<City> cities = new HashSet<City>();  //多的一方放在集合中
20 
21     public Integer getId() {
22         return id;
23     }
24 
25     public void setId(Integer id) {
26         this.id = id;
27     }
28 
29     public String getName() {
30         return name;
31     }
32 
33     public void setName(String name) {
34         this.name = name;
35     }
36 
37     public Set<City> getCities() {
38         return cities;
39     }
40 
41     public void setCities(Set<City> cities) {
42         this.cities = cities;
43     }
44     
45     
46 }

各個實體類配置文件

City.hbm.xml

 1 City配置文件
 2 
 3 <?xml version="1.0" encoding="UTF-8"?>
 4 <!DOCTYPE hibernate-mapping PUBLIC 
 5     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 6     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 7 <hibernate-mapping package="com.edu.many2one">
 8     <class name="City">
 9         <id name="id">
10             <generator class="increment"/>
11         </id>
12         
13         <property name="name"/>
14     
15         <!-- 映射關聯屬性 -->
16         <!-- pro  和 Province類 多對一 
17             name:  關聯屬性的名字
18             class: 關聯類的類名
19             column: 數據庫外鍵字段的名字
20         
21         -->
22         <many-to-one name="pro" class="Province" column="pid"
23             cascade="save-update"/>
24     </class>
25 
26 </hibernate-mapping>

Province.hbm.xml

 1 Province配置文件
 2 
 3 <?xml version="1.0" encoding="UTF-8"?>
 4 <!DOCTYPE hibernate-mapping PUBLIC 
 5     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 6     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 7 <hibernate-mapping package="com.edu.many2one">
 8     <class name="Province">
 9         <id name="id">
10             <generator class="increment"/>
11         </id>
12         
13         <property name="name"/>
14         
15         <!-- 關聯屬性 
16             cascade屬性:級聯操做默認值爲none
17                   save-update:級聯保存或更新
18                   delete:級聯刪除
19                   all
20             inverse="true":默認值爲false。主控方
21                            true 反轉控制權,變爲被控方,沒有維護關聯關係的權利。
22         -->
23         <!-- cities  和City類    一對多 -->
24         <set name="cities" cascade="delete" inverse="true">
25             <key column="pid"/>  <!-- 肯定關聯的外鍵列 -->
26             <one-to-many class="City"/>
27         </set>
28     </class>
29     
30 
31 </hibernate-mapping>

 

hibernate.cfg.xml

 1 hibernate配置文件
 2 
 3 <?xml version="1.0" encoding="UTF-8"?>
 4 <!DOCTYPE hibernate-configuration PUBLIC
 5     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 6     "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 7 <hibernate-configuration>
 8 <session-factory>
 9     <!-- 配置數據庫鏈接的基本信息 -->
10     <property name="hibernate.connection.driver_class">
11         oracle.jdbc.driver.OracleDriver
12     </property>
13     <property name="hibernate.connection.url">
14         jdbc:oracle:thin:@localhost:1521:XE
15     </property>
16     <property name="hibernate.connection.username">lihengyu</property>
17     <property name="hibernate.connection.password">lihengyu</property>
18 
19     <!-- 數據庫的方言 使用的是哪一種數據庫 -->
20     <property name="hibernate.dialect">
21         org.hibernate.dialect.Oracle10gDialect
22     </property>
23     <!-- 顯示sql語句 -->
24     <property name="hibernate.show_sql">true</property>
25     <!-- 自動建立數據庫表 
26         none:默認值  有表就使用,沒表不建立
27         create:每次都建立新表
28         update: 有表就使用,沒表建立。若是持久化類及映射文件發生改變,則發生alter語句修改表結構。
29     -->
30     <property name="hibernate.hbm2ddl.auto">update</property>
31 
32     <!-- 添加映射文件 -->
33     <mapping resource="com/edu/many2one/City.hbm.xml" />
34     <mapping resource="com/edu/many2one/Province.hbm.xml" />
35 
36 </session-factory>
37 
38 
39 </hibernate-configuration>

代碼測試

  1 TestHibernate 測試
  2 
  3 package com.edu.many2one;
  4 
  5 import org.hibernate.SessionFactory;
  6 import org.hibernate.Transaction;
  7 import org.hibernate.cfg.Configuration;
  8 import org.hibernate.classic.Session;
  9 import org.junit.Test;
 10 
 11 /**
 12  * 使用單元測試工具,測試hibernate 的增刪改查(CRUD)操做
 13  * 
 14  * @author Administrator
 15  * 
 16  */
 17 public class TestHibernate {
 18 
 19     private static SessionFactory sf;
 20     static {
 21         // 1. 加載配置文件
 22         Configuration cfg = new Configuration();
 23         cfg.configure("com/edu/many2one/hibernate.cfg.xml");
 24 
 25         // 2. 得到SessionFactory
 26         sf = cfg.buildSessionFactory();
 27     }
 28     
 29 
 30     /**
 31      *  保存用戶
 32      *  1.  保存Province 不保存City
 33      *  2.  保存City  不保存Province
 34      *  3.  先保存Province,再保存City
 35      *  4.  先保存City,再保存Province
 36      */
 37     @Test
 38     public void save() {
 39         
 40         
 41         Session session = sf.openSession();
 42         Transaction tran = session.beginTransaction();
 43         
 44         Province p = new Province();
 45         p.setName("吉林省");
 46         
 47         City c = new City();
 48         c.setName("長春市");
 49         
 50         //維護關聯關係
 51         c.setPro(p);
 52         p.getCities().add(c);
 53         
 54         //保存對象
 55         /*
 56          * 1.保存Province 不保存City  city對象是臨時狀態,不能操做數據庫
 57          * TransientObjectException:      臨時對象異常
 58         session.save(p);
 59          */
 60         
 61         /*
 62          * 2.  保存City  不保存Province
 63          * TransientObjectException:      臨時對象異常
 64          */
 65         session.save(c);
 66         
 67         /*
 68          * 3.  先保存Province,再保存City
 69          * 
 70          *  發送幾條sql語句
 71          *  insert into Province (name, id) values (?, ?)
 72             insert into City (name, pid, id) values (?, ?, ?)
 73             update City set pid=? where id=?
 74         session.save(p);
 75         session.save(c);
 76          */
 77         /*
 78          * 4.  先保存City,再保存Province
 79          * 
 80          *  發送4條sql語句
 81          *  insert into City (name, pid, id) values (?, ?, ?)
 82             insert into Province (name, id) values (?, ?)
 83             update City set name=?, pid=? where id=?
 84             update City set pid=? where id=?
 85         session.save(c);
 86         session.save(p);
 87          */
 88         
 89         tran.commit();
 90         session.close();
 91     }
 92     /**
 93      * 查詢
 94      * 1.  1號城市屬於哪一個省份
 95      * 2.  1號省份關聯的全部城市
 96      */
 97     @Test
 98     public void find() {
 99         
100         
101         Session session = sf.openSession();
102         Transaction tran = session.beginTransaction();
103         
104         //1
105         //City c = (City) session.get(City.class, 1);
106         //System.out.println(c.getPro().getName());
107         
108         //2
109         Province p = (Province) session.get(Province.class, 1);
110         
111         for(City city:p.getCities()) {
112             System.out.println(city.getName());
113         }
114         tran.commit();
115         session.close();
116     }
117     
118     /**
119      * 刪除
120      * 1.  刪除5號城市信息
121      * 2.  刪除4號省份信息
122      */
123     @Test
124     public void delete() {
125         
126         
127         Session session = sf.openSession();
128         Transaction tran = session.beginTransaction();
129         
130 //        City c = (City) session.get(City.class, 5);
131 //        session.delete(c);
132         
133         Province p = (Province) session.get(Province.class, 4);
134         session.delete(p);
135         
136         tran.commit();
137         session.close();
138     }
139     
140     /*
141      *   City變動
142      *   
143      *   把4號城市變動爲2號省份
144      *   
145      */
146     @Test
147     public void update() {
148         
149         
150         Session session = sf.openSession();
151         Transaction tran = session.beginTransaction();
152         
153         //查詢信息
154         City c4 = (City) session.get(City.class, 4);
155         Province p2 = (Province) session.get(Province.class, 2);
156         
157         /*
158          * 變動關聯關係
159          * 
160          * 此時發送2條update語句。重複操做。 
161          * 關聯兩端同時維護關係,對象的狀態都發生了改變,全部會生成2條update語句
162          * update City set name=?, pid=? where id=?
163            update City set pid=? where id=?
164            
165          *  只要執行一條update就能夠更新數據庫中的記錄
166          *  只須要一端維護關係。
167          *  哪一端維護關聯關係?
168          *  領導1  
169          *  全國人民N   主控方
170          *  
171          *  在一對多關聯中,須要多的一端做爲主控方,來維護關聯關係
172          *  那麼一的一端就應該交出控制權,做爲被控方。
173          */
174         c4.setPro(p2);
175         /*
176          * 雖然,此條刪除語句不會影響到數據庫中的記錄。
177          * 但爲了維護程序的健壯性,建議添加此條語句。
178          */
179         p2.getCities().add(c4);
180         
181         //更新  不須要調用update方法
182 //        session.update(c4);
183 //        session.update(p2);
184         
185         
186         tran.commit();
187         session.close();
188     }
189 }
相關文章
相關標籤/搜索