使用 Hibernate 和 MySQL 需要知道的五件事

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

使用 JPA 和 Hibernate 的好處之一是它提供了資料庫特定方言和功能抽象。 因此,理論上,您可以實現一個應用程式,將其連接到一個受支持的資料庫,並且它可以在不用更改任何代碼的情況下運行。Hibernate 真的很好。 但老實說,您沒有想過您的應用程式能與每個支持的資料庫完美運行,是嗎? ...


https://www.thoughts-on-java.org/5-things-you-need-to-know-when-using-hibernate-with-mysql/
作者:Thorben Janssen
譯者:oopsguy.com

使用 JPA 和 Hibernate 的好處之一是它提供了資料庫特定方言和功能抽象。 因此,理論上,您可以實現一個應用程式,將其連接到一個受支持的資料庫,並且它可以在不用更改任何代碼的情況下運行。

Hibernate 真的很好。 但老實說,您沒有想過您的應用程式能與每個支持的資料庫完美運行,是嗎?

Hibernate 處理最重要的事情。 但是,如果您希望應用能夠運行良好,您仍然需要知道要使用哪種資料庫,並相應地調整配置和代碼。

在之前的一篇文章中,我討論了“如果你想使用 Hibernate 和 PostgreSQL 資料庫你需要知道的 6 件事情”。今天我想仔細看看 MySQL 資料庫。

1、映射:主鍵

處理和創建主鍵很基礎,但也是應用程式最重要的一部分。

JPA 規範的 **@GeneratedValue** 註解允許您定義用於創建唯一主鍵值的策略。您可以選擇 SEQUENCE、IDENTITY、TABLE 和 AUTO

一般來說,我建議使用 SEQUENCE 策略,因為它允許 Hibernate 使用 JDBC 批處理和其他需要延遲執行 SQL INSERT 語句的優化策略。

然而,您不能將此策略與 MySQL 資料庫一起使用。因為它需要一個資料庫序列,恰好 MySQL 不支持此功能。

因此,您需要在 IDENTITYTABLE 之間進行選擇。考慮到 TABLE 策略的性能和可擴展性問題,這很容易作出決定。

如果您正在使用 MySQL 資料庫,則應始終使用 GenerationType.IDENTITY。它使用自動增量(autoincremented )的資料庫列,這是最有效的可用方法。您可以通過使用 **@GeneratedValue(strategy = GenerationType.IDENTITY)** 註解主鍵屬性來執行此操作。

@Entity
public class Author {
 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;
 
    ...
}

2、映射:Hibernate 5 中 GenerationType.AUTO 問題

當您使用 GenerationType.AUTO 時,Hibernate 會根據 Hibernate 方言選擇生成策略。如果您需要支持多資料庫,以下一種常見的方法。

@Entity
public class Author {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;
 
    ...
}

在舊版本中,Hibernate 為 MySQL 資料庫選擇 GenerationType.IDENTITY。 這是一個不錯的選擇。如之前所述,這是最有效的方法。

不幸的是此行為在 Hibernate 5 中發生了改變。現在是選擇 GenerationType.TABLE,它使用資料庫表來生成主鍵。 這種方法需要大量資料庫查詢和悲觀鎖來生成唯一值。

14:35:50,959 DEBUG [org.hibernate.SQL] - select next_val as id_val from hibernate_sequence for update
14:35:50,976 DEBUG [org.hibernate.SQL] - update hibernate_sequence set next_val= ? where next_val=?
14:35:51,097 DEBUG [org.hibernate.SQL] - insert into Author (firstName, lastName, version, id) values (?, ?, ?, ?)

您可以通過定義一個 **@GenericGenerator** 來避免這一點,以下代碼告訴 Hibernate 使用本地策略生成主鍵值。

@Entity
public class Author {
 
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "native")
    @GenericGenerator(name = "native", strategy = "native")
    @Column(name = "id", updatable = false, nullable = false)
    private Long id;
 
    ...
}

然後,Hibernate 將使用 MySQL 自動增量資料庫列生成主鍵值。

14:41:34,255 DEBUG [org.hibernate.SQL] - insert into Author (firstName, lastName, version) values (?, ?, ?)
14:41:34,298 DEBUG [org.hibernate.id.IdentifierGeneratorHelper] - Natively generated identity: 1

3、映射:只讀視圖

使用 JPA 與 Hibernate,您可以以與任何資料庫表相同的方式來映射視圖。 只要遵循 Hibernate 的命名約定,您只需要實現一個使用了 **@Entity** 註解的類,該類的屬性為您想要映射的列。

如果視圖是只讀的,您應該使用 **@Immutable** 註解告訴 Hibernate。 然後它將忽略對該實體的所有更改。

@Entity
@Immutable
public class BookView {
   
  @Id
  @Column(name = "id", updatable = false, nullable = false)
  private Long id;
 
  @Column(name = "version")
  private int version;
  
  @Column
  private String title;
  
  @Column
  @Temporal(TemporalType.DATE)
  private Date publishingDate;
  
  @Column
  private String authors;
   
  ...
   
}

4、查詢:MySQL特有的函數與數據類型

作為一個資料庫,MySQL 使用一組自定義函數和數據類型來擴展 SQL 標準。 其中的例子是 JSON 數據類型sysdate 函數

JPA 不支持這些,但由於 Hibernate 的 MySQL 方言,您可以使用它們。

Query q = em.createQuery("SELECT a, sysdate() FROM Author a ");
List<Object[]> results = q.getResultList();

如果您發現 Hibernate 的 MySQL 方言不支持的函數或者數據類型,可以使用一個 AttributeConverter 將數據類型轉換為受支持的數據類型和使用 JPQL 函數來調用一個 JPQL 查詢中的任意函數。

但請記住,使用資料庫特有的函數或數據類型,您可以將應用程式綁定到特定的資料庫。如果需要支持不同的資料庫,您將需要更改應用程式的這部分代碼。

5、查詢:存儲過程

許多資料庫管理員喜歡在資料庫中使用存儲過程來執行數據繁重的操作。 大多數情況下,這種方法比在 Java 代碼中執行相同的操作要快得多。

但是,大多數 Java 開發人員並不想使用存儲過程。 當然,有一個說法是業務邏輯分佈在多個系統上,這使得它更加難測試和理解。 另一個原因是在 JPA 2.1 之前,該規範並沒有直接支持存儲過程調用。 你必須使用原生查詢,總之感覺很複雜。

這在 JPA 2.1 引入了 StoredProcedureQuery**@NamedStoredProcedureQuery** 才有所改變。

@NamedStoredProcedureQuery

**@NamedStoredProcedureQuery** 註解允許您定義存儲過程調用一次,且可通過其名稱在業務代碼中引用它。 以下代碼片段展示了一個簡單示例,它定義了存儲過程 calculate 的調用,附帶了輸入參數 xy 以及輸出參數 sum

@NamedStoredProcedureQuery(
    name = "calculate", 
    procedureName = "calculate", 
    parameters = {  @StoredProcedureParameter(mode = ParameterMode.IN, type = Double.class, name = "x"),
            @StoredProcedureParameter(mode = ParameterMode.IN, type = Double.class, name = "y"),
            @StoredProcedureParameter(mode = ParameterMode.OUT, type = Double.class, name = "sum") })

然後,您可以將 **@NamedStoredProcedureQuery** 的名稱提供給 EntityManagercreateNamedStoredProcedureQuery,以實例化一個新的 StoredProcedureQuery

StoredProcedureQuery query = em.createNamedStoredProcedureQuery("calculate");
query.setParameter("x", 1.23d);
query.setParameter("y", 4d);
query.execute();
Double sum = (Double) query.getOutputParameterValue("sum");

您可以在代碼段中看到,您可以設置輸入參數的值,方法與設置 JPQL 查詢的綁定參數值一樣。 您只需使用輸入參數的名稱和值來調用 StoredProcedureQuerysetParameter 方法即可。

StoredProcedureQuery

存儲過程調用的編程定義非常類似於前面示例中給出的基於註解的方法。 您只需使用要執行的存儲過程的名稱配合 EntityManager 調用 createStoredProcedureQuery 即可。有一個 StoredProcedureQuery 介面,您可以使用它來註冊存儲過程的輸入參數和輸出參數。

StoredProcedureQuery query = em.createStoredProcedureQuery("calculate");
query.registerStoredProcedureParameter("x", Double.class, ParameterMode.IN);
query.registerStoredProcedureParameter("y", Double.class, ParameterMode.IN);
query.registerStoredProcedureParameter("sum", Double.class, ParameterMode.OUT);

這就是您定義存儲過程調用全部需要做的事。 之後,您可以與 **@NamedStoredProcedureQuery** 一樣使用它。 在執行存儲過程調用之前,需要設置輸入參數值。

query.setParameter("x", 1.23d);
query.setParameter("y", 4d);
query.execute();

6、總結

如您所見,Hibernate 已經支持大多數 MySQL 特有的功能。 但是,如果要創建一個輕便和性能良好的應用程式,還需要記住一些事項。

特別是在 Hibernate 5 中生成唯一主鍵值和 GenerationType.AUTO 的行為的改變,可能會在將應用程式部署到生產環境時產生意外的可擴展性問題。


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

-Advertisement-
Play Games
更多相關文章
  • 設置調整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+ ...
  • 昨天發佈了 Hibernate 學習筆記第一篇後,今天第二篇來襲~ 此篇筆記是 Hibernate 學習的重點和難點,包括 Hibernate 中的映射關聯關係、Hibernate 的檢索策略與檢索方式(HQL、QBC)、Hibernate 的二級緩存,還包括管理 Session ,如何使 Sess... ...
  • 分類 功能點 Eclipse快捷鍵 IDEA快捷鍵 搜索 搜索文本 Ctrl + F Ctrl + F Ctrl + R 查找替換 Alt + P/A 逐個/全部替換 Alt + F3 查找當前選中詞 繼續搜索 Ctrl + K 向前 Ctrl + Shift + K 向後 F3 Shift + F ...
  • 參考鏈接:http://www.python(tab).com/html/2017/pythonhexinbiancheng_0904/1170.html(去除括弧) http://blog.csdn.net/eastmount/article/details/51082253 首先本文參考了上述兩 ...
  • Lambda表達式(匿名函數)實現了一次執行且無污染的函數定義,是拋棄型函數並且不維護任何類型的狀態。閉包在匿名函數的基礎上增加了與外部環境的變數交互,通過 use 子句中指定要導入的外部環境變數。C字元串以空字元('\0')為結束標誌,這使得C字元串不能保存像圖片、音頻、視頻、壓縮文件這樣的二進位... ...
  • PS:本系列內容進度節奏會放的很慢,每次知識點都儘量少一點,這樣大家接觸的知識點少了,會更容易理解,因為少即是多。另外,對於後面代碼部分,雖然儘量不用那些複雜的封裝和類,但它並不表示看了就能全部記住,並懂得每個函數的用法,在什麼時候去調用,清楚它輸入的參數類型、能處理的參數類型和輸出的結果是什麼。它 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...