一、 Hibernate實現Web開發的基本步驟-簡
(1) 創建數據庫
(2) 將Hibernate所需要的JAR包導入項目(WEB-INF/lib下)
(3) 創建Hibernate的配置文件
(4) 利用Hibernate的第三方工具或者eclipse的有關插件從數據庫中創建出相應的實體對象、ORM映射文件(Hibernate支持註解之後無此配置文件)
(5) 創建Hibernate的SessionFactory類
(6) 通過SessionFactory創建Session實例
(7) 通過創建的Session實例踐行持久化對象的管理(CRUD)
(8) 通過創建的Transaction實例進行事務管理
(9) 通過創建的Query或者Criteria實例實現數據庫的查詢
二、 Hibernate的核心接口和類
Hibernate的核心類和接口一共有6個,分別爲:Session、SessionFactory、Transaction、Query、Criteria和Configuration。這6個核心類和接口在任何開發中都會用到。通過這些接口,不僅可以對持久化對象進行存取,還能夠進行事務控制,這一節先對這6個核心接口簡要說一下,再接下來的幾節會做詳細介紹。
1. Configuration
Configuration 類的作用是對Hibernate 進行配置,以及對它進行啓動。在Hibernate 的啓動過程中,Configuration 類的實例首先定位映射文件的位置,讀取這些配置,然後創建一個SessionFactory對象。雖然Configuration 類在整個Hibernate 項目中只扮演着一個很小的角色,但它是啓動hibernate 時所遇到的第一個對象。
2. SessionFactory
SessionFactory接口負責初始化Hibernate。它充當數據存儲源的代理,並負責創建Session對象。這裏用到了工廠模式。需要注意的是SessionFactory並不是輕量級的,因爲一般情況下,一個項目通常只需要一個SessionFactory就夠,當需要操作多個數據庫時,可以爲每個數據庫指定一個SessionFactory。
3. Session
Session接口負責執行被持久化對象的CRUD操作(CRUD的任務是完成與數據庫的交流,包含了很多常見的SQL語句)。但需要注意的是Session對象是非線程安全的。同時,Hibernate的session不同於JSP應用中的HttpSession。這裏當使用session這個術語時,其實指的是Hibernate中的session,而以後會將HttpSession對象稱爲用戶session。
4. Transaction
Transaction 接口是一個可選的API,可以選擇不使用這個接口,取而代之的是Hibernate 的設計者自己寫的底層事務處理代碼。 Transaction 接口是對實際事務實現的一個抽象,這些實現包括JDBC的事務、JTA 中的UserTransaction、甚至可以是CORBA 事務。之所以這樣設計是能讓開發者能夠使用一個統一事務的操作界面,使得自己的項目可以在不同的環境和容器之間方便地移植。
5. Query
Query接口讓你方便地對數據庫及持久對象進行查詢,它可以有兩種表達方式:HQL語言或本地數據庫的SQL語句。Query經常被用來綁定查詢參數、限制查詢記錄數量,並最終執行查詢操作。
6. Criteria
Criteria接口與Query接口非常類似,允許創建並執行面向對象的標準化查詢。值得注意的是Criteria接口也是輕量級的,它不能在Session之外使用。
三、 Hibernate的體系結構
在Hibernate的體系結構中,Hibernate Session這個概念非常重要,只有處於Session管理下的POJO纔有持久化操作的能力。當應用程序對處於Session管理下的POJO實例執行操作時,Hibernate將這種面向對象的操作轉換爲持久化操作。在使用Hibernate時,需要用到一個名爲hibernate。properties的文件,此文件用於配置Hibernate與數據庫的連接信息。還有映射文件(現在基本使用註解形式,持久化類和數據表之間的映射文件就不需要了)。
Hibernate的持久化解決方案將用戶從原始的JDBC訪問中釋放出來,用戶無需關心底層的JDBC操作,而是以面型對象的方式進行持久化操作。底層數據連接的獲得、數據訪問的實現、事務控制都無需用戶關心。這是一種“全面解決”的體系結構方案,將應用層從底層的JDBC/JTA API中抽象出來。
一個簡要的 Hibernate 整體體系結構大致如下圖所示:
Application:應用
persistent objects:持續化對象
properties:屬性,性能
XML Mapping:XML映射
從上圖可以看出,Hibernate 使用數據庫(Database)和配置信息(hibernate.properties 等)來爲應用程序提供持久化服務(以及持久的對象 Persistent Objects)。
我們再來看看 Hibernate 運行時的體系結構。由於Hibernate非常靈活,且支持多種應用方案,所以這裏我們只描述一下兩種極端的情況。
1、 “輕型”的體系結構方案
要求應用程序提供自己的 JDBC 連接並管理自己的事務。這種方案使用了 Hibernate API 的最小子集:
2、 “全面解決”的體系結構方案
將應用層從底層的 JDBC/JTA API 中抽象出來,而讓 Hibernate 來處理這些細節:
四、 使用Hibernate操作數據(最基本)
從上往下依次進行:
(1) 創建一個Configuration實例conf並且調用.configure()方法加載配置文件
(2) conf.buildSessionFactory()創建一個SessionFactory類sf
(3) sf.openSession()創建一個Session類sess
(4) sess.beginTransaction()創建一個Transaction事務類tx,開啓事務
(5) 操作實體
(6) sess.save(entity);保存消息
(7) tx.commit()提交事務
(8) sess.close();關閉Session
(9) sf.close();關閉SessionFactory
也就是說,Hibernate的工作流程是:首先通過configuration對象讀取配置文件;解析映射信息,創建StandardSessionFactory;調用openSession打開session;創建事務transaction,之後進行持久化操作;完成後提交事務,關閉session,關閉sessionFactory。
五、 核心接口之Configuration
1) 接口介紹
Configuration接口的作用是對Hibernate進行配置,以及對他進行啓動,在Hibernate的啓動過程中,Configuration類的實例首先定位映射文檔的位置,讀取這些配置,然後創建一個SessionFactory對象
一個org.hibernate.cfg.Configuration實例代表了一個應用程序中Java類型到SQL數據庫映射的完整集合。Configuration被用來構建一個不可變的SessionFactory,映射定義則由不同的XML映射定義文件編譯而來。
2) Configuration有以下幾個方面的操作函數
(1)爲Configuration指定映射文件
你可以直接實例化Configuration來獲取一個實例併爲他指定XML映射定義文件 如果映射定義文件在類路徑中 請使用addResource()
Configuration cfg = new Configuration().addResource("com/demo/hibernate/beans/User.hbm.xml");
(2)爲Configuration指定持久化類
一個替代的方法是指定被映射的類 讓Hibernate幫你尋找映射定義文件
Configuration cfg = new Configuration().addClass(com.demo.hibernate.beans.User.class);
Hibernate將會在類路徑中需找名字爲/com/demo/hibernate/beans/User.hbm.xml 映射定義文件 消除了任何對文件名的硬編譯
(3)爲Configuration指定配置屬性
Configuration也允許指定配置屬性
Configuration cfg =new Configuration().addClass(com.demo.hibernate.beans.User.class)
setProperty("hibernate.dialect","org.hibernate.dialect.MySQLInnoDBDialect")
setProperty("hibernate.connection.datasource","java:comp/env/jdbc/test")
setProperty("hibernate.order_update","true");
六、 核心接口之SessionFactory
接口SessionFactory使用工廠設計模式。通過SessionFactory對象可以獲取Session對象,Hibernate4已經將configuration的buildSessionFactory方法已經劃線了,說明已經過時了,不過這不影響我們web開發人員使用(如果不追求極致深層次的話)。
參看hibernate源碼。以及API幫助文檔,發現Hibernate4新增了一個接口ServiceRegistry,所有基於Hibernate的配置或者服務都必須統一向這個ServiceRegistry註冊後才能生效。所以不難看出 Hibernate4的配置入口不再是Configuration對象,而是ServiceRegistry對象,Configuration對象將通過ServiceRegistry對象獲取配置信息。使用了Builder模式創建一個ServiceRegistry對象,可以看到源碼org.hibernate.service.ServiceRegistryBuilder這個類。
具體獲取如下:
import org.hibernate.HibernateException;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class Test {
private static Configuration configuration = null;
private static SessionFactory sessionFactory = null;
private static ServiceRegistry serviceRegistry = null;
public static void main(String[] args) {
try {
configuration = new Configuration().configure();
serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
sessionFactory = configuration.buildSessionFactory(serviceRegistry);
} catch (HibernateException e) {
e.printStackTrace();
}
}
}
七、 核心接口之Session
1) Session介紹
Session:是應用程序與數據庫之間的一個會話,是hibernate運作的中心,持久層操作的基礎。持久化對象的生命週期、事務的管理、數據庫的查詢、存取都與Session息息相關。Hibernate在操作數據庫之前必須先取得Session對象,相當於JDBC在操作數據庫之前必須先取得Connection對象一樣。
Session對象不是線程安全的(ThreadSafe),一個Session對象最好只由一個單一線程來使用。
2) Session創建
Session對象是通過SessionFactory構建的,有兩種方式分別是:getCurrentSession()或者openSession(),在Spring的管理中我們可以這樣獲取Session:
@Autowired
private SessionFactory sessionFactory;
public Session getSession() {
return sessionFactory.getCurrentSession();
}
@Override
public T save(T entity){
Session session = getSession();
session.save(entity);
return entity;
}
3) 需要注意點
(1)openSession和getCurrentSession的區別?
*openSession必須關閉,currentSession在事務結束後自動關閉
*openSession沒有和當前線程綁定,currentSession和當前線程綁定
如果使用currentSession需要在hibernate.cfg.xml文件中進行配置:
*如果是本地事務(jdbc事務)
<propertyname="hibernate.current_session_context_class">thread</property>
*如果是全局事務(jta事務)
<propertyname="hibernate.current_session_context_class">jta</property>
全局事務:資源管理器管理和協調的事務,可以跨越多個數據庫和進程。資源管理器一般使用XA 二階段提交協議與“企業信息系統”(EIS) 或數據庫進行交互。
本地事務:在單個 EIS或數據庫的本地並且限制在單個進程內的事務。本地事務不涉及多個數據來源。
(2)和jdbc的聯繫
獲取Session對象後,Hibernate內部並不會獲取操作數據庫的java.sql.Connection對象,而是等到Session對象真正需要對數據庫進行CRUD等操作時,纔會從數據庫連接池中獲取java.sql.Connection對象。
而關閉Session對象時,則是將java.sql.Connection對象返回連接池,而不是直接關閉java.sql.Connection對象。
八、 核心接口之Transaction
摘自-《開源中國》黃勇的文章《Transaction 那點事兒》,
九、 核心接口之Query
Session session = getSession();
String hql = null;
hql = "from Authorization where serviceId ='"+serviceId+"'";
Query query = session.createQuery(hql);
Authorization authorization = (Authorization) query.uniqueResult();
return null;
上面代碼只是爲了說明Query這個接口的用法,具體的詳細內容還要在實踐中去獲得,這裏就不詳細介紹了。
十、 核心接口之Criteria
Hibernate進行軟件開發進行數據查詢時,主要基於HQL(Hibernate 面向對象的查詢語言,語法類似SQL)、Criteria(面向對象的條件查詢對象)、SQL(原生態SQL語句)幾種方式。
Criteria 是一個完全面向對象,可擴展的條件查詢API,通過它完全不需要考慮數據庫底層如何實現、SQL語句如何編寫,是Hibernate框架的核心查詢對象。Hibernate 定義了CriteriaSpecification接口規範用來完成面向對象的條件查詢,Criteria就是CriteriaSpecification的子接口。
Criteria與Session綁定,其生命週期跟隨着Session結束而結束,使用Criteria時進行查詢時,每次都要於執行時期動態建立物件,並加入各種查詢條件,隨着Session的回收,Criteria也跟着回收。
Session session = getSession();
Criteria criteria = session.createCriteria(clazz);
Criteria 和 DetachedCriteria (Criteria 和 DetachedCriteria 的主要區別在於創建的形式不一樣, Criteria 是在線的,是由Hibernate Session 進行創建的;而 DetachedCriteria 是離線的,創建時無需Session)均可使用Criterion 和Projection 設置查詢條件。可以設置 FetchMode( 聯合查詢抓取的模式 ) ,設置排序方式。對於 Criteria 還可以設置 FlushModel(沖刷 Session 的方式)和 LockMode (數據庫鎖模式)。
Criterion 是 Criteria 的查詢條件。Criteria提供了 add(Criterion criterion) 方法來添加查詢條件。
Criterion 的實例可以通過 Restrictions 工具類來創建,Restrictions 提供了大量的靜態方法,如 eq (等於)、 ge (大於等於)、 between 等來方法的創建 Criterion 查詢條件(SimpleExpression 實例)
Criterion criterion1 = Restrictions.like(“name”,”李%”);
Criterion criterion2 = Restrictions.like(“id”,new Integer(1),new Integer(10));
criteria.add(criterion1);
criteria.add(criterion2);
十一、 Hibernate中對象的三種狀態
1. 瞬時態
hibernate中什麼時候的對象爲瞬時態呢,當我們new 一個對象時,還沒有save時,它就是瞬時態的,當我們delete一個對象時,它也是瞬時態了,因爲此時,他們在數據庫中沒有對應的記錄存在。兩點特徵:
1)不在Session的緩存中,不與任何的Session實例相關聯
2)在數據庫中沒有與之相對應的記錄
2. 持久態
當我們save一個對象時,這個對象會保存到數據庫,同時也會緩存在session中,同時,當我們get(),load(),updateOrSave()一個對象時,也會將這個對象緩存在session中,這時緩存中的對象與數據庫是同步的,也就是持久態的,任何一方的改變都會同步更新。兩點特徵:
1)在Session的緩存中,與Session實例相關聯。
2)在數據庫中存在與之相對應的記錄
3. 遊離態
當對象從持久態轉變爲另一狀態時,這個狀態就是遊離態了。比如:session.close(),session.evict()對象時,對象從session緩存中清除,數據庫中有數據,緩存中沒有數據,因爲數據庫中有數據,所以它是可以再被持久化的.兩點特徵:
1)不在Session的緩存中,不與任何Session實例相關聯。
2)在數據庫中存在與之相對應的記錄(前提是沒有其他Session實例刪除該條記錄)。