hibernate删除时报identifier of an instance of xx was altered from xx to xx
org.hibernate.HibernateException: identifier of an instance of com.gwideal.apps.xjzeg.entity.rota.NightshiftTemporary was altered from 47392c5531464d5d97a4955c8e85a92b to fe21e9b9d5754adfaa5ada7982428cc7,47392c5531464d5d97a4955c8e85a92b
新泾镇公务员平台街镇版接入系统
大致过程:
1、页面参数是id=fe21e9b9d5754adfaa5ada7982427,47392c5531464d5d55c8e85a92b
2、action 是 implements ModelDriven<T>, Preparable的
prepare方法中对实体entity 进行了hibernate的查询操作,使之和hibernate的session关联起来
@Override
protected void prepareModel() throws Exception {
....
entity =nightShiftTemporaryManager.getNightShift(temId);
....
}
3、在action中调用的方法中执行了删除操作
nightShiftTemporaryManager.deleteNightShift(removeId);其中removeId是对id的截取
然后报错,debug定位到 SimpleHibernateDao<T, PK extends Serializable>中的session.delete(entity);方法
4、action配置的是paramsPrepareParamsStack拦截栈,该栈中拦截器顺序如下
<interceptor-stack name="paramsPrepareParamsStack"> <interceptor-ref name="exception"/> <interceptor-ref name="alias"/> <interceptor-ref name="i18n"/> <interceptor-ref name="checkbox"/> <interceptor-ref name="multiselect"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="servletConfig"/> <interceptor-ref name="prepare"/> <interceptor-ref name="chain"/> <interceptor-ref name="modelDriven"/> <interceptor-ref name="fileUpload"/> <interceptor-ref name="staticParams"/> <interceptor-ref name="actionMappingParams"/> <interceptor-ref name="params"> <param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param> </interceptor-ref> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> <interceptor-ref name="workflow"> <param name="excludeMethods">input,back,cancel,browse</param> </interceptor-ref> </interceptor-stack>
其中关键拦截器:
params : Sets the request parameters onto the Action
prepare :If the Action implements Preparable, calls its prepare method
modelDriven:If the Action implements ModelDriven, pushes the getModel Result onto the Value Stack
actionMappingParams:这是params 参数拦截器的子类
解释大概原因:
该action是实现ModelDriven的,则在modelDrivenInterceptor 拦截器中, 把entity 放入了valueStatck 中的栈顶,在接下来的actionMappingParams拦截器又把id参数赋值给了valueStatck 中root对象的id属性,这里即entity 中的id属性。所以在执行action中方法的时候,entity 的id值被赋予了参数id的值fe21e9b9d5754adfaa5ada7982428cc7,47392c5531464d5d97a4955c8e85a92b,所以在调用session.delete(entity)中。hibernate检测到了持久对象entity 的id被改变,抛出了异常;
由关键拦截器顺序5个步骤解释具体原因:
step1、params : Sets the request parameters onto the Action
在该拦截器中,stuts2对action中的id属性赋值fe21e9b9d5754adfaa5ada7982428cc7,47392c5531464d5d97a4955c8e85a92b
step2、prepare :If the Action implements Preparable, calls its prepare method
在该拦截器中,拦截器调用了action中prepare 方法,而该方法把实体entity 和hibenate的session产生了关联,使起变成了hibernate中的持久化对象
step3、modelDriven:If the Action implements ModelDriven, pushes the getModel Result onto the Value Stack
在该拦截器中,把action中的实体entity 放入Value Stack中,使其在接下来的参数拦截中接受参数
step4、actionMappingParams:这是params 参数拦截器的子类
把请求参数id,赋给entity 的id
step5、所以在接下来的执行action方法中,调用session.delete(entity)中。hibernate检测到了持久对象entity 的id被改变,抛出了异常