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。