org.springframework.dao.InvalidDataAccessApiUsageException: Write operations
在配置 springmvc+hibernate+MySQL 的时候,出现如下问题:
异常信息:
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.org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1175)org.springframework.orm.hibernate3.HibernateTemplate$25.doInHibernate(HibernateTemplate.java:839)org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:837)org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:833)com.longxia.springmvc.dao.HibernateBaseDao.deleteObject(HibernateBaseDao.java:94)com.longxia.springmvc.manager.usermanager.UserManagerImpl.deleteUser(UserManagerImpl.java:88)com.longxia.springmvc.controller.UserController.deleteAllUser(UserController.java:52)sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)java.lang.reflect.Method.invoke(Unknown Source)org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:574)javax.servlet.http.HttpServlet.service(HttpServlet.java:617)javax.servlet.http.HttpServlet.service(HttpServlet.java:717)org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
问题原因分析:
为了解决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>
这样就可以解决问题了。起码我是这样解决的,哎,困扰了3天。疯掉了。还好今天突发想法。所以分享我的经验,希望后来人早点解决问题。
我的项目结构(只是自己练习的小项目,嘿嘿)
题外话:
关于 mvc:annotation-driven 和 context:annotation-config 这两个区别,我在网上找了一点资料,顺便贴出来供大家分享,(文章出处http://mushiqianmeng.blog.51cto.com/3970029/723880)
在基于主机方式配置Spring的配置文件中,你可能会见到<context:annotation-config/>这样一条配置,他的作用是式地向 Spring 容器注册
AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、
PersistenceAnnotationBeanPostProcessor 以及 RequiredAnnotationBeanPostProcessor 这 4 个BeanPostProcessor。
注册这4个BeanPostProcessor的作用,就是为了你的系统能够识别相应的注解。
例如:
如果你想使用@Autowired注解,那么就必须事先在 Spring 容器中声明 AutowiredAnnotationBeanPostProcessor Bean。传统声明方式如下:
- <bean class="org.springframework.beans.factory.annotation. AutowiredAnnotationBeanPostProcessor "/>
如果想使用@ Resource 、@ PostConstruct、@ PreDestroy等注解就必须声明CommonAnnotationBeanPostProcessor
如果想使用@PersistenceContext注解,就必须声明PersistenceAnnotationBeanPostProcessor的Bean。
如果想使用 @Required的注解,就必须声明RequiredAnnotationBeanPostProcessor的Bean。同样,传统的声明方式如下:
- <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
一般来说,这些注解我们还是比较常用,尤其是Antowired的注解,在自动注入的时候更是经常使用,所以如果总是需要按照传统的方式一条一条配置显得有些繁琐和没有必要,于是spring给我们提供<context:annotation-config/>的简化配置方式,自动帮你完成声明。
不过,呵呵,我们使用注解一般都会配置扫描包路径选项
- <context:component-scan base-package=”XX.XX”/>
该配置项其实也包含了自动注入上述processor的功能,因此当使用 <context:component-scan/> 后,就可以将 <context:annotation-config/> 移除了。
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations相关推荐
- org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in r...
2019独角兽企业重金招聘Python工程师标准>>> Struts Problem Report Struts has detected an unhandled exceptio ...
- org.springframework.dao.InvalidDataAccessApiUsageException
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read ...
- org.springframework.dao.InvalidDataAccessApiUsageException: ERR wrong number of arguments for ‘srem‘
1.报错信息 org.springframework.dao.InvalidDataAccessApiUsageException: ERR wrong number of arguments for ...
- org.springframework.dao.InvalidDataAccessApiUsageException:The given object has a null identifi的解决方案
异常信息: org.springframework.dao.InvalidDataAccessApiUsageException: The given object has a null identi ...
- org.springframework.dao.InvalidDataAccessApiUsageException: Cannot locate field code on class .....
报错日志 org.springframework.dao.InvalidDataAccessApiUsageException: Cannot locate field code on class c ...
- 找不到org.springframework.dao.support.DaoSupport的类文件
无法访问org.springframework.dao.support.DaoSupport 找不到org.springframework.dao.support.DaoSupport的类文件 或 ...
- java.lang.NoClassDefFoundError: org/springframework/dao/support/PersistenceE解决方法
笔者是使用spring4.0时,报的错误: 原因是没有引入spring-tx-4.0.0.RELEASE.jar包,將spring-tx-4.0.0.RELEASE.jar添加到build path中 ...
- org.springframework.dao.IncorrectResultSizeDataAccessException: query did not return a unique result
客户现场反馈考勤计算失败: 日志报错显示: org.springframework.dao.IncorrectResultSizeDataAccessException: query did not ...
- 达梦数据库 ,无效的列名, org.springframework.dao.DataIntegrityViolationException: Hibernate-related JDBC operat
在达梦数据库中创建了一张表,然后向表中插入字段,报错如下 org.springframework.dao.DataIntegrityViolationException: Hibernate-rela ...
最新文章
- 人类吃屎用屎指南:用做肥料不如制咖啡、当展品、做炸弹
- C++ goto的用法
- 找出最大和第二大的数PHP,2020-09-01 十大经典排序算法总结php为例
- 线上BUG定位神器(阿尔萨斯)-Arthas2019-0801
- 无法打开登录所请求的数据库DbName 。登录失败。 用户 'IIS APPPOOL\DefaultAppPool' 登录失败。 的解决方案...
- iOS有哪些数据类型/基本数据类型?
- 论文浅尝 | 基于未知谓词与实体类型知识图谱的 Zero-Shot 问题生成
- bzoj 3406: [Usaco2009 Oct]Invasion of the Milkweed 乳草的入侵
- PHP可以读取什么配置文件,使用php读取配置文件
- QTP(Quick Test Professional)安装详细教程
- aforge 相机标定_在C#和WPF中使用Aforge.NET获取网络摄像头流
- html 日期区间选择器,element日期范围选择器
- 零基础快速入行入职软件测试工程师
- 基于WIN32 API界面编程实现的贪吃蛇游戏
- foxmail发邮件时总提示接收密码错误是怎么回事
- Android截取人物头像,Android 图片截取人物头像(仿逗拍)
- Shiro(一)之shiro简介与工作原理
- selenium新浪邮箱注册句柄切换实战
- (关于边界填充)cv2.copyMakeBorder()怎么用?及效果展示(opencv)(python)
- 软件自动化测试可行性分析,基于 AI 的软件自动化测试思考与实践—kylinTOP 测试与监控平台...
热门文章
- 对asn.net三层架构的初步认识
- Linux SPI总线和设备驱动架构之二:SPI通用接口层
- seata xid是什么_Seata 分布式事务框架
- STL源代码分析(ch2 内存分配)uninitialized_fill_n
- Boost Asio总结(4) io_service
- (chap1 网络基础知识)网络的构成要素:(7)网关
- C++ Primer 5th笔记(10)chapter10 泛型算法 :迭代器
- armv8-M(cortex-m) Trustzone总结和介绍
- 两种方法设置html表格的宽高
- c# SortedList的妙用 (GroupBy)