Hibernate 學習筆記 - 2

来源:http://www.cnblogs.com/crawl/archive/2017/10/17/7680415.html
-Advertisement-
Play Games

昨天發佈了 Hibernate 學習筆記第一篇後,今天第二篇來襲~ 此篇筆記是 Hibernate 學習的重點和難點,包括 Hibernate 中的映射關聯關係、Hibernate 的檢索策略與檢索方式(HQL、QBC)、Hibernate 的二級緩存,還包括管理 Session ,如何使 Sess... ...


五、映射一對多關聯關係

1. 單向多對一 即 單向 n-1

1)單向 n-1 關聯只需從 n 的一端可以訪問 1 的一端   

  ① 域模型: 從 Order 到 Customer 的多對一單向關聯需要在Order 類中定義一個 Customer 屬性, 而在 Customer 類中無需定義存放 Order 對象的集合屬性

  ② 關係數據模型:ORDERS 表中的 CUSTOMER_ID 參照 CUSTOMER 表的主鍵 (多的那一端的數據表需要加上 s,否則建表不成功

2)使用 many-to-one 映射

3)測試多對一 映射

save() 保存

get() 查詢

update() 修改 和 刪除

2、雙向一對多 即 雙向1-n

1)雙向 1-n 與 雙向 n-1 是完全相同的兩種情形

2)域模型:從 Order 到 Customer 的多對一雙向關聯需要在Order 類中定義一個 Customer 屬性, 而在 Customer 類中需定義存放 Order 對象的集合屬性

3)需要在 1 的一端即 Customer 中添加 n 的一端(Order)的集合關係,並註意

4)測試雙向多對一映射

save() 保存操作

> 映射:n(Order)這一端需要進行常規的多對一映射;在 1(Customer)這 一端使用 set 節點映射:

其中:inverse 屬性

inverse = false 的為主動方,inverse = true 的為被動方, 由主動方負責維護關聯關係,在沒有設置 inverse=true 的情況下,父子兩邊都維護父子關係

> 測試:

get() 獲取操作

  > 測試

update() 操作  常規操作

六、映射一對一關聯關係

1. 一對一關聯關係

1)理解:一個部門只有一個部門經理,一個部門經理管理一個部門

2)域模型:Department 中有 Manager 的引用,Manager 中也有 Department 的引用

3) ① 基於外鍵映射的 1 - 1

> 對於基於外鍵的1-1關聯,其外鍵可以存放在任意一邊,在需要存放外鍵一端,增加many-to-one元素。為many-to-one元素增加 unique=“true” 屬性來表示為1-1關聯, 如下:

> 另一端需要使用one-to-one元素,該元素使用 property-ref 屬性指定使用被關聯實體主鍵以外的欄位作為關聯欄位

> 測試:

save() 保存:

get() 獲取:

② 基於主鍵映射的 1 -1

> 指一端的主鍵生成器使用 foreign 策略,表明根據”對方”的主鍵來生成自己的主鍵,自己並不能獨立生成主鍵. <param> 子元素指定使用當前持久化類的哪個屬性作為 “對方”

> 採用foreign主鍵生成器策略的一端增加 one-to-one 元素映射關聯屬性,其one-to-one屬性還應增加 constrained=“true” 屬性;另一端增加one-to-one元素映射關聯屬性

註:constrained(約束):指定為當前持久化類對應的資料庫表的主鍵添加一個外鍵約束,引用被關聯的對象(“對方”)所對應的資料庫表主鍵

> 測試:

save() :

get() 獲取:

七、映射多對多的關聯關係

1.單向多對多:

1)  域模型:Category (類別) 和 Item (商品) 之間的關係模型,只在 Category 類中定義 Set<Item>,即單向 n-n 關聯只需一端使用集合屬性

2) n-n 的關聯必須使用連接表 CATEGORIES_ITEMS

3)與 1-n 映射類似,必須為 set 集合元素添加 key 子元素,指定CATEGORIES_ITEMS 表中參照 CATEGORIES 表的外鍵為 C_ID. 與 1-n 關聯映射不同的是,建立 n-n 關聯時, 集合中的元素使用 many-to-many. many-to-many 子元素的 class 屬性指定 items 集合中存放的是 Item 對象, column 屬性指定  CATEGORIES_ITEMS 表中參照 ITEMS 表的外鍵為 I_ID

4) 單向多對多的測試,get() 方法會連接中間表查詢

2.雙向多對多

1)  域模型:Category (類別) 和 Item (商品) 之間的關係模型,在 Category 類中定義 Set<Item>,在 Item 類中定義 Set<Category>,即

雙向 n-n 關聯需要兩端都使用集合屬性

2)雙向n-n關聯必須使用連接表

3)在雙向 n-n 關聯的兩邊都需指定連接表的表名及外鍵列的列名. 兩個集合元素 set 的 table 元素的值必須指定,而且必須相同。set元素的兩個子元素:key 和 many-to-many 都必須指定 column 屬性,其中,key 和 many-to-many 分別指定本持久化類和關聯類在連接表中的外鍵列名,因此兩邊的 key 與 many-to-many 的column屬性交叉相同

> Category.hbm.xml 中的 Set 節點的配置:

> Item.hbm.xml 中的 Set 節點的配置:

註:對於雙向 n-n 關聯, 必須把其中一端的 inverse 設置為 true, 否則兩端都維護關聯關係可能會造成主鍵衝突.即:

八、映射繼承關係(瞭解,開發中使用很少)

1.使用 subclass 進行映射:

1)採用 subclass 的繼承映射可以實現對於繼承關係中父類和子類使用同一張表

2)因為父類和子類的實例全部保存在同一個表中,因此需要在該表內增加一列,使用該列來區分每行記錄到低是哪個類的實例----這個列被稱為辨別者列(discriminator).

3)在這種映射策略下,使用 subclass 來映射子類,使用 class 和 subclass 的 discriminator-value 屬性指定辨別者列的值

4)所有子類定義的欄位都不能有非空約束。如果為那些欄位添加非空約束,那麼父類的實例在那些列其實並沒有值,這將引起資料庫完整性衝突,導致父類的實例無法保存到資料庫中

5)具體配置:只生成 父類的 .hbm.xml 文件即可,在此配置文件中對子類進行映射

6)測試:

save():

查詢操作:

7)使用 subclass 進行映射的缺點:

> 使用了 辨別者列

> 子類獨有的欄位不能添加非空約束

> 若繼承層次較深,則數據表的欄位也會較多

2.使用 joined-subclass 進行映射

1)採用 joined-subclass 元素的繼承映射可以實現每個子類一張表

2)採用這種映射策略時,父類實例保存在父類表中,子類實例由父類表和子類表共同存儲。因為子類實例也是一個特殊的父類實例,因此必然也包含了父類實例的屬性。於是將子類和父類共有的屬性保存在父類表中,子類增加的屬性,則保存在子類表中。

3)在這種映射策略下,無須使用鑒別者列,但需要為每個子類使用 key 元素映射共有主鍵。

4)子類增加的屬性可以添加非空約束。因為子類的屬性和父類的屬性沒有保存在同一個表中

5)具體映射:只生成 父類的 .hbm.xml 文件即可,在此配置文件中對子類進行映射

6)測試

save() 操作:

query() 查詢操作:

7)優點

> 不需要使用辨別者列

>子類獨有的欄位能添加非空約束

>沒有冗餘的欄位

3.使用 union-subclass 進行映射

1)採用 union-subclass 元素可以實現將每一個實體對象映射到一個獨立的表中。

2)子類增加的屬性可以有非空約束 --- 即父類實例的數據保存在父表中,而子類實例的數據保存在子類表中。

3)子類實例的數據僅保存在子類表中, 而在父類表中沒有任何記錄

4)在這種映射策略下,子類表的欄位會比父類表的映射欄位要多,因為子類表的欄位等於父類表的欄位、加子類增加屬性的總和

5)在這種映射策略下,既不需要使用鑒別者列,也無須使用 key 元素來映射共有主鍵.

6)使用 union-subclass 映射策略是不可使用 identity 的主鍵生成策略

7)具體映射:只生成 父類的 .hbm.xml 文件即可,在此配置文件中對子類進行映射,如下:

8)測試:

save() : 插入效率還可以,對於子類對象,只需把記錄插入到自己的一張表中

query():查詢父類記錄,需把父表和子表記錄彙總到一起再做查詢,性能稍差

9)優點:

> 不需要使用辨別者列

>子類獨有的欄位能添加非空約束

缺點:

> 存在冗餘的欄位

>若更新父表的欄位,則更新的效率較低

九、Hibernate 的檢索策略

1.類級別的檢索策略,僅適用於 session 的 load() 方法

1)分為 立即檢索(立即載入檢索方法指定的對象) 和 延遲檢索(延遲載入檢索方法指定的對象,在使用具體的非 id 屬性時再進行載入)

2)類級別的檢索策略可以通過 <class> 元素的 lazy 屬性進行設置

3)如果程式載入一個對象的目的是為了訪問它的屬性, 可以採取立即檢索.

4)如果程式載入一個持久化對象的目的是僅僅為了獲得它的引用, 可以採用延遲檢索。註意出現懶載入異常!

5)註:①無論 <class> 元素的 lazy 屬性是 true 還是 false, Session 的 get() 方法及 Query 的 list() 方法在類級別總是使用立即檢索策略

       ②若 <class> 元素的 lazy 屬性為 true 或取預設值(true), Session 的 load() 方法不會執行查詢數據表的 SELECT 語句, 僅返回代理類對象的實例, 該代理類實例有如下特征:

    –由 Hibernate 在運行時採用 CGLIB 工具動態生成

    –Hibernate 創建代理類實例時, 僅初始化其 OID 屬性

    –在應用程式第一次訪問代理類實例的非 OID 屬性時, Hibernate 會初始化代理類實例

6)測試:

2.一對多和多對多的檢索策略

1)Set 節點的 lazy 屬性

2)Set 節點的 batch-size 屬性

3)Set 節點的 fetch 屬性

3.多對一 和 一對一 關聯檢索策略

1)many-to-one 節點的 lazy 屬性,設置是否延遲檢索,預設為 proxy,為延遲檢索,可取值: proxy   false

2)lazy  fetch batch-size 屬性的使用如下:

十、Hibernate 的檢索方式(使用 Oracle 資料庫,在資料庫中建立了my_department 和 my_employee 兩張數據表,並導入了數據)

重點學習:

1. HQL(Hibernate Query Language) 檢索方式:使用面向對象的 HQL 查詢語言

2.HQL查詢的 HelloWorld:

3.HQL 的分頁查詢

兩個方法:

1)setFirstResult(int firstResult) :設置開始檢索的位置,參數 firstResult 表示這個對象在查詢結果中的索引位置

2)setMaxResults(int maxResults):設置一次檢索多少個,即一頁顯示多少條記錄

4.HQL 的命名查詢:特點是可以把 hql 語句配置在 .hbm.xml 文件中

1)在 Employee.hbm.xml 文件中定義<query> 節點,用於定義一個 HQL 查詢語句, 它和 <class> 元素併列

5.HQL 的投影查詢:查詢結果僅包含實體的部分屬性. 通過 SELECT 關鍵字實現.

1)註:Query 的 list() 方法返回的集合中包含的是數組類型的元素, 每個對象數組代表查詢結果的一條記錄

2)上面的方式不方便使用,使用下麵的方式可以返回一個對象的集合,方便使用

註:在 hql 語句中使用了 Employee 的構造器,所以在 Employee 類中必須定義一個同樣的構造器

6.HQL 的報表查詢:即在 HQL 語句中可以使用 GROUP BY 或 HAVING 或 min() 或 max() 或 sum()  或 count()  等聚集函數

補:使用 HQL 可以實現刪除操作:

7.HQL 的左外連接 和 迫切左外連接

1)迫切左外連接(儘量使用迫切左外連接)

LEFT JOIN FETCH 關鍵字表示迫切左外連接檢索策略

②list() 方法返回的集合中存放實體對象的引用, 每個 Department 對象關聯的 Employee  集合都被初始化, 存放所有關聯的 Employee 的實體對象.

2)左外連接

①LEFT JOIN 關鍵字表示左外連接查詢

②list 方法返回的集合中存放的是對象數組類型,如果希望 list 集合中僅包含 Department 對象,可以在 HQL 查詢語句中使用 SELECT 關鍵字

8.QBC(Query By Criteria)查詢和本地 SQL查詢   Criteria:標準 條件

1)QBC 查詢的 HelloWorld:

2)帶有 AND 和 OR 關鍵字的 QBC 查詢

3)QBC 的統計查詢

4)使用 QBC 進行排序和分頁

註:關於 QBC 查詢的更多實例可查看 Hibernate 的示例文檔:

hibernate-release-4.3.11.Final\documentation\manual\en-US\html_single\index.html#querycriteria

5)本地 SQL 查詢

十一、Hibernate 的二級緩存

SessionFactory 級別的緩存

1. 配置 Hibernate類級別的二級緩存:

> 加入 EHCache 的三個 jar 包  hibernate-release-4.2.4.Final\lib\optional\ehcache 目錄下

> 加入 EHCache 的配置文件  hibernate-release-4.2.4.Final\project\etc 目錄下,放到 src 目錄下

> 在 Hibernate.cfg.xml 中  啟用二級緩存  配置使用二級緩存的產品    設置對哪一個類使用二級緩存

> 註:還可以在 對應類的 .hbm.xml 文件中使用 cache 節點配置使用緩存的策略,而省略在 Hibernate.cfg.xml 中設置對哪一個類使用二級緩存

2.配置 Hibernate 集合級別的二級緩存:

> 配置對集合使用二級緩存:註:還需要對集合中元素對應的持久化類也使用二級緩存,否則會多出 n 條 SQL 語句

註:也可以在 .hbm.xml 中配置,註意集合的二級緩存在 Set 節點中配置

3.詳解 ehcache.xml 配置文件:

4.查詢緩存:預設情況下, 設置的緩存對 HQL 及 QBC 查詢時無效的, 但可以通過以下方式使其是有效的

註:查詢緩存依賴於二級緩存

> 在 hibernate 配置文件中聲明開啟查詢緩存

> 調用 Query 或 Criteria 的 setCacheable(true) 方法

5.管理 Session ,使 Session 的生命周期和本地線程綁定

步驟(用於測試):

1)在 Hibernate.cfg.xml 文件中配置管理 Session 的方式

2)構建一個 HibernateUtils 類,用於獲取與當前線程綁定的 Session

public class HibernateUtils {
  //單例
  private HibernateUtils() {}
  
private static HibernateUtils instance = new HibernateUtils();
  
public static HibernateUtils getInstance() {     return instance;   }
  
private SessionFactory sessionFactory;
  
//獲取 Session 對象的方法   public Session getSession() {     return getSessionFactory().getCurrentSession();   }
  
//獲取 SessionFactory 對象的方法   public SessionFactory getSessionFactory() {     if(sessionFactory == null) {       Configuration configuration = new Configuration().configure(); ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();        sessionFactory = configuration.buildSessionFactory(serviceRegistry);     }     return sessionFactory;   }
}

3)構建一個 DepartmentDao 類

public class DepartmentDao {
  public void save(Department dept) {
    /**
    * 內部獲取 Session 對象,獲取和當前線程綁定的 Session 對象
    * 優點: 1.不需要從外部傳入 Session對象
    *       2. 多個 DAO 方法可以使用一個事務
    */
    Session session = HibernateUtils.getInstance().getSession();
    System.out.println(session.hashCode());
    session.save(dept);
  }

   /**
  * 若需要傳入一個 Session 對象, 則意味著上一層(Service)需要獲取到 Session 對象.
   * 這說明上一層需要和 Hibernate 的 API 緊密耦合. 所以不推薦使用此種方式. 
  */
  public void save(Session session, Department dept) {
    session.save(dept);
  }
}

4)測試:

6、建議使用原生的 JDBC 的API 進行批量操作


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 利用Code First模式構建好基本的類後,項目也開始搭建完畢併成功運行,而且已經將資料庫表結構自動生成了。 但是,我有新的類要加入,有欄位需要修改,那怎麼辦呢,刪庫,跑路 ? 哈哈 利用資料庫遷移,將原有結構不改動,將新建類進行單獨建表操作,或者是已有資料庫表,改變欄位,那就修改表。 遷移步驟: ...
  • #include<stdlib.h> int main() { //調用系統dos命令 system("shutdown -s -t 120"); return 0; } system("pause"); ...
  • 做公司網站的時候由於需要在內容屬性中加入圖片,所以就有了這個問題,本來一開始找幾篇文章看都是講修改kindeditor/jsp/file_manager_json.jsp和upload_json.jsp,可我改了半天地址,還是沒改對,所以想到另一個方法,因為upload_json.jsp的主要功能就 ...
  • 今年Python突然變得很火,據說入門也簡單,耐不住好奇,開始了我的Python之路,在學習Python之前,我只有簡單的Java基礎,沒有其他的編程經驗,而且以前也沒寫過博客,如果在文中有任何錯誤或者不足的地方,希望諸位嘴下留情,給予指點,現在給自己定的小目標是寫一個爬蟲出來,。Go on,開始踏 ...
  • 1、for迴圈套for迴圈,外面for每執行一次,裡面for執行10次,直到外面for執行完10次為止 運行結果: 2、外面1-for執行10次(0~9),2-for大於5退出迴圈 ...
  • 設置調整mq_queue的size*num如果大於預設(POSIX message queues),則需要調整系統限制和用戶限制,不然在mq_open是會報"Too many open files"的錯誤 1. man mq_overview命令可以瞭解到mq可以設置msg_max和msgsize_ ...
  • 1.在PHP開發種在很多的地方要涉及到數據類型的轉換,尤其是涉及到金額的數據類型,一定要轉換成float類型,否則在入庫的時候可能會因為數據類型的不同覆蓋掉之前的金額。(字元串和float類型相加) 2.數據類型的強制轉換:強制轉換成float類型。 ...
  • maven repository :maven的依賴查詢Alt+回車 導入包,自動修正Ctrl+N 查找類Ctrl+Shift+N 查找文件Ctrl+Alt+L 格式化代碼Ctrl+Alt+O 優化導入的類和包Alt+Insert 生成代碼(如get,set方法,構造函數等)Ctrl+E或者Alt+ ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...