【CSDN迁移】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.
通过报错信息理解,可以定位到错误原因 是和Spring事务有关,当前方法的权限是read-only。 我执行的方法是
excelExportDao.save(oobfs.get(1));
所以需要找一下事务配置文件里面对save*的配置,事务的配置代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
<!-- 扫描cn.jkstudio.excelexport.service包下所有标注@Service的服务组件 -->
<context:component-scan base-package="cn.jkstudio.excelexport.service"/>
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- 配置事务通知属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- 定义事务传播属性 -->
<tx:attributes>
<!-- 增 -->
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="new*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<!-- 删 -->
<tx:method name="remove*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<!-- 改 -->
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="set*" propagation="REQUIRED" />
<tx:method name="change*" propagation="REQUIRED" />
<!-- 查 -->
<tx:method name="get*" propagation="REQUIRED" read-only="true" />
<tx:method name="find*" propagation="REQUIRED" read-only="true" />
<tx:method name="load*" propagation="REQUIRED" read-only="true" />
<tx:method name="*" propagation="REQUIRED" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* cn.jkstudio.*.service.*.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
</beans>
可以看到的是,对save方法已经进行了事务配置,网上搜索了一下这个问题,大多数解决方法都是差不多的,大意就是
1、在执行操作之前 插入getHibernateTemplate().setFlushMode(2) 或者 在方法执行之后 getHibernateTemplate().flush(); 这也能够明白为什么会出现这个原因的。但是本人不推荐这种解决方式
2、使用 hibernateFilter 来解决:......
事实上,我的项目是从我之前的一个项目里面copy过来修改的,之前并没有遇到事务问题,按照该网上的方法修改之后并没有解决问题。
当我仔细检查后发现,我遇到这个报错的原因很简单,在配置事务切面的地方对包路径写的有问题:
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* cn.jkstudio.*.service.*.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
检查expression="execution(* cn.jkstudio.*.service.*.*.*(..))"
第一个 * 表示方法返回值类型可以为任意类型
第二个 * 表示cn.jkstudio包下面的任意包
第三个 * 表示service包下面的任意包
第四个 * 表示service.任意包 下面的任意一个类
第五个 * 表示service.任意包.任意类下面的任意一个方法
后面小括号里面的两个 .. 表示该方法可以有0个或多个参数
因为我这个项目的包路径和之前的项目包路径有所区别,在service包下面直接是类代码,而没有继续分模块包。 这就导致在该项目中实际上并没有对service层的代码进行注入,所以,save方法才会报事务相关的错误。
问题找到了,也就好解决了,修改一下expression就好了。 希望给同样遇到这种错误的人提供解决问题的思路,有时候不一定是事务配置没写,而是粗心写错了切面注入的位置。:P
<!-- 配置事务切面 -->
<aop:config>
<aop:pointcut id="serviceOperation"
expression="execution(* cn.jkstudio.*.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>
原创文章,作者:宁白久,如若转载,请注明出处:《【CSDN迁移】org.springframework.dao.InvalidDataAccessApiUsageException问题解决与分析》https://www.liangrenyixin.cn/article/p/8345164871697409
全部评论: 条