春天& Hibernate:非事务性服务方法

时间:2010-12-03 11:17:47

标签: java hibernate spring transactions annotations

我希望我的读取方法不使用事务,因为根本不需要它,我只用@Transactional标记我的创建/更新方法。但是我该怎么做?我有一个非常基本的Spring配置等...

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 />

此错误是否与传播标准为必需的事实有关?

4 个答案:

答案 0 :(得分:10)

将方法标记为事务性并且只读以确保事务不会修改任何数据:

@Transactional(readOnly=true)

使用Hibernate时,这是一个非常有用的优化。要详细了解此注释的含义,请阅读以下文章: Read-Only transactions with Spring and Hibernate

答案 1 :(得分:3)

正如消息中明确指出的那样,没有会话绑定到该线程,并且您指定的配置不允许创建“非事务”会话。我将尝试解释每个场景。

当你的配置中启用了Spring的事务时(正如你所做的那样),当调用SessionFactory.getCurrentSession时,Spring将使用代理来封装SessionFactory对象,该代理可以阻止创建新会话(如果尚未存在)。代理只会获取绑定到本地线程的当前会话,并且代码不允许创建临时会话(非事务性)。这就是您的配置阻止非交易会话创建的方式。

当您使用@Transactional注释方法/类时,Spring的TransactionInterceptor将创建一个会话,并在调用该方法时将其绑定到当前线程,以便以后可用。 Spring的OpenSessionInViewFilter,如果启用,还会将会话绑定到当前线程。由于您没有执行任何这些操作,因此未找到线程绑定会话。

您应该做的是使用@Transactional(readOnly = True)注释您的类,然后使用@Transactional(readOnly = False)注释您的创建/更新/删除方法。在读取数据时,必须具有只读事务。这可以确保没有人可以在该呼叫期间提交数据。

答案 2 :(得分:2)

即使使用Spring事务管理,也可以在事务之外启动会话。致电sessionFactory.openSession()以获取新会话。此会话是本地会话,因为它不绑定到某个线程,因此在您调用sessionFactory.getCurrentSession()时不会返回该会话。您必须对其进行管理,并确保在会话结束时正确关闭或发生错误。

答案 3 :(得分:0)

如果没有(休眠)会话,您将无法访问数据。

提供此类会话的一种方法是(使用spring时):

  • org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
  • org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter (这取决于您使用持久性提供程序的方式)

这个fiters的积极副作用是,在呈现JSP视图时会话仍处于打开状态 - 因此在渲染时访问这样一个尚未加载的属性时,您将没有延迟加载问题。

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