2010-12-03 90 views
2

我希望我的讀取方法不要使用事務,因爲這根本就不需要,我只用@Transactional標記我的創建/更新方法。但我該怎麼做?我有一個非常基本的配置春天等...Spring&Hibernate:非事務性服務方法

SessionFactory注入我的DAO,並在每個方法我呼籲sessionFactory。 getCurrentSession()。doQueryStuff();

然而這會導致這個錯誤:

org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here 

如果你需要我的Spring配置:

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
xmlns:context="http://www.springframework.org/schema/context" 
xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:oxm="http://www.springframework.org/schema/oxm" 
xmlns:tx="http://www.springframework.org/schema/tx" 
    xmlns:util="http://www.springframework.org/schema/util" 
xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
    http://www.springframework.org/schema/mvc 
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd 
    http://www.springframework.org/schema/oxm 
    http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd 
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util-3.0.xsd"> 

<context:annotation-config /> 
<context:component-scan base-package="be.howest.kidscalcula" /> 
<mvc:annotation-driven /> 

<bean id="viewResolver" 
    class="org.springframework.web.servlet.view.InternalResourceViewResolver"> 
    <property name="prefix"> 
     <value>/WEB-INF/views/</value> 
    </property> 
    <property name="suffix"> 
     <value>.jsp</value> 
    </property> 
</bean> 


<bean id="myDataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
    <property name="driverClassName" value="com.mysql.jdbc.Driver" /> 
    <property name="url" value="jdbc:mysql://localhost/kidscalcula" /> 
    <property name="username" value="root" /> 
    <property name="password" value="" /> 
</bean> 

<bean class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" 
    id="sessionFactory"> 
    <property name="dataSource" ref="myDataSource" /> 
    <property name="mappingResources"> 
     <list> 
      <value>be/howest/kidscalcula/model/Foto.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Kindleerplanonderdeel.hbm.xml 
      </value> 
      <value>be/howest/kidscalcula/model/Klas.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Leerkracht.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Leerling.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Leerplan.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/LeerplanOefenreeks.hbm.xml 
      </value> 
      <value>be/howest/kidscalcula/model/Leerplanonderdeel.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Niveau.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Oefenreeks.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Overgangsregel.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Rapport.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/RapportLeerplanonderdeel.hbm.xml 
      </value> 
      <value>be/howest/kidscalcula/model/Schooljaar.hbm.xml</value> 
      <value>be/howest/kidscalcula/model/Subonderdeel.hbm.xml</value> 
     </list> 
    </property> 
    <property name="hibernateProperties"> 
     <props> 
      <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 
      <prop key="hibernate.connection.pool_size">3</prop> 
      <prop key="hibernate.show_sql">true</prop> 
      <prop key="hibernate.format_sql">true</prop> 
      <prop key="hibernate.use_sql_comments">true</prop> 
      <prop key="hibernate.cache.use_second_level_cache">false</prop> 

     </props> 
    </property> 
</bean> 

<!-- Configure the multipart resolver --> 
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> 
    <!-- one of the properties available; the maximum file size in bytes --> 
    <property name="maxUploadSize" value="500000" /> 
</bean> 


<!-- 
    Transaction manager for a single Hibernate SessionFactory (alternative 
    to JTA) 
--> 
<bean id="transactionManager" 
    class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
    <property name="sessionFactory"> 
     <ref bean="sessionFactory" /> 
    </property> 
</bean> 

<tx:annotation-driven /> 

這個錯誤有什麼用事實傳播是標準要求?

回答

1

即使使用Spring事務管理,也可以在事務之外啓動會話。撥打電話sessionFactory.openSession()即可獲得新會話。此會話是本地的,因爲它不會綁定到線程,因此在撥打sessionFactory.getCurrentSession()時不會返回。您必須對其進行管理,並確保在會話結束時或發生錯誤時正確關閉它。

0

如果沒有(休眠)會話,則無法訪問數據。

一家提供這樣的會話方式是(用時春):

  • org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  • org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter (這取決於您使用的持久性提供者的方式)

這個特效的積極副作用是,在JSP視圖呈現時會話仍處於打開狀態 - 所以在訪問這樣一個尚未加載時,您將不會遇到延遲加載問題屬性而渲染。

@see http://community.jboss.org/wiki/OpenSessioninView

10

標記方法事務和只讀,以保證事務不修改任何數據:

@Transactional(readOnly=true) 

使用Hibernate時,這是一個有用的優化。要了解更多關於這個註釋的含義,這裏是一個偉大的職位:Read-Only transactions with Spring and Hibernate

+0

我知道這存在,但做一個數據讀取沒有事務和一個事務,但在readOnly = true之間的性能差異?我想避免在只讀方法中使用@Transactional,因爲首先不需要事務。 – toomuchcs 2010-12-03 14:02:20

2

隨着消息明確表示,沒有會話被綁定到線程並且已指定不允許「非交易配置「會話被創建。我會盡力解釋每一種情況。

當您的配置中啓用了Spring的事務時(如您所做的那樣),Spring將使用代理來包裝SessionFactory對象,以防止在SessionFactory.getCurrentSession被調用時創建新會話(如果尚未存在)。代理只會獲取綁定到本地線程的當前會話,並且您的代碼不允許創建特定會話(非事務性)。這就是您的配置阻止非事務性會話創建的方式。

當您使用@Transactional註解方法/類時,Spring的TransactionInterceptor將創建一個會話並在方法被調用時將其綁定到當前線程,以便稍後可用。如果啓用了Spring的OpenSessionInViewFilter,它還會將會話綁定到當前線程。由於您沒有執行任何這些操作,因此未找到線程綁定會話。

你應該做的是用@Transactional(readOnly = True)註釋你的類,然後用@Transactional(readOnly = False)註釋你的創建/更新/刪除方法。在閱讀數據時,您必須擁有隻讀事務。這可以確保您在通話期間無人可以提交數據。

相關問題