架個spring4+hibernate4的demo,dao層直接注入的sessionFactory,而後用getCurrentSession方法獲取session,而後問題來了,直接報錯:spring
Could not obtain transaction-synchronized Session for current thread
提示沒法獲取當前線程的事務同步session,略微奇怪,這和事務有什麼關係..而後百度一下有人說改爲用openSession方法就行了,那我又百度了一下這2個方法的區別:api
(1)openSession每次打開都是新的Session,因此屢次獲取的Session實例是不一樣的,而且須要人爲的調用close方法進行Session關閉。
(2)getCurrentSession是從當前上下文中獲取Session而且會綁定到當前線程,第一次調用時會建立一個Session實例,若是該Session未關閉,後續屢次獲取的是同一個Session實例;事務提交或者回滾時會自動關閉Sesison,無需人工關閉。
看起來這個getCurrentSession方法的確和事務有點關係.而後我加上事務:session
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean> <tx:annotation-driven transaction-manager="transactionManager"/>
而後在dao層加上@Transaction註解,再運行ok了..不過好奇驅使吧,看了一下getCurrentSession的源碼(個人demo中用的spring的實現類),關鍵點:this
if (TransactionSynchronizationManager.isSynchronizationActive()) { Session session = this.sessionFactory.openSession(); if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) { session.setFlushMode(FlushMode.MANUAL); } SessionHolder sessionHolder = new SessionHolder(session); TransactionSynchronizationManager.registerSynchronization( new SpringSessionSynchronization(sessionHolder, this.sessionFactory, true)); TransactionSynchronizationManager.bindResource(this.sessionFactory, sessionHolder); sessionHolder.setSynchronizedWithTransaction(true); return session; } else { throw new HibernateException("Could not obtain transaction-synchronized Session for current thread"); }
而後點進去看了一下isSynchronizationActive()方法:spa
public static boolean isSynchronizationActive() { return (synchronizations.get() != null); }
get方法說明:hibernate
Returns the value in the current thread's copy of this thread-local variable. If the variable has no value for the current thread, it is first initialized to the value returned by an invocation of the initialValue method.
而後再看initialValue的說明:線程
This implementation simply returns null; if the programmer desires thread-local variables to have an initial value other than null, ThreadLocal must be subclassed, and this method overridden. Typically, an anonymous inner class will be used.
到此問題明瞭了,補充一點以前配置文件中配了事務,不過是原來那種在配置中根據方法名字來定義事務傳播的方式,可是在dao中並無繼承它,故其實是沒有事務的,只有實現.而在spring的事務實現中須要判斷當前線程中的事務是否同步,而沒有事務的時候,那個判斷是否同步的方法會由於get返回初始的null值而返回false,最終致使throw一個Could not obtain transaction-synchronized Session for current thread的異常.code
綜上:spring4+hibernate4,使用hibernate的api的時候須要配置事務的,若是不配置事務會致使獲取當前session拋出異常.orm