Hibernate - Write operations are not allowed in read-only mode 解决方案

138 阅读1分钟

代码 demo

@Service
public class LogDAOImpl extends AbstracRepositoryImpl implements ILogDAO {

    @Override
    public String saveLog(LogAggregateRoot log){
        MsLog msLog = new MsLog();
        msLog.setUserId(log.getUserId());
        msLog.setOptFlowType(Integer.valueOf(log.getOptFlowType()));
        msLog.setRoleType(Byte.valueOf(log.getRoleType()));
        msLog.setServiceOrderId(Long.valueOf(log.getBizNo()));
        msLog.setRemark(log.getDetail());
        msLog.setCreatedTime(log.getOptTime());
        msLog.setStatus(log.getStatus());
        return super.save(msLog).getLogId().toString();
    }
}

报错报文

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.

问题分析

That error message is typically seen when using the Spring OpenSessionInViewFilter and trying to do persistence operations outside of a Spring-managed transaction. The filter sets the session to FlushMode.NEVER/MANUAL . 当使用 Spring OpenSessionInViewFilter并尝试在 Spring 管理的事务之外执行持久性操作时,通常会看到该错误消息。过滤器将会话设置为 FlushMode.NEVER/MANUAL。

解决方案

1、添加事务(@Transactional)

当 Spring 事务机制开始一个事务时,它将刷新模式更改为“COMMIT”。事务完成后,它会根据需要将其设置回 NEVER/MANUAL。

@Service
public class LogDAOImpl extends AbstracRepositoryImpl implements ILogDAO {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveLog(LogAggregateRoot log){
        MsLog msLog = new MsLog();
        msLog.setUserId(log.getUserId());
        msLog.setOptFlowType(Integer.valueOf(log.getOptFlowType()));
        msLog.setRoleType(Byte.valueOf(log.getRoleType()));
        msLog.setServiceOrderId(Long.valueOf(log.getBizNo()));
        msLog.setRemark(log.getDetail());
        msLog.setCreatedTime(log.getOptTime());
        msLog.setStatus(log.getStatus());
        return super.save(msLog).getLogId().toString();
    }
}

2、关闭检查Hibernate会话是否处于只读模式(setCheckWriteOperations(false))

设置写入操作(保存/更新/删除)时是否检查Hibernate会话是否处于只读模式。

默认值为“true”,表示在只读事务中尝试写入操作时的快速失败行为。关闭此选项以允许在刷新模式为手动的会话上保存/更新/删除。

@Service
public class LogDAOImpl extends AbstracRepositoryImpl implements ILogDAO {

    @Override
    public String saveLog(LogAggregateRoot log){
        MsLog msLog = new MsLog();
        msLog.setUserId(log.getUserId());
        msLog.setOptFlowType(Integer.valueOf(log.getOptFlowType()));
        msLog.setRoleType(Byte.valueOf(log.getRoleType()));
        msLog.setServiceOrderId(Long.valueOf(log.getBizNo()));
        msLog.setRemark(log.getDetail());
        msLog.setCreatedTime(log.getOptTime());
        msLog.setStatus(log.getStatus());
        super.getHibernateTemplate().setCheckWriteOperations(false);
        return super.save(msLog).getLogId().toString();
    }
}

参考: docs.spring.io/spring-fram…