Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition...
时间: 2023-11-22 12:52:57 AIGC 浏览: 164
这个错误通常出现在使用Spring框架进行数据库操作时,意思是当前事务为只读事务,不允许进行写操作。解决方法有两个:
1. 将当前事务的FlushMode设置为COMMIT或AUTO,这样就可以进行写操作了。可以在代码中使用以下语句设置FlushMode:
```
session.setFlushMode(FlushMode.COMMIT);
```
2. 将当前事务的readOnly属性设置为false,这样就可以进行写操作了。可以在Spring的事务定义中将readOnly属性设置为false,例如:
```
<tx:method name="update*" propagation="REQUIRED" readOnly="false"/>
```
相关问题
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 at org.springframework.orm.hibernate.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:975) at org.springframework.orm.hibernate.HibernateTemplate$9.doInHibernate(HibernateTemplate.java:554) at org.springframework.orm.hibernate.HibernateTemplate.execute(HibernateTemplate.java:363) at org.springframework.orm.hibernate.HibernateTemplate.save(HibernateTemplate.java:552) at com.smec.apps.crm.service.impl.PaySubmitServiceImpl.getAttachment(PaySubmitServiceImpl.java:391) at sun.reflect.GeneratedMethodAccessor39.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:335)什么错误
这个错误是典型的 **Spring + Hibernate** 应用中出现的 **只读模式下执行写操作** 的异常:
---
### ❗错误信息解析:
```
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
```
**翻译解释:**
> 不允许在只读模式(FlushMode.NEVER)下执行写操作。请将 Session 设置为 FlushMode.AUTO,或者从事务定义中移除 `readOnly` 标记。
---
### 📌 错误原因
这个错误通常发生在你使用了带有 `readOnly = true` 的事务配置,但在事务中执行了诸如 `save()`, `update()`, `delete()` 等 **写操作**。
#### 示例场景:
```java
@Transactional(readOnly = true)
public void saveData(Entity entity) {
hibernateTemplate.save(entity); // ❌ 错误:在只读事务中执行写操作
}
```
或者:
```xml
<tx:method name="save*" read-only="true"/>
```
你在事务配置中声明了 `read-only="true"`,但实际调用了写数据库的操作。
---
### ✅ 解决方案
#### 方法一:移除 `readOnly` 标记
如果你的事务需要进行写操作,请确保不要设置 `readOnly = true`。
```java
@Transactional
public void saveData(Entity entity) {
hibernateTemplate.save(entity); // ✅ 正确:非只读事务中执行写操作
}
```
#### 方法二:在 XML 配置中调整事务属性
如果你是通过 XML 配置事务:
```xml
<tx:method name="save*" read-only="false"/>
```
---
### 🔍 补充说明
- `FlushMode.NEVER` 表示 Hibernate 不会自动刷新 session 缓存,通常用于只读查询。
- 如果你在这种模式下执行 `save()` 等操作,Hibernate 会抛出上述异常,防止脏数据写入。
---
### 🧪 示例代码修复
#### 原错误代码(错误):
```java
@Transactional(readOnly = true)
public void getAttachment(Payment payment) {
hibernateTemplate.save(payment); // 错误:在只读事务中执行写操作
}
```
#### 修复后代码(正确):
```java
@Transactional
public void getAttachment(Payment payment) {
hibernateTemplate.save(payment); // 正确:写操作在可写事务中执行
}
```
---
###
SpringMVC4+hibernate遇到 readOnly问题FlushMode.MANUAL
在SpringMVC4 + hibernate中,可以使用@Transactional注解来管理事务。@Transactional默认会将事务设置为读写模式,也就是说,如果你在一个只读的方法上使用@Transactional注解,那么这个方法也会被执行成写模式,这可能会引起一些不必要的性能问题。
为了避免这种情况,可以使用readOnly属性来将事务设置为只读模式。例如:
```java
@Transactional(readOnly = true)
public void myReadOnlyMethod() {
// 只读操作
}
```
另外,如果你需要在只读模式下执行查询操作,但是又想让hibernate缓存这些查询结果,可以使用FlushMode.MANUAL来禁止hibernate自动刷新缓存。例如:
```java
Session session = sessionFactory.getCurrentSession();
session.setFlushMode(FlushMode.MANUAL);
// 执行查询操作
```
这样做可以避免hibernate在查询结束后自动刷新缓存,从而提高性能。但需要注意的是,由于缓存不会自动刷新,如果你在查询之后修改了数据,那么这些修改可能不会被缓存所感知,因此需要手动刷新缓存或者重新查询。
阅读全文
相关推荐


















