Hibernate4中使用getCurrentSession報Could not obtain transaction-synchronized Session for current thread

架個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

相關文章
相關標籤/搜索