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被改变,抛出了异常

猜你喜欢

转载自zhouchaofei2010.iteye.com/blog/1797088
xx
今日推荐