[Hibernate] Hibernate 5.4 Getting Started Guide 官方入門文檔

  前言

最近的精力主要集中在Hibernate上,在乎識到Hibernate 5 的中文資料並很少的時候,我不得不把目光轉向Hibernate的官方doc,學習之餘簡要翻一下入門文檔。html

原文地址:https://docs.jboss.org/hibernate/orm/5.4/quickstart/html_single/,勘誤請在評論區留言java

原文序

使用面向對象軟件和關係型數據庫可能既麻煩且耗時。開發成本每每會因數據在軟件和數據庫中的數據範式(paradigm)表現不一而顯著地增加,Hibernate就是一種Java語言環境下的一個對象/關係映射 解決方案(ORM框架),對象/關係映射(ORM)的概念,則代指一種將數據的對象模型形式,即在軟件中的表現形式,和數據模型形式,即數據庫中的表現形式,這兩種形式的數據相映射的技術。能夠參照Wikipedia上的ORM詞條以得到更詳細的瞭解。git

雖然Hibernate並不要求用戶須要有很是豐富的SQL編程經驗,可是對於一些概念的基本理解着實可讓你更快更全面的理解Hibernate,特別是對數據建模原理的理解就顯得尤其重要,這兩篇文章能夠幫助你快速開始理解這些原理dataModeling101 、DataModeling(wiki)github

Hibernate負責Java class和數據庫表的映射工做,同時也會處理二者間數據格式的映射。另外,它還提供了數據查詢和獲取功能。它能夠節省開發者本來須要的手動數據處理時間(若是你使用SQL和JDBC這些原生手段的話)Hibernate的設計目標是將開發者從95%的平常持久化編程步驟中解放出來,開發者再無需手冊來經過SQL和JDBC手動處理數據。同時,不像其餘持久化方案,Hibernate並不會將原生SQL的優勢隱藏起來,你依舊可使用它,意味着你以前所付出的學習和相關知識依然十分有價值。數據庫

HIbernate可能不是那些以數據爲中心的,重度依賴存儲過程的應用的最佳解決方案。它更適合於對於數據相關的應用中間層,這種狀況下,它的確能夠去除掉那些針對特定數據庫而寫的SQL,流水化查詢的數據集轉譯到對象表(對於編程語言而言)。編程

See http://hibernate.org/orm/contribute/ for information on getting involved.api

本文章中涉及的項目代碼能夠從這裏下載: hibernate-tutorials.zip緩存

  

1. 獲取 Hibernate

1.1. Hibernate Modules/Artifacts

Hibernate’s 的功能被分紅一些不一樣的 modules/artifacts 用來隔離依賴關係(模塊化).安全

hibernate-core

Hibernate 核心module. 定義了ORM功能和API,還有不一樣的集成SPIs(方便第三方進行自定義擴展).session

hibernate-envers

Hibernate歷史實體版本控制功能

hibernate-spatial

Hibernate空間數據集和GIS(地理信息系統)數據類型支持

hibernate-osgi

Hibernate對在OSGi容器中運行的支持。

hibernate-agroal

Hibernate Agroal 鏈接池支持

hibernate-c3p0

Hibernate  C3P0 鏈接池支持

hibernate-hikaricp

Hibernate  HikariCP 鏈接池支持

hibernate-vibur

Hibernate  Vibur DBCP 鏈接池支持

hibernate-proxool

Hibernate  Proxool 鏈接池支持

hibernate-jcache

Hibernate JCache 緩存支持 , 使得任何兼容的組件成爲二級緩存的提供者。

hibernate-ehcache

Hibernate Ehcache 緩存支持。使得Ehache成爲二級緩存提供者。

 1.2. 發行包下載

Hibernate發行包存放在 SourceForge File Release System, 有 TGZ 和 ZIP 兩種格式,兩種都包含了JAR文件、文檔、源代碼和其餘一些東西。

你能夠從這裏下載:https://sourceforge.net/projects/hibernate/files/hibernate-orm/. 如下是發行包目錄結構:

  • lib/required/ 目錄包含 hibernate-core jar包和它的依賴。全部的jar包都須要在在classpath下,不論那些功能有沒有被用到。

  • lib/envers 目錄包含 hibernate-envers jar包和它的依賴 (先包含lib/required/ 和 lib/jpa/).

  • lib/spatial/ 目錄包含 hibernate-spatial jar包和它的依賴 (先包含 lib/required/)

  • lib/osgi/ 目錄包含 hibernate-osgi jar包和它的依賴 (先包含 lib/required/ 和lib/jpa/)

  • lib/jpa-metamodel-generator/ 目錄包含 生成Criteria API類型安全的元模型(Criteria API type-safe Metamodel)所需的jar。

  • lib/optional/ 目錄包含 Hibernate提供的各類鏈接池和第二級緩存集成所需的jar及其依賴。

1.3. Maven Repository Artifacts

Hibernate artifacts的權威倉庫爲the JBoss Maven repository. Hibernate artifacts會自動同步到這上面(可能會延遲發佈).

負責JBoss Maven倉庫的團隊維護着許多包含重要信息的Wiki頁面:

Hibernate ORM artifacts發佈在org.hibernate groupId下。

2. 使用Hibernate原生 API 和 hbm.xml 映射文件 

  本示例位於您下載的壓縮包中的basic/.
 
 
目標
  • 啓動 Hibernate SessionFactory

  • 使用 Hibernate 映射文件(hbm.xml)來提供映射信息

  • 使用Hibernate原生API

2.1. Hibernate配置文件

在本示例中,  hibernate.cfg.xml 文件定義了Hibernate配置信息

connection.driver_classconnection.urlconnection.username 和connection.password <property/> 元素定義了JDBC鏈接信息這些示例使用內置的H2 in-memory 數據庫,因此全部的屬性被設置成H2數據庫以在內存中運行connection.pool_size 用來配置內置鏈接池的大小。

  內置的Hibernate鏈接池並不能用於實際應用中,對比實際應用中的的鏈接池它缺少一些基本功能

 

dialect元素定義了Hibernate會使用的特定SQL類型

  絕大多數狀況下, Hibernate 可以自動選擇數據庫的方言(dialect),當你使用多種數據庫時這點尤爲有用(注:3.x版本不清楚)

 

hbm2ddl.auto 屬性開啓自動生成數據庫schema,也即自動建表功能。

最後,添加映射文件到配置文件中, 位於 <mapping/> 元素中的resource 使得Hibernate會嘗試去使用用java.lang.ClassLoader 在classpath下進行查找。

有許多方式能夠用於啓動SessionFactory,詳見the Native Bootstrapping topical guide. 

2.2. Java類

本示例中的實體類爲示例代碼中的: org.hibernate.tutorial.hbm.Event

關於實體類:
  • 實體類使用標準JavaBean的命名規範,包括getter/setter和私有的變量,雖然這是推薦的用法,但並不強制

  • 無參構造函數,一樣做爲JavaBean的規範,則要求必須實現,Hibernate須要經過反射機制(Java Reflection)爲你建立實體類(即查詢結果時),構造函數不能是私有的,同時,包可見性也要保證,這樣才能經過java運行時代理機制(runtime proxy)生成以保證無需經過 字節碼檢測(bytecode instrumentation)進行代理。

2.3. 映射文件

本示例中的映射文件位於 org/hibernate/tutorial/hbm/Event.hbm.xml (同上文).

Hibernate 使用映射元數據來決定如何加載和存儲持久化類,Hibernate 映射文件就是提供元數據的一種方式。

示例 1. 類映射元素
<class name="Event" table="EVENTS">
    ...
</class>

 關於 <varname>class</varname> 映射元素:

  • name 屬性 (可在 <hibernate-mapping/> 中添加package屬性來定義包名) 定義了類名

  • table 屬性定義表名

到此爲止,Event類和EVENTS數據庫表被關聯起來。

示例 2. Id映射
<id name="id" column="EVENT_ID">
    ...
</id>

 Hibernate 使用 <id/> 元素來確保行惟一性。

  id元素不須要映射到表的實際主鍵列,但這是常規約定。在Hibernate中映射的表甚至不須要定義主鍵。可是,強烈建議全部schema都定義適當的參照完整性。如此一來,id和主鍵在整個Hibernate中能夠互換使用 。

 

此處的<id/> 元素將EVENT_ID列命名爲EVENTS表的主鍵。它還將Event類的id屬性標識爲包含標識符值的屬性。

 generator 元素通知Hibernate使用哪一種策略爲該實體生成主鍵值。本示例使用簡單的遞增計數。(注,在其餘相關性能調優指南文章中,有說起不要使用id生成器,會那樣會阻止批量插入)

示例 3. 屬性映射元素
<property name="date" type="timestamp" column="EVENT_DATE"/>
<property name="title"/>

這兩個 <property/>元素聲明瞭Event 類的其他兩個持久屬性:date 和title 。date 屬性映射包括列屬性,但title 不包含。在沒有列屬性的狀況下,Hibernate默認使用屬性名稱做爲列名稱。這適用於title,可是因爲date 是大多數數據庫中的保留關鍵字,所以您須要爲列名指定一個非保留字。 

title映射也缺乏類型屬性。映射文件中聲明和使用的類型既不是Java原生數據類型也不是SQL數據庫類型。相反,它們是Hibernate映射類型,它們是在Java和SQL數據類型之間轉換的轉換器。若是未在映射中指定type屬性,則Hibernate嘗試自動肯定正確的轉換和映射類型,方法是使用Java反射來肯定已聲明屬性的Java類型,並使用該Java類型的默認映射類型(注:如,BigInteger->Integer)。

在某些狀況下,如date 屬性所示,此自動檢測可能未選擇您指望或須要的默認值。 Hibernate沒法知道類型爲java.util.Date的屬性是否應映射到SQL DATE,TIME或TIMESTAMP數據類型。經過將屬性映射到timestamp轉換器(timestamp converter)來保存完整的日期和時間信息,該轉換器標識轉換器類org.hibernate.type.TimestampType

  處理映射文件時,Hibernate使用反射來肯定映射類型。此過程增長了時間和資源方面的開銷。若是啓動性能( startup performance)很重要,請考慮明肯定義要使用的類型。

 

2.4. 示例代碼

 org.hibernate.tutorial.hbm.NativeApiIllustrationTest 類說明了如何使用Hibernate原生API。

  爲了易於使用,這些教程中的示例以JUnit測試的形式呈現。這種方法的優勢之一是setUp() tearDown() 大體說明了如何在應用程序啓動時建立org.hibernate.SessionFactory並在應用程序生命週期結束時將其關閉。
 
 
示例 4. 獲取 org.hibernate.SessionFactory
protected void setUp() throws Exception {
    // A SessionFactory is set up once for an application!
    final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
            .configure() // configures settings from hibernate.cfg.xml
            .build();
    try {
        sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();
    }
    catch (Exception e) {
        // The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory
        // so destroy it manually.
        StandardServiceRegistryBuilder.destroy( registry );
    }
} 

setUp方法首先建立org.hibernate.boot.registry.StandardServiceRegistry實例,該實例將配置信息合併到服務(Services,有特指)的工做集中以供SessionFactory使用。在本教程中,咱們在hibernate.cfg.xml中定義了全部配置信息。

使用StandardServiceRegistry咱們建立org.hibernate.boot.MetadataSources,這是向Hibernate告知您的Domain模型的起點。再一次,由於咱們在hibernate.cfg.xml中定義了它,因此這邊沒什麼東西好講的。 org.hibernate.boot.Metadata表示SessionFactory將基於的應用程序域模型的完整,部分驗證的視圖。

引導程序的最後一步是構建SessionFactory。 SessionFactory是一個線程安全的對象,實例化一次便可服務整個應用程序。

SessionFactory充當org.hibernate.Session實例的工廠,應將其視爲「工做單元」的必然(corollary )結果。

示例 5. 保存實體

Session session = sessionFactory.openSession();
session.beginTransaction();
session.save( new Event( "Our very first event!", new Date() ) );
session.save( new Event( "A follow up event", new Date() ) );
session.getTransaction().commit();
session.close();

testBasicUsage() 首先使用save() 方法建立一些新的Event對象並將其交給Hibernate進行管理。 Hibernate如今負責爲每一個Event在數據庫上執行INSERT。 

示例 6. 獲取List結果集
session = sessionFactory.openSession();
session.beginTransaction();
List result = session.createQuery( "from Event" ).list();
for ( Event event : (List<Event>) result ) {
    System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
}
session.getTransaction().commit();
session.close();

 在這裏,咱們看到一個Hibernate查詢語言(HQL)的示例,該示例經過生成適當的SELECT SQL,將其發送到數據庫,並使用結果集數據填充Event對象來從數據庫加載全部現有的Event對象。

2.5. 下一步!

練習
  • 從新配置示例以鏈接到您本身的持久關係數據庫。 

  •  Add an association to the Event entity to model a message thread.

3. 使用 Hibernate 原生API 和 註解式映射

  本示例位於您下載的壓縮包中的 annotations/.
 
 
目標:
  • 啓動 Hibernate SessionFactory

  • 使用 Java註解來提供映射信息

  • 使用Hibernate原生API

3.1. Hibernate配置文件

內容與上文的Hibernate配置文件相同,但有一個重要區別...最後的<mapping />元素使用class屬性命名帶註釋的實體類。

3.2. 註解的Java類

本示例中的實體類是遵循JavaBean約定的org.hibernate.tutorial.annotations.Event。實際上,該類自己與實體Java類中的類相同,只不過註釋用於提供元數據而不是單獨的映射文件。

示例7.將類標識爲實體
@Entity
@Table( name = "EVENTS" )
public class Event {
    ...
}

 @ javax.persistence.Entity註釋用於將類標記爲實體。它的功能與映射文件中討論的<class />映射元素相同。此外,@ javax.persistence.Table註釋顯式指定了表名。若是沒有此規範,默認表名稱將爲EVENT。

示例8. 標記id屬性

@Id
@GeneratedValue(generator="increment")
@GenericGenerator(name="increment", strategy = "increment")
public Long getId() {
    return id;
}

@ javax.persistence.Id標記定義實體標識符的屬性。

@ javax.persistence.GeneratedValue@ org.hibernate.annotations.GenericGenerator協同工做以指定Hibernate應該對該實體的標識符值使用Hibernate的增量生成策略。

示例9. 標記基本屬性
public String getTitle() {
    return title;
}

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "EVENT_DATE")
public Date getDate() {
    return date;
}

與映射文件中同樣,日期屬性須要進行特殊處理以考慮其特殊命名和SQL類型。 帶有註釋的映射默認狀況下將實體的屬性視爲持久化屬性(與數據庫字段相同),這就是爲何咱們看不到任何與title相關的映射信息的緣由。 

3.3. 示例代碼

org.hibernate.tutorial.annotations.AnnotationsIllustrationTest本質上與示例代碼中討論的org.hibernate.tutorial.hbm.NativeApiIllustrationTest相同。

3.4. 下一步!

練習
  • 向事件實體添加關聯以對消息線程進行建模。有關更多詳細信息,請使用《用戶指南》。 

  • 添加回調以在建立,更新或刪除事件時接收通知。使用事件監聽器嘗試相同的操做。有關更多詳細信息,請使用《用戶指南》。

4. 使用 Java Persistence API (JPA)

  本示例位於您下載的壓縮包中的 entitymanager/.
 
 
目標:
  • 啓動JPA EntityManagerFactory 

  • 使用 Java註解來提供映射信息

  • 使用JPA API 

4.1. persistence.xml

以前的教程使用了特定於Hibernate的hibernate.cfg.xml配置文件。可是,JPA定義了一個不一樣的引導過程,該過程使用其本身的名爲persistence.xml的配置文件。該引導過程由JPA規範定義。在Java SE環境中,須要持久性提供程序(在這種狀況下爲Hibernate)經過META-INF / persistence.xml資源名稱的類路徑查找來定位全部JPA配置文件。

示例10. persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
        version="2.0">
    <persistence-unit name="org.hibernate.tutorial.jpa">
        ...
    </persistence-unit>
</persistence>

persistence.xml文件應爲每一個「持久性單元」提供惟一的名稱。在獲取javax.persistence.EntityManagerFactory引用時,應用程序使用此名稱來引用配置。

Hibernate配置文件中討論了<properties />元素中定義的設置。這裏儘量使用javax.persistence前綴的變體。請注意,其他特定於Hibernate的配置設置名稱如今以hibernate前綴。

此外,<class />元素的功能與咱們在Hibernate配置文件中看到的相同。

4.2. 註解的Java類

實體與上節註解的的Java類中的徹底相同。

4.3. 示例代碼

先前的教程使用了Hibernate原生API。本教程使用JPA API

示例11. 獲取 javax.persistence.EntityManagerFactory
protected void setUp() throws Exception {
    sessionFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );
}

再次注意,持久化單元名稱是org.hibernate.tutorial.jpa,與persistence.xml相匹配。

示例12. 保存實體類
EntityManager entityManager = sessionFactory.createEntityManager();
entityManager.getTransaction().begin();
entityManager.persist( new Event( "Our very first event!", new Date() ) );
entityManager.persist( new Event( "A follow up event", new Date() ) );
entityManager.getTransaction().commit();
entityManager.close();

該代碼相似於上文的保存實體類。使用javax.persistence.EntityManager接口代替org.hibernate.Session接口。 JPA將此操做稱爲「持久化」(persistence)而不是「保存」(save)。

示例13. 獲取List結果集
entityManager = sessionFactory.createEntityManager();
entityManager.getTransaction().begin();
List<Event> result = entityManager.createQuery( "from Event", Event.class ).getResultList();
for ( Event event : result ) {
    System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );
}
entityManager.getTransaction().commit();
entityManager.close();

一樣,該代碼與咱們在獲取上文的 獲取List結果集看到的很是類似。

4.4. 下一步!

練習
  • 開發一個EJB Session bean來研究使用容器管理的持久性上下文的含義。嘗試無狀態(stateless )和有狀態(stateful )兩種狀況。 

  • 將事件監聽器(listeners)與基於CDI的注入(CDI-based injection)結合使用,以開發基於JMS的事件消息中心 

5. 使用 Envers

  本示例位於您下載的壓縮包中的 envers/.
 
 
目標
  • 將實體註釋爲歷史對象
  •  配置 Envers

  • 使用Envers API查看和分析歷史數據

5.1. persistence.xml

這個文件在JPA 示例中已提過 persistence.xml, 並且基本是同樣的

5.2. 註解的Java類

一樣,該實體與上文:註釋的Java類中的相同。主要區別在於添加了@ org.hibernate.envers.Audted註釋,該註釋告訴Envers自動跟蹤對此實體的更改。

5.3. 示例代碼

該代碼保存了一些實體,對其中一個實體進行了更改,而後使用Envers API來查詢初始修訂(revision)以及更新的修訂。修訂是指實體的歷史快照(snapshot )。

示例14. 使用org.hibernate.envers.AuditReader
public void testBasicUsage() {
    ...
    AuditReader reader = AuditReaderFactory.get( entityManager );
    Event firstRevision = reader.find( Event.class, 2L, 1 );
    ...
    Event secondRevision = reader.find( Event.class, 2L, 2 );
    ...
}

能夠看到:咱們從org.hibernate.envers.AuditReaderFactory得到了一個org.hibernate.envers.AuditReader,它包裝了javax.persistence.EntityManager。 

接下來,find 方法檢索實體的特定修訂版。第一次調用找到ID爲2的事件的修訂版本1。第二次調用找到ID爲2的事件的修訂版本2。

5.4.下一步!

練習
  • 提供自定義修訂版本實體,以額外獲取進行更改的人員。 

  •  寫一個只取回符合條件歷史數據的查詢。 使用 User Guide 查看 Envers 查詢如何建立。(Envers用於在自動生成記錄更改信息的數據表,用於審計)

  • 嘗試使用具備各類關係(多對一,多對多等)的審計實體(auditing entities)。嘗試查找此類實體的歷史版本(修訂版)並瀏覽對象樹。
相關文章
相關標籤/搜索