a different object with the same identifier value was already associated with the session

异常描述:在执行以下方法出现此异常:

注:类Role 与类Function 呈多对多关联,这里是添加一个role并添加三个function

@Test//fail
    public void add(){
        Role r = new Role();
        r.setRname("Java项目经理");
        
        
        Function f = functionService.findById(98);
        Function f1 = functionService.findById(99);
        Function f2 = functionService.findById(100);
        
        r.getFunctions().add(f);
        r.getFunctions().add(f1);
        r.getFunctions().add(f2);
        
        roleService.saveOrUpdate(r);
    }

具体异常信息:

org.springframework.dao.DuplicateKeyException: a different object with the same identifier value was already associated with the session: [com.chen.vo.Function#99]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.chen.vo.Function#99]
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:662)
    at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:411)
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
    at org.springframework.orm.hibernate3.HibernateTemplate.saveOrUpdate(HibernateTemplate.java:737)
    at com.chen.dao.RoleDaoImpl.saveOrUpdate(RoleDaoImpl.java:52)
    at com.chen.service.RoleService.saveOrUpdate(RoleService.java:38)
    at com.chen.service.RoleService$$FastClassByCGLIB$$be28c933.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:713)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:646)
    at com.chen.service.RoleService$$EnhancerByCGLIB$$3b898394.saveOrUpdate(<generated>)
    at com.chen.test.RoleTest.add(RoleTest.java:37)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:232)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:175)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.chen.vo.Function#99]
    at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:613)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:307)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:246)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:112)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
    at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:241)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:292)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:240)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:320)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:266)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:243)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:154)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:121)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.cascadeOnUpdate(DefaultSaveOrUpdateEventListener.java:380)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:352)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:246)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:112)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
    at org.hibernate.engine.CascadingAction$5.cascade(CascadingAction.java:241)
    at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:292)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:240)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
    at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:320)
    at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:266)
    at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:243)
    at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:193)
    at org.hibernate.engine.Cascade.cascade(Cascade.java:154)
    at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:479)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:357)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:204)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:117)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:535)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:527)
    at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:523)
    at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:740)
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
    ... 45 more

分析:根据异常的字面信息及网上提示总结原因是在com.chen.vo.Function中定义了相同的Object,类Function代码如下:

public class Function implements Serializable{
    private int fid;
    private String fname;
    private String namespace;
    private String actioname;
    private String method;
//    private int parentid;
    
    private Function parent;
    private Set<Function> childs = new HashSet<Function>();
    
    private Set<Role> roles = new HashSet<Role>();
    
    //...
    
}

类Role的代码:

public class Role {
    private int rid;
    private String rname;//角色名
    
    private Set<Empl> empls = new HashSet<Empl>();
    private Set<Function> functions = new HashSet<Function>();

    //..
}

从以上代码可看出在类Function与类Role中均有Set<Function>的定义,因此在添加role级联添加function时出现此异常。

解决方法:

采用session.merge (object o)方法,这里是hibernateTemplate.merge(object o);

代码:

@Test//success
    public void add2(){
        Role r = new Role();
        r.setRname("Java项目经理");
        
        
        Function f = functionService.findById(98);
        Function f1 = functionService.findById(99);
        Function f2 = functionService.findById(100);
        
        r.getFunctions().add(f);
        r.getFunctions().add(f1);
        r.getFunctions().add(f2);
        
        hibernateTemplate.merge(r);
        
    }

具体原理现在也不多去分析了,详情参见:

http://lcy0202.iteye.com/blog/1453868

posted @ 2015-10-10 07:23  Tom1997  阅读(1257)  评论(0编辑  收藏  举报