Hibernate

Hibernate是個ORM框架

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

ORM框架

ORM(Object-Relational Mapping),若是照著字義上來翻譯,那就是「物件關係的映射」,實際上它其實只是一種概念。

在程式語言中,通常在表示資料都是以「物件的方式」來撰寫;而對應在「關聯式資料庫 (RDBMS)」中,表示資料的形式則會是資料表內的資料。

在兩者之間,存在著一種對應的映射關係,這種映射關係的概念,就是所謂的 ORM。而 ORM 概念的誕生,其實也是因為物件導向程式開發的崛起。

當物件與表資料之間存在映射關係的時候,就可以讓我們在開發程式時,無須操作許多繁瑣的 SQL 語句,同時在資料的安全面上,也可以避免 SQL 語句的一些惡意注入攻擊。因此在 ORM 的概念上,是可以減少那些對資料庫進行基本操作的程式開發。

不過既然是具有映射的關係,就代表著在有些時候效能可能不如原本來的好。另外雖然 ORM 的概念可以減輕那些 SQL 的學習成本,但其實也就只是學個半套,若對於資料庫本身的基本設計不清楚,那麼在資料庫的設計與維護上,會更容易有力不從心的感覺。

所以 ORM 的概念是可以將資料提取並應射程物件的形式,但如果對於需要做複雜的操作,像是多個表之間的 join 或查詢,比起直接下 SQL 語句是相較來的稍微綁手綁腳些。

參考: https://medium.com/learning-from-jhipster/13-甚麼是-jdbc-orm-jpa-orm框架-hibernate-c762a8c5e112

JPA和Hibernate的差異

JPA 僅僅是一種管理資料庫的規範。JPA 沒有具體的實現,因為它是一種指導方針,用於操作我們的資料庫。另一方面,Hibernate 則是 JPA 規範的具體實現。Hibernate 是符合 JPA 規範所定義的 API 的代碼實現。

簡而言之,JPA 可以被稱為介面,而 Hibernate 則是這些介面的實現。

JPA 為開發者提供了無縫進行資料庫操作的標準,而 Hibernate 則使用這些 Java 持久化 API 的標準來進行資料庫操作。

還值得一提的是,JPA 有其本身的查詢語言,稱為 Java 持久化查詢語言(JPQL),這是一種面向對象的查詢語言,用於進行資料庫操作。而 Hibernate 則使用 HQL(Hibernate Query Language),這同樣是一種面向對象的查詢語言,用於進行資料庫操作。

定義

  • JPA 是一套規範,它定義了Java持久化對象的標準方法。JPA提供了一組接口和註解,用於映射對象到關係數據庫。
  • Hibernate 是JPA規範的一個實現。除了實現JPA規範外,Hibernate還提供了許多超出JPA規範的功能。

功能範圍

  • JPA作為規範,主要定義了ORM(對象關係映射)的標準操作,如實體管理(Entity Management)、查詢語言(Query Language)等。
  • 實體管理(Entity Management)
    實體管理是 JPA 中用於管理持久化對象生命周期的機制。在 JPA 中,一個實體(Entity)是指一個輕量級的持久化域對象,通常對應資料庫中的一行數據。實體管理涉及以下關鍵概念:

  • 實體管理器(EntityManager):是 JPA 中用於實體的增刪改查操作的主要接口。它負責管理實體的生命周期,包括實體的創建、讀取、更新和刪除(CRUD)操作。
    持久化上下文(Persistence Context):是實體實例的集合,這些實例當前正在被管理(即在資料庫中有對應記錄)。持久化上下文跟蹤實體的狀態變化,並在事務提交時同步這些變化到資料庫。
    事務(Transaction):JPA 中的操作通常在事務的上下文中執行,以確保數據的一致性和完整性。
    查詢語言(Query Language)
    JPA 提供了一種獨立於資料庫的查詢語言——JPQL(Java Persistence Query Language),它允許開發者以面向對象的方式進行查詢,而不是依賴於特定資料庫的 SQL 語法。

  • JPQL(Java Persistence Query Language):是一種抽象的查詢語言,用於在持久化實體上執行查詢。JPQL 語句類似於 SQL,但操作的是實體對象而不是資料庫表。例如,一個查詢實體的 JPQL 語句可能看起來像這樣:SELECT e FROM Employee e WHERE e.salary > :salary。

  • Criteria API:是另一種構建類型安全查詢的方法。它提供了一套 Java API,用於構建動態查詢,特別適合於需要在運行時構建複雜查詢的情況。
    命名查詢(Named Queries):JPA 允許將查詢定義為靜態常量,這樣可以在實體類中通過註解預定義查詢,並在應用程式中通過名稱引用它們,以提高代碼的可重用性和清晰度。
    總的來說,JPA 的實體管理和查詢語言提供了一套豐富的機制,使得開發者可以以面向對象的方式管理資料庫中的數據,同時也提供了強大的查詢能力,以滿足各種複雜的數據操作需求。

  • Hibernate提供了JPA中定義的所有功能,並且還擴展了許多高級功能,如二級緩存(Second Level Cache)、查詢緩存(Query Cache)、惰性載入(Lazy loading)等。

在 Hibernate 中,二級快取(Second Level Cache)和查詢快取(Query Cache)是兩種用於提升應用效能的快取機制:

  • 二級快取(Second Level Cache)
    二級快取是 Hibernate 中的一個可選快取,用於跨會話(Session)快取實體資料。它位於會話快取(第一級快取)和資料庫之間。
    當啟用二級快取時,如果一個實體被多個會話訪問,那麼在第一次訪問資料庫載入實體後,實體資料可以被快取。後續的會話可以直接從二級快取中獲取這些資料,而不需要再次訪問資料庫,從而減少資料庫訪問次數,提升應用效能。
    二級快取需要顯式配置,並且可以根據實體類精細控制哪些實體被快取。

  • 查詢快取(Query Cache)
    查詢快取是用於快取查詢結果的一種機制。當啟用查詢快取時,Hibernate 會快取查詢結果集的識別符(而不是實體本身),以及查詢的參數和查詢語句。
    當相同的查詢(查詢語句和參數都相同)再次執行時,Hibernate 可以直接從查詢快取中獲取結果集的識別符,然後結合二級快取中的實體資料來重建查詢結果,從而避免了對資料庫的訪問。
    查詢快取通常用於快取頻繁執行且返回結果相對穩定的查詢。由於查詢快取需要維護查詢結果的一致性,所以在使用時需要謹慎,以避免因資料變更導致的快取資料和資料庫資料不一致的問題。

總的來說,二級快取和查詢快取是 Hibernate 提供的兩種高級快取機制,通過減少資料庫訪問來提升應用效能。然而,它們的使用需要仔細考慮快取的一致性和應用場景,以確保快取資料的準確性和有效性。

靈活性和擴展性

  • 使用JPA使得應用程序可以不依賴於特定的ORM實現,從而提高了代碼的可移植性。如果需要,開發者可以輕鬆地從一個ORM實現切換到另一個。
  • Hibernate作為JPA的實現,提供了更多的配置選項和優化功能,但這也意味著使用Hibernate特有功能的代碼可能不容易移植到其他JPA實現。

查詢語言

  • JPA定義了一種平台無關的查詢語言——JPQL(Java Persistence Query Language),用於對數據庫進行操作。
  • Hibernate提供了一種更為強大的HQL(Hibernate Query Language),並且支持原生SQL和Criteria查詢,給開發者提供了更多的靈活性。

參考資料

HQL 基本介紹

HQL 為 Hibernate 的查詢語句,他很類似於 SQL 但是比所能達到的功能有些許限制
重點是 HQL 為一種物件導向式的查詢語言,簡單說 HQL 是可以直接針對實體物件進行查詢、修改
而不像 SQL 是針對 Table,以下用一個最簡單的 selectfrom 來介紹 HQL
一般的 SQL 的 select * from t_product - 指 撈出 t_product 這個 table 的所有欄位資料
如果是 HQL 會這樣寫 select p from Product p - 這裡的 Product 為一個實體物件
以上這樣的寫法 可以簡化成 from Product as p 或是 from Product p
甚至還可以這樣寫 from Product
只要記得的是 from 後面接的是一個 Java 的實體類別,如果只是要撈出 t_product 的 name 欄位呢?

HQL : select p.name from Product - 注意這裡的 p.name
p 目前唯一個 Product 的物件,p.name 表示了 p 物件的 name 屬性
也就是說在定義 Product 這個類別時一定會有著一個叫 name 的屬性
而且還可以利用建構子的方式達成同樣的效果

HQL : select new Product(p.name) from Product p

以下繼續運用 Hibernate 的 API 執行一個完整的查詢語句

List<Product> list = null;
try{
    session = HibernateUtils.getSession(); //取得 Session
    tx = session.beginTransaction()//開始交易
    
    Query query = session.createQuery("from Product"); //運用session建立 Query 對象
    list = query.list(); //執行查詢,傳回結果List
    
    tx.commit() //提交事務
}catch(Exception e){....}

在Hibernate 2時,HQL只用於查詢資料,要更新或刪除資料,則是依賴於Session的update()、saveOrUpdate()、delete()等方法, 在Hibernate 3中,HQL新增了update與delete語句,可以直接使用HQL指定更新或刪除,例如使用update子句進行更新:

Session session = sessionFactory.openSession();
Transaction tx= session.beginTransaction();
Query query = session.createQuery("update User set name='momor' where name='bbb'");
query.executeUpdate();
tx.commit();
session.close();

使用delete子句進行資料刪除:

Session session = sessionFactory.openSession();
Transaction tx= session.beginTransaction();
Query query = session.createQuery("delete User where name='bush'");
query.executeUpdate();
tx.commit();
session.close();

Hibernate with Maven Project

https://www.digitalocean.com/community/tutorials/hibernate-tutorial-for-beginners