org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER)

在执行service中一个方法bumenAuth()时出现错误:

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

查看srping中事务管理配置:

<bean id="txProxyTemplate" abstract="true"
  class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
  <property name="transactionManager">
   <ref bean="transactionManager" />
  </property>
  <property name="transactionAttributes">
   <props>
    <prop key="find*">PROPAGATION_REQUIRED</prop>
    <prop key="save*">PROPAGATION_REQUIRED</prop>
    <prop key="remove*">PROPAGATION_REQUIRED</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="create*">PROPAGATION_REQUIRED</prop>
    <prop key="add*">PROPAGATION_REQUIRED</prop>
    <prop key="del*">PROPAGATION_REQUIRED</prop>
    <prop key="clear*">PROPAGATION_REQUIRED</prop>
    <prop key="build*">PROPAGATION_REQUIRED</prop>
   </props>
  </property>
 </bean>

看了之后才知道,原来的事务策略的<prop key="*">PROPAGATION_REQUIRED</prop>被删除后,bumenAuth()方法后忘了修改,所以导致报上述的错误

修改方法一:

     将此方法修改为update或者build,add....等上述策略名称开头的方法:如:updateBumenAuth()

修改方法二:

    增加<prop key="*">PROPAGATION_REQUIRED</prop>即可

修改方法三:

 将web.xml下的

   <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>true</param-value>
  </init-param>
 </filter>

中的singleSession值修改为false,即不限制整个过程用同一个session,但缺点是Hibernate Session的Instance可能会大增,使用的JDBC Connection量也会大增,如果Connection Pool的maxPoolSize设得太小,很容易就出问题

参考:关于OpenSessionView(http://liuwei1578.blog.163.com/blog/static/4958036420092104215514/)

Spring事务配置TransactionProxyFactoryBean(http://liuwei1578.blog.163.com/blog/static/49580364200921041136625/)

 

 

——————————————————————————————————————

参考另一篇文章:

 

http://zhupan.javaeye.com/blog/33507   注重讲的是spring!!!!!!!!!!!!!!!!!!!!!!!

### 解决 Spring Data 访问只读副本时出现的 `InvalidDataAccessApiUsageException` 异常 当遇到 `org.springframework.dao.InvalidDataAccessApiUsageException: Error attempting to get column 'repertory_time' from result set.` 这样的错误时,通常意味着应用程序尝试从数据库的结果集中获取某一列的数据失败了。这可能是由于多种原因引起的,特别是在访问只读副本的情况下。 #### 可能的原因分析 1. **驱动程序不支持某些操作** 如果使用的 JDBC 驱动程序版本较旧或存在兼容性问题,则可能导致无法执行特定的操作,比如通过 `getObject()` 方法获取数据[^2]。 2. **查询语句中的字段名拼写错误** 查询 SQL 中指定的字段名称可能与实际表结构不符,导致找不到对应的列。应仔细核对字段命名是否一致[^1]。 3. **只读副本配置不当** 对于 MySQL 或其他关系型数据库而言,在设置主从复制架构下连接至 slave 节点(即只读实例),如果未正确处理事务隔离级别或是权限控制方面的问题也会引发此类异常。 #### 实施解决方案 为了有效解决问题并确保应用能够稳定运行: - **更新依赖库** 检查项目所引入的相关依赖项如 spring-data-jpa 和 jdbc driver 是否为最新稳定版;必要时升级这些组件来修复潜在 bug 并获得更好的性能表现。 - **优化实体映射定义** 使用 JPA 注解精确描述实体类属性同数据库表格之间的对应关系,特别是对于日期时间类型的字段要特别注意其格式转换逻辑。可以考虑采用自定义 Converter 来实现更灵活的时间解析方式。 - **调整查询方法签名** 当调用带有修改功能的方法时需加上 `@Modifying(clearAutomatically=true)` 注释,并声明返回值类型为 int 表明受影响记录数。而对于纯检索性质的服务则保持默认即可。 ```java import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; public interface ProductRepository extends JpaRepository<Product, Long> { @Query(value = "SELECT p FROM Product p WHERE p.id = :id", nativeQuery = false) Optional<Product> findById(Long id); @Modifying(clearAutomatically = true) @Query(value = "UPDATE Product SET name=:name WHERE id=:id", nativeQuery = false) void updateProductName(@Param("id") Long id, @Param("name") String name); } ``` - **合理规划读写分离策略** 明确区分业务场景下的读取请求和写入指令路径,针对高并发读多写的系统建议部署专门负责响应 SELECT 请求的 Slave Server 组成集群分担压力的同时保障 Master 的稳定性。同时要注意同步延迟带来的影响以及如何应对临时性的单点故障切换机制等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值