如何使用Hibernate为Spring MVC中的读操作应用事务最佳实践?

mik*_*e.l 5 spring hibernate transactions

正如博客/书籍中提到的(例如Mark Richards的Java Transactions Design Strategies),读取操作必须具有Propagation.SUPPORTS属性.

在一个带有Hibernate 4.1的简单Spring 3.1 MVC项目中,场景是:

  • 使用@Transactional进行声明式事务管理
  • org.springframework.orm.hibernate4.LocalSessionFactoryBean的sessionFactory
  • org.springframework.orm.hibernate4.HibernateTransactionManager的事务管理器
  • 带@Transactional的服务类(propagation = Propagation.REQUIRED)
  • 仅使用@Transactional(propagation = Propagation.SUPPORTS)检索结果集(执行读取操作)的Service类的功能
  • 读取操作的功能使用sessionFactory.getCurrentSession()来恢复结果集.get()

当然,当Controller执行读操作的功能时,会引发异常"找不到当前线程的会话",因为没有启动事务并且没有获得会话.

基于上述配置(尽管最好是非侵入性,较少代码等),除非在使用Propagation.REQUIRED或Propagation.REQUIRES_NEW之前启动事务,否则不能使用Propagation.SUPPORTS属性.

我们如何使用Propagation.SUPPORTS进行读取操作而无需启动事务,例如之前使用Propagation.REQUIRED但仍然利用声明式事务管理的好处?

先感谢您.

编码器,这是配置:

<tx:annotation-driven transaction-manager="txManager"/>

<context:component-scan base-package="com.myapps.service.impl" />

<bean id="txManager"
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db.driverClassName}" />
    <property name="url" value="${db.url}" />
    <property name="username" value="${db.username}" />
    <property name="password" value="${db.password}" />
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="mappingResources">
        <list>
            <value>.....</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${db.dialect}</prop>
            <prop key="hibernate.format_sql">true</prop>
        </props>
    </property>
</bean>
Run Code Online (Sandbox Code Playgroud)

JB *_*zet 6

我不同意使用SUPPORTS进行读取操作.使用必需.

  • 无论如何都需要一个事务来执行每个数据库操作
  • 执行几个小事务以一次读取多个内容不会从第一级缓存中受益
  • 所有后续读取之间不会有任何隔离,这意味着第一次读取不可见的内容可能会对第二次读取可见
  • 遍历关联时,你会得到延迟加载异常