1. 程式人生 > >Could not obtain transaction-synchronized Session for current thread

Could not obtain transaction-synchronized Session for current thread

ram form string spa 實現 sql 新的 line nal

今天運行程序時 報了 如下的錯誤。

Could not obtain transaction-synchronized Session for current thread

在Spring中使用Hibernate,如果我們配置了TransactionManager,那麽我們就不應該調用SessionFactory的openSession()來獲得Sessioin,因為這樣獲得的Session並沒有被事務管理。我們應該使用getCurrentSession()

Spring 修改

在Spring中,如果我們在沒有配置TransactionManager並且沒有事先調用SessionFactory.openSession()的情況直接調用getCurrentSession(),那麽程序將拋出“No Session found for current thread”異常。如果配置了TranactionManager並且通過@Transactional或者聲明的方式配置的事務邊界,那麽Spring會在開始事務之前通過AOP的方式為當前線程創建Session,此時調用getCurrentSession()將得到正確結果。

可以由上面的看到首先在Spring 和Hibernate 整合時 ,如果我們沒有配置TranscationManager,但是直接調用了getCurrentSession(),那麽就出現了這個錯誤,所以我們現在首先要將TranscationManager 加入進來。

解決辦法:

1. 在Spring中加入事務 即使這個只是個查詢的事務,不過我們可以設置此為一個ReadOnly 事務

1) 將事務的標簽加入對應的方法中

1     @Transactional(readOnly = true)
2     public int findBookPriceByIsbn(String isbn) {
3 String hql = "SELECT b.price FROM Book b WHERE b.isbn = ?"; 4 Query<Integer> query = getSession().createQuery(hql).setParameter(0, isbn); 5 return query.uniqueResult(); 6 }

2)在xml中配置事務

1     <bean id="transactionManager"
2         class="org.springframework.orm.hibernate5.HibernateTransactionManager"
> 3 <property name="sessionFactory" ref="localSessionFactoryBean"></property> 4 </bean> 5 6 <tx:annotation-driven transaction-manager="transactionManager" />

Hibernate中修改:

其實我們也可以在Hibernate 中進行修改 , 當我們不需要Spring的時候

然而,產生以上異常的原因在於Spring提供了自己的CurrentSessionContext實現,如果我們不打算使用Spring,而是自己直接從hibernate.cfg.xml創建SessionFactory,並且為在hibernate.cfg.xml
中設置current_session_context_class為thread,也即使用了ThreadLocalSessionContext,那麽我們在調用getCurrentSession()時,如果當前線程沒有Session存在,則會創建一個綁定到當前線程。

我們可以看到 當我們不使用Spring的時候 其實也會出現這個錯誤,歸根結底在於有沒有開這個session

解決方案:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 <hibernate-configuration>
 6     <session-factory>
 7         <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
 8         <property name="hibernate.show_sql">true</property>
 9         <property name="hibernate.format_sql">true</property>
10         <property name="hibernate.hbm2ddl.auto">update</property>
       //添加新的屬性 11 <property name="current_session_context_class">thread</property> 12 </session-factory> 13 </hibernate-configuration>

web.xml解決方案:

在項目中,利用SessionFactory.getCurrentSession()方法獲取hibernate的會話,當在一個controller方法中多次使用訪問數據庫,會報出錯誤:Could not obtain transaction-synchronized Session for current thread
在這裏應該用一下spring中的OpenSessionInViewFilter,否則,需要每次使用完成後關閉session,下一次使用才不會報錯,但是又涉及到一個lazy loading的問題,關閉session之後就無法懶加載,所以使用OpenSessionInViewFilter是一個兩全的選擇

1  <filter>
2        <filter-name>SpringOpenSessionInViewFilter</filter-name>
3        <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
4      </filter>
5   <filter-mapping>
6     <filter-name>SpringOpenSessionInViewFilter</filter-name>
7     <url-pattern>/*</url-pattern>
8   </filter-mapping>

參考資料:

1.SpringMVC4+Hibernate4運行報錯Could not obtain transaction-synchronized Session for current thread

2. Hibernate4 No Session found for current thread原因

3. spring+hibernate Could not obtain transaction-synchronized Session for current thread

Could not obtain transaction-synchronized Session for current thread