java – Spring只读事务将数据提交给DB

我正在尝试按照Spring Framework Reference的第11.5.2项实现服务方法的只读事务,但事务仍然会自动将数据提交到数据库.

我正在使用Spring 3.1.0.RELEASE,Hibernate 3.5.5-Final和Oracle 11g Express Edition Release 11.2.0.2.0.这是我的设置:

建议,切入点,顾问和事务管理器的XML:

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="get*" read-only="true" />
        <tx:method name="*"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="myServiceMethods" expression="execution(* my.example.service.*.*(..))" />
    <aop:advisor pointcut-ref="myServiceMethods" advice-ref="transactionAdvice" />
</aop:config>

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
    <!-- the sessionFactory bean declaration does not set the -->
    <!-- hibernate.connection.autocommit property as either true or false -->
</bean>

服务界面:

package my.example.service;

public interface MyService {

    void getFoo();

    void bar();
}

服务实施:

package my.example.service.impl;

import my.example.dao.MyDao;
import my.example.domain.MyEntity;
import my.example.service.MyService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    private MyDao dao;

    public void getFoo() {
        MyEntity example = this.dao.getMyEntity(1L);
        example.setSomeInteger(2);
        example.setSomeString("three");
    }

    public void bar() {
        MyEntity example = this.dao.getMyEntity(4L);
        example.setSomeInteger(5);
        example.setSomeString("six");
    }
}

在调用getFoo()或bar()之后,即使getFoo()被标记为只读,DB也会更新.但如果我改变这两行:

<tx:method name="get*" read-only="true" />
<tx:method name="*"/>

至:

<tx:method name="*" read-only="true" />

两种方法都遵循只读属性,数据不会提交给DB.

这是怎么回事?我究竟做错了什么?我错过了什么?

解决方法:

我发现为什么只读事务被覆盖.在web.xml中声明了一个OpenSessionInViewFilter,以前的开发人员在加载用户及其在控制器/接口中的角色时用来阻止LazyInitializationExceptions.

这是过滤器声明:

<filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>

我通过配置过滤器来解决这个问题,让每个事务都使用自己的会话(称为延迟模式).

这是激活延迟模式的过滤器声明:

<filter>
    <filter-name>openSessionInViewFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <param-name>singleSession</param-name>
        <param-value>false</param-value>
    </init-param>
</filter>

请阅读过滤器的Javadoc中的NOTE.我的DAO类扩展了org.springframework.orm.hibernate3.support.HibernateDaoSupport,并且继承方法返回的Hibernate Session getSession()或getSessionFactory().getCurrentSession()将其flush模式设置为FlushMode.MANUAL,而不是FlushMode.NEVER,正如我在阅读this SO answer后所说的那样.

上一篇:Oracle11g启动与关闭


下一篇:Oracle11g行列互换pivot和unpivot说明