天天看點

Spring JDBCTemplate與Hiberante混用

就像我們知道的一樣,Hibernate是ORM領域事實上的标準,它在操作資料庫方面,提供了最大程度的周遊與快捷,而hibernate與 spring的結合,更是将這種便利發揮到了極緻,這其中得益于HibernateDaoSupport 和HiberateTemplate以及HibernateTransation的大力支援.簡單的來說,有了spring,使得使用Hibernate 的時候,更簡潔,更便利,而統一的聲明事務,又讓本來就已經很簡潔的Hibernate對事務的處理,大大簡化.這其中,得益于AOP思想的應用.可以 說,有了Spring之後,Hibernate就像插上了翅膀,轉化為軟體開發人員手中一件天使一般的工具.不能不說,這是我們這個時代的一個驕傲.

     但任何事務都有兩面性,在帶來大量便捷的同時,Hibernate也給我們留下了一點小小的遺憾,比如衆所周知的,在處理大批量資料查詢的時 候,Hibernate的查詢效率,是不盡人意的,有人做過測試,在高并發查詢的時候,hibernate的查詢效率,僅僅相當于使用jdbc效率7成左 右,這對于對速度有着很高要求的網際網路應用來說,不能不說是悲劇.盡管有存在有各種各樣的緩存解決方案,但還是在高并發查詢下,讓人們對 hibernate的性能,捏了一把汗.同時,hibernate在查詢的時候,所帶來的n+1問題,也一直讓人所诟病.

    進而在批量操作方面,比如在早期,在沒有使用jdbc3.0的batch update的時候,hibernate的批量删除,是讓人很頭痛的, 甚至是一條記錄的删除,也不能做到像jdbc一樣讓人滿意.

     是以,在我們的項目架構中,混合使用hibernate與jdbc,各自發揮各自的優勢與長處,彌補對方的缺陷,提高系統的響應速度.但是需要注意 的時, jdbcTemplate的HibernateTemplate混合使用的時候,要注意其混合事務的處理.

      正如我們以前的項目一樣,一開始在項目中使用的是JDBCTemplate,為了提高開發效率決定采用Hibernate,但是發現Hibernate 在做批量操作時,效率不是很理想。是以現在采用JDBCTemplate和Hibernate混用,JDBCTemplate和Hibernate混用是 可以的,有幾個注意事項. 

1.如果采用JDBCTemplate的部分隻涉及到查詢,則可以使用Hibernate的應用緩存,即二級緩存. 

2.如果采用JDBCTemplate的部分涉及到對資料庫的更新操作,即增,删,改.則不能開啟Hibernate的二級緩存,如果系統有緩存的需要, 我覺得可以自己在邏輯層實作緩存.Java的緩存方案還是很多的. 

3.在使用Spring做為容器的系統中,混用JDBCTemplate和Hibernate,事務管理請統一使用 HibernateTransactionManager,前提是JDBCTemplate和Hibernate共用一個DataSource. 

在HibernateTransactionManager的類說明中有一段原話

This transaction manager is appropriate for applications that use a single Hibernate SessionFactory for transactional data access, but it also supports direct DataSource access within a transaction (i.e. plain JDBC code working with the same DataSource). This allows for mixing services which access Hibernate and services which use plain JDBC (without being aware of Hibernate)! Application code needs to stick to the same simple Connection lookup pattern as with DataSourceTransactionManager (i.e. DataSourceUtils.getConnection(javax.sql.DataSource) or going through a TransactionAwareDataSourceProxy). 複制代碼

從代碼的角度上看也是可以混用的.事務可以統一管理。HibernateTransactionManager的doBegin方法中有這麼一段代碼

1    // add the Hibernate transaction to the session holder

2    txObject.getSessionHolder().setTransaction(session.beginTransaction());

3    // register transaction timeout

4    if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT)

6    {

7       txObject.getSessionHolder().setTimeoutInSeconds(definition.getTimeout());

8    }

9    // bind the session holder to the thread

10    if (txObject.isNewSessionHolder())

11    {

12        TransactionSynchronizationManager.bindResource(this.sessionFactory,      txObject.getSessionHolder());

13    }

14    // register the Hibernate Session's JDBC Connection for the DataSource, if set

15    if (this.dataSource != null)

16 

17    {

18      ConnectionHolder conHolder = new ConnectionHolder(session.connection());

19      if (definition.getTimeout() != TransactionDefinition.TIMEOUT_DEFAULT)

20      {

21           conHolder.setTimeoutInSeconds(definition.getTimeout());

22      }

23     TransactionSynchronizationManager.bindResource(this.dataSource, conHolder);

24    }

25 複制代碼

26   

注意這一注釋  register the Hibernate Session's JDBC Connection for the DataSource, if set

繼續閱讀