Hibernate常用API詳解及源碼分析 .


一:使用SchemaExport自動創建數據庫表

         我相信在此之前大家應該都是用最原始的方法:SQL建立數據庫相關的表,然后再Java寫映射寫配置文件.現在我們學習了hibernate以后就可以用一些偷懶的方式了,我們可以使用SchemaExport自動創建數據庫,建立根據你的對象建立數據庫表。下面我們來看一下具體操作:

首先當然要建好POJO object, XML Mapping File(也可以使用工具根據POJO class建立),配置文件(hibernate.cfg.xml),然后運行下面的Java代碼

  1. import org.hibernate.cfg.Configuration;   
  2.   
  3. import org.hibernate.tool.hbm2ddl.SchemaExport;  
  4.   
  5.   
  6. public class SchemaUtil {  
  7.     public static void main(String[] args) {  
  8.   
  9.         Configuration cfg = new Configuration().configure();  
  10.   
  11.         SchemaExport schemaExport= new SchemaExport(cfg);  
  12.   
  13.         schemaExport.create(falsetrue);  
  14.   
  15.     }  
  16. }  


再看看數據庫,表是不是已經幫你建好了,對於我這樣不熟悉數據庫的人真是太方便了。

 

 

二.使用Hibernate操作數據庫需要七個步驟

(1讀取並解析配置文件

Configuration conf = new Configuration().configure();

(2)讀取並解析映射信息,創建SessionFactory

SessionFactory sf = conf.buildSessionFactory();

(3)打開Session

Session session = sf.openSession();

(4)開始一個事務(增刪改操作必須,查詢操作可選)

Transaction tx = session.beginTransaction();


(5)數據庫操作

session.save(user);//或其它操作

(6)提交事務(回滾事務)

tx.commit();(tx.rollback();)

7)關閉session

session.close();

下面我們來詳細看一下這七大步驟的API

Configuration:負責管理Hibernate的配置信息,這些配置信息都是從配置文件hibernate.cfg.xml或者Hibernate.properties讀取的,當然也可以自定義文件名稱,只要在實例化Configuration的時候指定具體的路徑就可以了;他為什么會自動加載hibernate.cfg.xml文件的呢?我們看一下configure源碼就一目了然了

  1. public Configuration configure() throws HibernateException {  
  2.   
  3. configure( "/hibernate.cfg.xml" );  
  4.   
  5. return this;  
  6.   
  7. }  


從這里我們可以看出,在hibernate源碼中,他就是默認的加載hibernate.cfg.xml,當然你也可以指定加載配置文件,Configuration提供了相應的方法:

 

public Configuration configure(String resource)

public Configuration configure(URL url)

public Configuration configure(File configFile)

 

SessionFactioryConfiguration的實例會根據當前的配置信息,構造SessionFactory實例。SessionFactory是線程安全的,一般情況下一個應用中一個數據庫共享一個SessionFactory實例。

 HibernateSessionFactory接口提供Session類的實例,Session類用於完成對數據庫的操作。由於SessionFactory實例是線程安全的(而Session實例不是線程安全的),所以每個操作都可以共用同一個SessionFactory來獲取Session

Hibernate配置文件分為兩種格式,一種是xml格式的配置文件,另一種是Java屬性文件格式的配置文件,因此構建SessionFactory也有兩種方法,下面分別介紹。

1 . 從XML文件讀取配置信息構建SessionFactory
XML文件讀取配置信息構建SessionFactory的具體步驟如下。

1)創建一個Configuration對象,並通過該對象的configure()方法加載Hibernate配置文件,代碼如下。

Configuration config = new Configuration().configure();

2)完成配置文件和映射文件的加載后,將得到一個包括所有Hibernate運行期參數的Configuration實例,通過Configuration實例的buildSessionFactory()方法可以構建一個惟一的SessionFactory,代碼如下。

SessionFactory sessionFactory = config.buildSessionFactory();

構建SessionFactory要放在靜態代碼塊中,因為它只在該類被加載時執行一次。

2  從Java屬性文件讀取配置信息構建SessionFactory
從Java屬性文件讀取配置信息構建SessionFactory的具體步驟如下。

(1)創建一個Configuration對象,此時Hibernate會默認加載classpath中的配置文件hibernate.properties,代碼如下。

Configuration config = new Configuration();

(2)由於在配置文件中缺少相應的配置映射文件的信息,所以此處需要通過編碼方式加載,這可以通過Configuration對象的

addClass()方法實現,具體代碼如下。

config.addClass(BranchForm.class);

addClass()方法用於加載實體類。

(3)完成配置文件和映射文件的加載后,將得到一個包括所有Hibernate運行期參數的Configuration實例,通過Configuration實例

的buildSessionFactory()方法可以構建一個惟一的SessionFactory,代碼如下。

SessionFactory sessionFactory = config.buildSessionFactory();

 

Session一般的持久化方法(CRUD)都是通過Session來調用的,Session是非線程安全的。

Session的創建與關閉 :Session是一個輕量級對象,通常將每個Session實例和一個數據庫事務綁定,也就是每執行一個數據庫事務,都應該先創建一個新的Session實例,在使用Session后,還需要關閉Session

Session的創建

創建SessionFactory后,就可以通過SessionFactory創建Session實例,通過SessionFactory創建Session實例的代碼如下。

Session session=sessionFactory.openSession();

創建Session后,就可以通過創建的Session進行持久化操作了。

Session的關閉

在創建Session實例后,不論是否執行事務,最后都需要關閉Session實例,釋放Session實例占用的資源。

關閉Session實例的代碼如下:

session.close();

 

下面來看一下:getCurrentSession 與 openSession() 的區別

1.getCurrentSession創建的session會和綁定到當前線程,openSession不會。

2 getCurrentSession創建的線程會在事務回滾或事物提交后自動關閉,openSession必須手動關閉

3. getCurrentSession () 使用當前的sessionopenSession() 重新建立一個新的session

這里getCurrentSession本地事務(本地事務:jdbc)時 要在配置文件里進行如下設置

 * 如果使用的是本地事務(jdbc事務)
 <property name="hibernate.current_session_context_class">thread</property>
 * 如果使用的是全局事務(jta事務)
 <property name="hibernate.current_session_context_class">jta</property> 

openSession() 與 getCurrentSession() 有何不同和關聯呢?

在 SessionFactory 啟動的時候,Hibernate 會根據配置創建相應的 CurrentSessionContext,在 getCurrentSession() 被調用的時候,實際被執行的方法是 CurrentSessionContext.currentSession() 。在 currentSession() 執行時,如果當前 Session 為空,currentSession 會調用 SessionFactory 的 openSession。所以 getCurrentSession() 對於 Java EE 來說是更好的獲取 Session 的方法。

 

事務transactionHibernate是對JDBC的輕量級對象封裝,Hibernate本身是不具備Transaction處理功能的,HibernateTransaction實際上是底層的JDBC Transaction的封裝,或者是JTA Transaction的封裝,下面我們詳細的分析:

Hibernate可以配置為JDBCTransaction或者是JTATransaction,這取決於你在hibernate.properties或者hibernate.cfg.xml中的配置,如果你什么都不配置,默認情況下使用JDBCTransaction,如果你配置為: hibernate.transaction.factory_class =net.sf.hibernate.transaction.JTATransactionFactory 

將使用JTATransaction 

JDBCTransaction究竟是什么東西呢?來看看源代碼就清楚了: 

Hibernate3.3.2源代碼中的類 org.hibernate.transaction;.JDBCTransaction: 

  1. public void begin() throws HibernateException {  
  2.   
  3.  ...  
  4.   
  5. try {  
  6.   
  7. toggleAutoCommit= jdbcContext.connection().getAutoCommit();  
  8.   
  9. if ( log.isDebugEnabled() ) {  
  10.   
  11. log.debug("currentautocommitstatus: " + toggleAutoCommit);  
  12.   
  13. }  
  14.   
  15. if (toggleAutoCommit) {  
  16.   
  17. log.debug("disabling autocommit");  
  18.   
  19. jdbcContext.connection().setAutoCommit(false);  
  20.   
  21. }  
  22.   
  23. } ... }   


 

這是啟動Transaction的方法,看到 connection().setAutoCommit(false) 了嗎?是不是很熟悉? 再來看 

  1. public void commit() throws HibernateException {   
  2.   
  3. ...   
  4.   
  5. try {  
  6.   
  7. commitAndResetAutoCommit();  
  8.   
  9. log.debug("committed JDBC Connection");  
  10.   
  11. committed = true;  
  12.   
  13. if ( callback ) {  
  14.   
  15. jdbcContext.afterTransactionCompletion( truethis );  
  16.   
  17. }  
  18.   
  19. notifyLocalSynchsAfterTransactionCompletion( Status.STATUS_COMMITTED );  
  20.   
  21. }... ; }   
  22.   
  23. commitAndResetAutoCommit方法源碼:  
  24.   
  25. private void commitAndResetAutoCommit() throws SQLException {  
  26.   
  27. try {  
  28.   
  29. jdbcContext.connection().commit();  
  30.   
  31. }  
  32.   
  33. finally {  
  34.   
  35. toggleAutoCommit();  
  36.   
  37. }}  


      這是提交方法,看到connection().commit() 了嗎?下面就不用我多說了,這個類代碼非常簡單易懂,通過閱讀使我們明白HibernateTransaction都在干了些什么?我現在把用Hibernate寫的例子翻譯成JDBC,大家就一目了然了: 

Connection conn = ...; <--- session = sf.openSession(); 

conn.setAutoCommit(false); <--- tx = session.beginTransactioin(); ... <--- ... conn.commit(); <--- tx.commit(); (對應左邊的兩句)

 conn.setAutoCommit(true); conn.close(); <--- session.close(); 

 

       看明白了吧,HibernateJDBCTransaction根本就是conn.commit而已,根本毫無神秘可言,只不過在Hibernate中,Session打開的時候,就會自動conn.setAutoCommit(false),不像一般的JDBC,默認都是true,所以你最后不寫commit也沒有關系,由於Hibernate已經把AutoCommit給關掉了,所以用Hibernate的時候,你在程序中不寫Transaction的話,數據庫根本就沒有反應。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM