org.springframework.dao.InvalidDataAccessApiUsageException

org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.

问题原因分析:

为了解决session closed 错误而是用 openSessionInViewInterceptor 或者 openSessionInViewFilter 延迟加载的错误,但是在我们开启OpenSessionInViewFilter这个过滤器的时候FlushMode就已经被默认设置为了MANUAL,如果FlushMode是MANUAL或NEVEL,在操作过程中 hibernate会将事务设置为readonly,所以在增加、删除或修改操作过程中会出现如下错误 

解决方案:

1、在执行操作之前 插入getHibernateTemplate().setFlushMode(2) 或者 在方法执行之后 getHibernateTemplate().flush();  这也能够明白为什么会出现这个原因的。但是本人不推荐这种解决方式

2、使用 hibernateFilter 来解决:

<filter>  
         <filter-name>hibernateFilter</filter-name>  
         <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>  
        <init-param>  
             <param-name>flushMode</param-name>  
             <param-value>AUTO</param-value>  
         </init-param>
         <init-param>  
             <param-name>singleSession</param-name>  
             <param-value>true</param-value>  
         </init-param> 
    <init-param>
      <param-name>sessionFactoryBeanName</param-name>
      <param-value>sessionFactory</param-value>
    </init-param> 
     </filter>  
     <filter-mapping>  
         <filter-name>hibernateFilter</filter-name>  
         <url-pattern>/*</url-pattern>  
     </filter-mapping>


 

3、配置spring 事务,让spring 来管理hibernate session,有 aop, 有基于注解的;(本人推荐这种方式,因为项目都会有事务的操作)

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory">
  </bean>
  
<!-- 用注解来实现事务管理  将所有具有@Transactional 注解的文件自动配置为声明式事务支持-->
<!--tx:annotation-driven  transaction-manager="transactionManager" /-->
  
<!-- xml配置事务 -->
<tx:advice id="txAdviceHibernate" transaction-manager="transactionManager">
   <tx:attributes>
      <tx:method name="delete*" propagation="REQUIRED" />
  <tx:method name="update*" propagation="REQUIRED" />
  <tx:method name="save*" propagation="REQUIRED" />
  <tx:method name="*" read-only="true" />
    </tx:attributes>
</tx:advice>
<aop:config>
    <aop:pointcut id="serviceMethodsHibnerate" expression="execution(* com.longxia.springmvc.manager..*.*(..))"/>
    <aop:advisor advice-ref="txAdviceHibernate" pointcut-ref="serviceMethodsHibnerate" />
</aop:config>
<!-- xml配置事务-->

 

99.9%的人配置了事务之后,都会解决这个问题。但是还有0.1%的人还是悲催的人,哥就是那0.1%的异类。

第一,检查事务的传播级别对不对,

例如 你配的

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

但是你的方法名称是 delInfo(...)..;那么你对应的事务传播级别就是 <tx:method name="*" read-only="true" /> ;还是read-only;

所以你要给你的方法改为 deleteInfo(...);或者在事务的传播级别加上一个<tx:method name="del*" propagation="REQUIRED" />

 

第二、 一个十分蛋疼的问题;你的 manager 到底有没有以bean的形式注入到sping容器里面去,这也是导致我这次问题的原因

由于我使用的是springmvc模式,所以我就用这种方式一起注入 controller,manager,dao

 

<!-- 激活@Controller模式 -->  
  <mvc:annotation-driven />
  <!-- 对包中的所有类进行扫描,以完成Bean创建和自动依赖注入的功能 -->  
  <context:component-scan base-package="com.longxia.**.controller" />
  <context:component-scan base-package="com.longxia.**.manager" />
  <context:component-scan base-package="com.longxia.**.dao" />


虽然这样访问没有什么问题,在controller里面访问manager,在manager里面访问dao没有什么问题,

但是spring api 上说 :

This tag registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for Spring MVC to dispatch requests to Controllers. 
这个标签注册了Spring MVC分发请求到控制器所必须的DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter实例

个人认为这个只是单纯的对controller进行进行分发。并没有将service以bean的形式注入的spring容器中;

 

所以我将 manager和dao 放在 applicationDataSource.xml文件中以下面这种形式注入spring容器中 (<context : annotation-config />):

<context:annotation-config/>
  <context:component-scan base-package="com.longxia.**.manager" />
  <context:component-scan base-package="com.longxia.**.dao" />


如果觉得放在applicationDataSource.xml里面比较臃肿,可以独立一个applicationContext.xml 将代码复制进去

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
  <context:annotation-config/>
  <context:component-scan base-package="com.longxia.**.manager" />
  <context:component-scan base-package="com.longxia.**.dao" />
</beans>

 

然后再web.xml文件中配置applicationContext.xml,引入进去

<!-- 设定配置文件列表 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
       <!-- classpath*: 指定编译后的class目录  -->
      classpath*:config/application*.xml
    </param-value>
  </context-param>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值