2010-12-03 141 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)注释你的创建/更新/删除方法。在阅读数据时,您必须拥有只读事务。这可以确保您在通话期间无人可以提交数据。