大致錯誤片段
org.hibernate.HibernateException: No Session found for current thread at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
大致問題:hibernate在處理sessoin
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.首先檢查web.xml 的問題
是否配置了org.springframework.orm.hibernate4.support.OpenSessionInViewFilte
<filter> <filter-name>openSessionInVieFilter</filter-name> <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class> </filter> <filter-mapping> <filter-name>openSessionInVieFilter</filter-name> <url-pattern>/web/*</url-pattern> </filter-mapping>
OpenSessionInViewFilte的作用:Spring為我們解決Hibernate的Session的關閉與開啟問題。
2.檢查spring事物配置路徑是否正確
(以下列出一個案例)
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- 聲明式事務管理begin --> <aop:config> <aop:advisor pointcut="execution(* com.*.*.service.impl..*ServiceImpl.*(..))" advice-ref="txAdvice"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="find*" read-only="true"/> <tx:method name="get*" read-only="true"/> <tx:method name="load*" read-only="true"/> <tx:method name="query*" read-only="true"/> <tx:method name="*" rollback-for="Exception"/> </tx:attributes> </tx:advice> <!-- 聲明式事務管理end -->
3.如上面兩個都正確的情況下考慮在sessionfactory中添加hibernate的屬性,自動創建session
sessionFactory里面加上
<prop key="current_session_context_class">thread</prop>