Hibernate4 與 spring3 集成之後, 如果在取得session 的地方使用了getCurrentSession, 可能會報一個錯:“No
Session found for current thread”, 這個錯誤的原因,網上有很多解決辦法, 但具體原因的分析,卻沒有多少,
這裏轉載一個原理分析:
SessionFactory的getCurrentSession並不能保證在沒有當前Session的情況下會自動創建一個新的,這取決於CurrentSessionContext的實現,SessionFactory將調用CurrentSessionContext的currentSession()方法來獲得Session。在Spring中,如果我們在沒有配置TransactionManager並且沒有事先調用SessionFactory.openSession()的情況直接調用getCurrentSession(),那麼程序將拋出“No
Session found for current
thread”異常。如果配置了TranactionManager並且通過@Transactional或者聲明的方式配置的事務邊界,那麼Spring會在開始事務之前通過AOP的方式爲當前線程創建Session,此時調用getCurrentSession()將得到正確結果。
然而,產生以上異常的原因在於Spring提供了自己的CurrentSessionContext實現,如果我們不打算使用Spring,而是自己直接從hibernate.cfg.xml創建SessionFactory,並且爲在hibernate.cfg.xml
中設置current_session_context_class爲thread,也即使用了ThreadLocalSessionContext,那麼我們在調用getCurrentSession()時,如果當前線程沒有Session存在,則會創建一個綁定到當前線程。
Hibernate在默認情況下會使用JTASessionContext,Spring提供了自己SpringSessionContext,因此我們不用配置current_session_context_class,當Hibernate與Spring集成時,將使用該SessionContext,故此時調用getCurrentSession()的效果完全依賴於SpringSessionContext的實現。
在沒有Spring的情況下使用Hibernate,如果沒有在hibernate.cfg.xml中配置current_session_context_class,有沒有JTA的話,那麼程序將拋出"No
CurrentSessionContext
configured!"異常。此時的解決辦法是在hibernate.cfg.xml中將current_session_context_class配置成thread。
在Spring中使用Hibernate,如果我們配置了TransactionManager,那麼我們就不應該調用SessionFactory的openSession()來獲得Sessioin,因爲這樣獲得的Session並沒有被事務管理。
至於解決的辦法,可以採用如下方式:
1. 在spring
配置文件中加入
程序代碼
<tx:annotation-driven
transaction-manager="transactionManager"/>
並且在處理業務邏輯的類上採用註解
程序代碼
@Service
public class CustomerServiceImpl
implements CustomerService {
@Transactional
public void
saveCustomer(Customer customer)
{
customerDaoImpl.saveCustomer(customer);
}
...
}
另外在
hibernate 的配置文件中,也可以增加這樣的配置來避免這個錯誤:
程序代碼
<property
name="current_session_context_class">thread</property>
需要的可以參考這裏的代碼,有源代碼下載測試:http://www.yihaomen.com/article/java/501.htm