问题:object references an unsaved transient instance - save the transient instance before flushing

1、报错日志:
在保存xx信息时,如果选了设备信息,后台不会报错,如果没选设备,就会报错,报错信息如下:

[2017-08-10 08:41:02] org.springframework.web.servlet.HandlerExecutionChain.triggerAfterCompletion(HandlerExecutionChain.java:173) 
<ERROR> HandlerInterceptor.afterCompletion threw exception

org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.hcepms.model.device.Device
    org.hibernate.engine.internal.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:279)
    at org.hibernate.type.EntityType.getIdentifier(EntityType.java:462)
    at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:281)
    at org.hibernate.type.ManyToOneType.isDirty(ManyToOneType.java:291)
    at org.hibernate.type.TypeHelper.findDirty(TypeHelper.java:296)
    at org.hibernate.persister.entity.AbstractEntityPersister.findDirty(AbstractEntityPersister.java:4144)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.dirtyCheck(DefaultFlushEntityEventListener.java:532)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.isUpdateNecessary(DefaultFlushEntityEventListener.java:215)
    at org.hibernate.event.internal.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:142)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:216)
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:85)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:38)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
    at com.hcepms.base.dao.BaseDaoImpl.save(BaseDaoImpl.java:38)
    at com.hcepms.base.service.BaseServiceImpl.save(BaseServiceImpl.java:38)
    at com.hcepms.base.interceptor.SecurityAndLogInterceptor.afterCompletion(SecurityAndLogInterceptor.java:150)
    at org.springframework.web.servlet.HandlerExecutionChain.triggerAfterCompletion(HandlerExecutionChain.java:170)
    at org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletion(DispatcherServlet.java:1297)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:976)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:895)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:967)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:869)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:843)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:151)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:528)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1099)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:670)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1520)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1476)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)
log4j:ERROR Failed to write [[2017-08-10 08:41:02] <http-nio-8080-exec-5> org.springframework.web.servlet.HandlerExecutionChain.triggerAfterCompletion(HandlerExecutionChain.java:173) 
<ERROR> HandlerInterceptor.afterCompletion threw exception

2、hibernate.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.hcepms.model.device.enter" default-access="field">
<class name="DeviceEnterDetail" table="T_DEVICE_ENTER_DETAIL">

  <many-to-one 
    name="device" 
    class="com.hcepms.model.device.base.Device" 
    fetch="select" 
    lazy="false"//不延迟加载 
    not-found="ignore">//指定引用的外键不存在时"忽略"
    <column name="DEVICE_"/>
  </many-to-one>

</class>
</hibernate-mapping>

3、controller中保存方法的代码:

/**
  * 
  * 保存XX信息
  * @author zhangsan 
  * @date 2016年8月2日
  * @param deviceEnterDetail XX信息
  * @param session
  * @return
  * @throws Exception
  */
@ResponseBody
@RequestMapping("/saveOrUpdateDetail")
public Json saveOrUpdateDetail(DeviceEnterDetail deviceEnterDetail,HttpSession session)throws Exception{
    Json json = new Json();
    String operat = (deviceEnterDetail.getId() == null ? "新增" : "编辑");
    try {
        SessionInfo sessionInfo = (SessionInfo)session.getAttribute("sessionInfo");
        UserDetail user = new UserDetail();
        user.setId(sessionInfo.getUserId());
        if(deviceEnterDetail.getId() == null){
            deviceEnterDetail.setCreateDate(new Date());
            deviceEnterDetail.setCreateUser(user);
            deviceEnterDetail.setStatus(1);
        }else{
            deviceEnterDetail.setUpdateDate(new Date());
            deviceEnterDetail.setUpdateUser(user);
        }
        dEDetailService.saveOrUpdate(deviceEnterDetail);
        json.setSuccess(true);
        json.setMsg(operat + "XX信息成功");
    } catch (Exception e) {
        log.error(operat + "XX信信息异常",e);
        json.setSuccess(true);
        json.setMsg(operat + "XX信细信息失败");
    }
    return json;
}

4、页面如下图
这里写图片描述 设备可选,可不选

<label for="useDev" class="col-xs-1 control-label" style="white-space: nowrap;">
<a class="require"><i class="icon-Asterisk"></i></a>
设备名称
</label>
<div class="col-xs-3">
     <div class="threepoint icon-DownMenu3" onclick="selectDevice()">
     </div>
     <input type="text" class="form-control sel" id="useDev" 
            placeholder="请选择设备" readonly>
     <input type="hidden" id="deviceId" name="device.id" />     
</div> 

5、解决方法
在controller中saveOrUpdateDetail方法中,在dEDetailService.saveOrUpdate(deviceEnterDetail);之前添加

if(deviceEnterDetail.getDevice() == null || deviceEnterDetail.getDevice().getId() == null){
      deviceEnterDetail.setDevice(null);
}

6、小结:
本人并没有使用级联。是保存单个对象,而这个有关联的对象,你的页面可以对这个关联对象不选值,就是给关联对象不选id值,这样的话springmvc会把你的关联对象重新new一个空对象赋给此对象,而这个空对象在数据库肯定是没有的,所以在保存该对象的时候就会报关联的没选值的对象为瞬时态的错误。解除决办法就是在hibernate保存单个对象之前,做一下判断关联的对象是否为空(注意关联的对象实体配置必须配制关联对象可为null),如果为空,则将关联对象set为null。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值