5

正如博客/书籍中提到的那样(例如 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) 检索结果集(执行读取操作)
  • 读取操作的功能使用 sessionFactory.getCurrentSession().get() 检索结果集

当然,当Controller执行读操作的功能时,由于没有启动事务,也没有获取到会话,所以会抛出“No Session found for current thread”的异常。

基于上述配置(虽然它是最好的,例如非侵入性、更少代码等),除非之前使用 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>
4

2 回答 2

6

我不同意将 SUPPORTS 用于读取操作。使用必需。

  • 无论如何都需要一个事务来执行每个数据库操作
  • 做几个小事务一次读取几个东西不会从一级缓存中受益
  • 所有后续读取之间不会有任何隔离,这意味着第一次读取不可见的内容可能对第二次读取可见
  • 遍历关联时会出现延迟加载异常
于 2012-05-25T10:06:51.010 回答
0

Propagation.SUPPORTS 并不总是需要事务。Propagation.SUPPORTS:支持当前事务,如果不存在则以非事务方式执行。

于 2012-05-25T10:11:51.760 回答