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

代码 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();
    }
}

参考:
https://docs.spring.io/spring-framework/docs/3.0.x/javadoc-api/org/springframework/orm/hibernate3/support/OpenSessionInViewFilter.html

你可能感兴趣的:(日常,框架,数据库,hibernate,java,spring)