正如博客/书籍中提到的那样(例如 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>