(FlushMode.NEVER/MANUAL): Turn your Session into

本文探讨了在Spring框架中遇到的InvalidDataAccessApiUsageException异常,详细解析了OpenSessionInViewFilter如何影响session的flush模式,并提供了实现写操作权限的具体解决方案。
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.


执行这个方法得时候 出错了getHibernateTemplate().save(agentLog);


错误原因:
OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。然后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,在请求过后再接除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。在这个过程中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限,如果没有transaction,并且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限,没受保护的则没有。
`org.springframework.dao.InvalidDataAccessApiUsageException` 异常通常表示在使用数据访问 API 时出现了不符合规范的操作。以下是相关异常信息、原因及解决方案: ### 异常信息及原因 - 异常信息:`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.` 原因是未加事务处理。在只读模式下进行写操作,而当前会话的刷新模式为 `MANUAL`,不允许进行写操作 [^1]。 - 示例代码中的异常情况:在 `requestData` 方法中调用 `uaasUserDAO.save(user)` 时出错,同样是因为处于只读模式(`FlushMode.NEVER/MANUAL`)下进行写操作 [^2]。 - 另一种异常信息:`org.hibernate.TransientObjectException: The given object has a null identifier:com.you.model.UserInfo`,这也可能导致 `InvalidDataAccessApiUsageException` 异常,原因是给定的对象标识符为空 [^3]。 ### 解决方案 对于因只读模式下进行写操作导致的异常,解决方案是将会话的刷新模式改为 `FlushMode.COMMIT/AUTO` 或者移除事务定义中的 `readOnly` 标记 [^1][^2]。 ```java // 示例代码:假设使用 Spring 框架的事务管理 import org.springframework.transaction.annotation.Transactional; // 移除 readOnly 标记 @Transactional public void requestData(){ UaasUser user = new UaasUser(); user.setLoginName("test"); user.setPassword("111111"); user.setStatus(1); user.setName("test"); user.setSexCode("1"); uaasUserDAO.save(user); } ``` 对于 `org.hibernate.TransientObjectException` 导致的异常,需要确保对象的标识符不为空。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值