1. 程式人生 > >Hibernate(三):Hibernate核心類,介面

Hibernate(三):Hibernate核心類,介面

一,Configuration

      Configuration是 一個介面,作用是對它進行啟動,以及負責管理Configuration的配置資訊,包括以下內容:

  • Hibernate執行的底層資訊:資料庫的URL,使用者名稱,密碼,JDBC驅動,資料庫的Dialect,資料庫連線池(對應hibernate.cfg,xml)
  • 持久化類與資料表的對映關係(*.hbm.xml)

      在Hibernate啟動的過程中Configuration的例項首先先定義對映文件的文職,讀取這些配置,然後建立一個SessionFactory物件。

       一個org.hibernate.cfg.Configuration例項代表了一個應用程式中Java型別到SQL資料庫對映的完整集合。Configuration被用來構建一個不可變的SessionFactory,對映定義則由不同的XML對映定義檔案編譯而來。

1.為Configuration指定對映檔案

     可以直接例項化Configuration來獲取一個例項,併為它指定XML對映檔案,如果對映檔案在類路徑中,請使用addResource()

Configuration cfg = new Configuration().addResource("類路徑");

2.為Configuration指定持久化類

     指定被對映的類, 讓Hibernate去尋找對映定義檔案

Configuration cfg=new Configuration().addClass(com.hibernate.beans.User.class);

Hibernate會在類路徑中尋找名字為/com/ibernate/beans/User.hbml.xml對映定義檔案

3,為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");
4.Configuration的載入方式 
    在Hibernate的啟動與開發中,需要使用一個Configuration,需要為它設定三個內容:資料庫連線屬性,hbm,xml,POJO類(第二個和第三個只需設定一個,就會自動尋找另一個)

  (1)使用hibernate.cfg.xml。該檔案設定了資料庫連線屬性和hbm.xml對映檔案配置。Hibernate會自動載入該配置屬性。

Configuration cfg = new Configuration();
cfg.configuration("hibernate.cfg.xml");

  (2)使用hibernate.properties

Configuration cfg = new Configuration();

  (3)在完全構造時進行硬編碼構造:

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介面負責初始化Hibernate,充當資料儲存源的代理。起到一個緩衝區的作用,緩衝了Hibernate自動生成的 SQL語句和其他對映資料,緩衝了一些將來有可能重複利用的資料。

1.特點:

      針對單個數據庫對映關係經過編譯後的記憶體映象,是執行緒安全的

      SessionFactory物件一旦構造完成,即被賦予特定的配置資訊(一旦SessionFactory構造完成,配置檔案變更不再影響物件)

     構造SessionFactory很浪費資源,一般情況下只初始化一個SessionFactory物件。

    如果操作多個數據庫,必須為每個資料庫指定一個SessionFactory

2.建立SessionFactory物件:

    (1)例項化Configuration物件,預設讀取src目錄下的hibernate.cfg.xml配置檔案

Configuration cfg = new Configuration();
cfg.configuration("hibernate.cfg.xml");
      (2)通過Configuration的buildSessionFactory()方法構建唯一的SessionFactory
SessionFactory sessionFactory = config.buildSessionFactory

Hibernate4 新增了一個 ServiceRegistry 介面,所有基於 Hibernate 的配置或者服務都必須統一向這個 ServiceRegistry  註冊後才能生效
Hibernate4 中建立 SessionFactory 的步驟


三,Session

     Session介面是Hibernate嚮應用程式提供操作資料庫的主要介面,它是抽象了持久化服務概念的核心抽象API類,提供了基本的儲存,更新,刪除和載入Java物件的方法。

特點:

           (1)  是應用程式與資料庫之間互動操作的一個單執行緒物件,是Hibernate的運作中心

             (2)所有持久化物件必須在Session的管理下才可以進行持久化操作

             (3)單執行緒,生命週期短,代表了一次會話過程

              (4)每一個Session例項與一個數據庫事務繫結:每執行一個數據庫事務操作,就先建立一個Session例項,如果事務執行出現異常,撤銷事務。無論成功與否,都要呼叫Session的close()方法,釋放例項佔用的資源

              (5)物件的例項狀態就是之前提到過的三種:臨時狀態(自由),持久化狀態,遊離狀態。

               (6)Session提供的方法使物件的狀態在這三種狀態中來回的變換:

  • 自由狀態的例項可以通過呼叫 save(),persist()或者saveOrUpdate() 方法進行持久化。
  •  持久化例項可以通過呼叫delete()變成遊離狀態。
  • 通過get()或load()方法得到的例項都是持久化狀態的。
  •  遊離狀態的例項可以通過呼叫 update(),saveUpdate(),lock()或者replicate() 進行持久化。
  • 遊離或者自由狀態下的例項可以通過呼叫merge()方法成為一個新的持久化例項。

Session介面中的方法如下:

Method Summary
 void clear()
          完整的清除這個session。
close()
          停止這個Session,通過中斷JDBC連線並且清空(cleaning up)它。

          獲取這個Session的JDBC連線。

如果這個session使用了積極的collection釋放策略(如CMT-容器控制事務的環境下),關閉這個呼叫的連線的職責應該由當前應用程式負責。
 boolean
          檢查這個物件例項是否與當前的Session關聯(即是否為Persistent狀態)。
(Class persistentClass)
          為給定的實體類或它的超類建立一個新的Criteria例項。

          根據給定的實體類或者它的超類建立一個新的Criteria例項,並賦予它(實體類)一個別名。

          根據給定的實體的名稱(name),建立一個新的Criteria例項。

          根據給定的實體的名稱(name),建立一個新的Criteria例項,並賦予它(實體類)一個別名
 Query
          根據給定的collection和過濾字串(查詢條件)建立一個新的Query例項。
 Query
          根據給定的HQL查詢條件建立一個新的Query例項。

          根據給定的SQL查詢條件建立一個新的SQLQuery例項。
 void
          從資料庫中移除持久化(persistent)物件的例項。
 void
          從資料庫中移除持久化(persistent)物件的例項。
 void
          禁用當前session的名稱過濾器。
 void evict(Object object)
          將當前物件例項從session快取中清除。
 void flush()
          強制提交重新整理(flush)Session
get(Class clazz,Serializable id)
          根據給定標識和實體類返回持久化物件的例項,如果沒有符合條件的持久化物件例項則返回null。

          根據給定標識和實體類返回持久化物件的例項,如果沒有符合條件的持久化物件例項則返回null。

          返回與給定的實體命名和標識匹配的持久化例項,如果沒有對應的持久化例項則返回null。

          返回與給定的實體類和標識所匹配的持久化例項,如果沒有對應的持久化例項則返回null。

          獲取給定的實體物件例項在Session的快取中的標識,如果該例項是自由狀態(Transient)的或者與其它Session關聯則丟擲一個異常。
 Query
          從對映檔案中根據給定的查詢的名稱字串獲取一個Query(查詢)例項。

          根據給定的實體模式(Entity Mode)開始一個新的有效的Session。

          獲取與這個session關聯的Transaction(事務)例項。 instance associated with this session.
 boolean
          檢查當前Session是否處於連線狀態。
 boolean
          當前Session是否包含需要與資料庫同步的(資料狀態)變化 ?如果我們重新整理提交(flush)這個session是否會有SQL執行?
 boolean
          檢查當前Session是否仍然開啟。
load(Class theClass,Serializable id)
          在符合條件的例項存在的情況下,根據給定的實體類和標識返回持久化狀態的例項。
load(Class theClass,Serializable id,LockMode lockMode)
          在符合條件的例項存在的情況下,根據給定的實體類、標識及指定的鎖定等級返回持久化狀態的例項。
 void
          將與給定的標示對應的持久化狀態(值)複製到給定的自由狀態(trasient)例項上。

          在符合條件的例項存在的情況下,根據給定的實體類和標識返回持久化狀態的例項。

          在符合條件的例項存在的情況下,根據給定的實體類、標識及指定的鎖定等級返回持久化狀態的例項。
 void lock(Object object,LockMode lockMode)
          從給定的物件上獲取指定的鎖定級別。
 void lock(String entityName,Object object,LockMode lockMode)
          從給定的物件上獲取指定的鎖定級別。
merge(Object object)
          將給定的物件的狀態複製到具有相同標識的持久化物件上。
merge(String entityName,Object object)
          將給定的物件的狀態複製到具有相同標識的持久化物件上。
 void
          將一個自由狀態(transient)的例項持久化。
 void
          將一個自由狀態(transient)的例項持久化。
 void
 void
          從資料庫中重新讀取給定例項的狀態。
 void
          根據指定的鎖定模式(LockMode),從資料庫中重新讀取給定例項的狀態。
 void
          使用當前的標識值持久化給定的遊離狀態(Transient)的實體。
 void
          使用當前的標識值持久化給定的遊離狀態(Transient)的實體。
save(Object object)
          首先為給定的自由狀態(Transient)的物件(根據配置)生成一個標識並賦值,然後將其持久化。
save(String entityName,Object object)
          首先為給定的自由狀態(Transient)的物件(根據配置)生成一個標識並賦值,然後將其持久化。
 void
          根據給定的例項的標識屬性的值(注:可以指定unsaved-value。一般預設null。)來決定執行 save()update()操作。
 void
          根據給定的例項的標識屬性的值(注:可以指定unsaved-value。一般預設null。)來決定執行 save()update()操作。
 void
          將一個未經更改的持久化物件設定為只讀模式,或者將一個只讀物件標記為可以修改的模式。
 void
          根據給定的detached(遊離狀態)物件例項的標識更新對應的持久化例項。
 void
          根據給定的detached(遊離狀態)物件例項的標識更新對應的持久化例項。

(7)獲得Session物件:

  • 獲得SessionFactory物件(上面已講過用法)
  • 根據SessionFactory例項物件獲取Session
Configuration config = new Configuration().configure();
SessionFactory sessionFactory = config.buildSessionFactory();
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
....
tx.commit();
session.close();

(8)管理Session

   Hibernate  自身提供了三種管理 Session 物件的方法

  • Session 物件的生命週期與本地執行緒繫結
  • Session 物件的生命週期與 JTA 事務繫結
  • Hibernate 委託程式管理 Session 物件的生命週期
  在 Hibernate 的配置檔案中, hibernate.current_session_context_class 屬性用於指定 Session 管理方式, 可選值包括
  • thread: Session 物件的生命週期與本地執行緒繫結
  • jta*: Session 物件的生命週期與 JTA 事務繫結
  • managed: Hibernate 委託程式來管理 Session 物件的生命週期
 如果把 Hibernate 配置檔案的 hibernate.current_session_context_class 屬性值設為 thread, Hibernate 就會按照與本地執行緒繫結的方式來管理 Session。Hibernate 按一下規則把 Session 與本地執行緒繫結
  • 當一個執行緒(threadA)第一次呼叫 SessionFactory 物件的 getCurrentSession() 方法時, 該方法會建立一個新的 Session(sessionA) 物件, 把該物件與 threadA 繫結, 並將 sessionA 返回 
  • 當 threadA 再次呼叫 SessionFactory 物件的 getCurrentSession() 方法時, 該方法將返回 sessionA 物件
  • 當 threadA 提交 sessionA 物件關聯的事務時, Hibernate 會自動flush sessionA 物件的快取, 然後提交事務, 關閉 sessionA 物件. 當 threadA 撤銷 sessionA 物件關聯的事務時, 也會自動關閉 sessionA 物件
  • 若 threadA 再次呼叫 SessionFactory 物件的 getCurrentSession() 方法時, 該方法會又建立一個新的 Session(sessionB) 物件, 把該物件與 threadA 繫結, 並將 sessionB 返回 
(9)Session批量處理資料 Session 的 save() 及 update() 方法都會把處理的物件存放在自己的快取中. 如果通過一個 Session 物件來處理大量持久化物件, 應該及時從快取中清空已經處理完畢並且不會再訪問的物件. 具體的做法是在處理完一個物件或小批量物件後, 立即呼叫 flush() 方法重新整理快取, 然後在呼叫 clear() 方法清空快取 程式碼示例:
News news=null;
for(int i=0;i<10000;i++){
         news=new News();
         news.setTitle("--"+i);
         session.save(news);
         if((i+1)%20==0){
               session.flush();
               session.clear();
              }
     }
批量更新: 在進行批量更新時, 如果一下子把所有物件都載入到 Session 快取, 然後再快取中一一更新, 顯然是不可取的
  • 使用可滾動的結果集 org.hibernate.ScrollableResults, 該物件中實際上並不包含任何物件, 只包含用於線上定位記錄的遊標. 只有當程式遍歷訪問 ScrollableResults 物件的特定元素時, 它才會到資料庫中載入相應的物件. 
  • org.hibernate.ScrollableResults 物件由 Query 的 scroll 方法返回
程式碼示例:
通過 Session 來進行處理操作會受到以下約束
  • 需要在  Hibernate 配置檔案中設定 JDBC 單次批量處理的數目, 應保證每次向資料庫傳送的批量的 SQL 語句數目與 batch_size 屬性一致
  • 若物件採用 “identity” 識別符號生成器, 則 Hibernate 無法在 JDBC 層進行批量插入操作
  • 進行批量操作時, 建議關閉 Hibernate 的二級快取