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

异常:

Exception caught by error page: a different object with the same identifier value was already associated with the session: [com.radicasys.intimate.mail.account.MailAccount#1]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.radicasys.intimate.mail.account.MailAccount#1]
org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session: [com.radicasys.intimate.mail.account.MailAccount#1]; nested exception is org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.radicasys.intimate.mail.account.MailAccount#1]
at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:679)
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.radicasys.util.hibernate.AbstractGenericHibernateDAO.makePersistent(AbstractGenericHibernateDAO.java:180)
at com.radicasys.intimate.mail.account.impl.HibernateMailAccountRepositoryImpl.save(HibernateMailAccountRepositoryImpl.java:135)
at com.radicasys.intimate.mail.account.MailAccountService.save(MailAccountService.java:194)
at com.radicasys.intimate.mail.account.MailAccountFacade.save(MailAccountFacade.java:93)
at com.radicasys.intimate.mail.account.MailAccountFacade$$FastClassByCGLIB$$f477ea27.invoke(<generated>)
at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:149)
at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:107)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
at com.radicasys.intimate.mail.account.MailAccountFacade$$EnhancerByCGLIB$$bc2cb688.save(<generated>)
at com.radicasys.intimate.mail.account.web.MailAccountUpdateAction.doPerform(MailAccountUpdateAction.java:93)
at com.radicasys.rmc.action.AbstractIntimateAction.perform(AbstractIntimateAction.java:82)
at org.apache.struts.action.ActionServlet.processActionPerform(ActionServlet.java:1787)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1586)
at com.radicasys.rmc.servlet.DataManagerControllerServlet.doGet(DataManagerControllerServlet.java:49)
at com.radicasys.rmc.servlet.DataManagerControllerServlet.doPost(DataManagerControllerServlet.java:58)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
at com.radicasys.obert.lang.StrutsIntegrateSpringSecurityFilter.invokeDelegate(StrutsIntegrateSpringSecurityFilter.java:151)
at com.radicasys.obert.lang.StrutsIntegrateSpringSecurityFilter.doFilter(StrutsIntegrateSpringSecurityFilter.java:104)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.radicasys.intimate.NoCacheFilter.doFilter(NoCacheFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.radicasys.intimate.LocaleFilter.doFilter(LocaleFilter.java:37)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.radicasys.rmc.security.RMCAuthenticationFilter.doFilter(RMCAuthenticationFilter.java:60)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.radicasys.intimate.util.web.HttpTrafficAuditFilter.doFilter(HttpTrafficAuditFilter.java:88)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at com.radicasys.intimate.bootstrap.StatusFilter.doFilter(StatusFilter.java:124)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:215)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:174)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:874)
at org.apache.coyote.http11.Http11BaseProtocol$Http11ConnectionHandler.processConnection(Http11BaseProtocol.java:665)
at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:528)
at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:81)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
at java.lang.Thread.run(Thread.java:595)
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.radicasys.intimate.mail.account.MailAccount#1]
at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:577)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:284)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:223)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:89)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:495)
at org.springframework.orm.hibernate3.HibernateTemplate$16.doInHibernate(HibernateTemplate.java:740)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
... 89 more

环境:spring3+hibernate3+struts2
在web.xml配置文件中增加了一个OpenSessionInView的Filter后出现该异常;
<filter>
<filter-name>OpenSessionInView</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>OpenSessionInView</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
解决办法:因为有struts1.x和struts2,而增加这个OpenSessionInView的filter的目的是测试struts2的,而原有的struts1是没有问题的,所以把<filter-mapping>改为:<filter-mapping>
<filter-name>OpenSessionInView</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
只对struts2的请求作用。
之所以出现这种情况的可能是以前旧的代码也有问题,这里就不说了,所以建议深入了解entity bean的持久化状态。
下面是一朋友那转的链接:
http://hi.baidu.com/zhouwei9960/blog/item/f4955eff50edff385d600850.html
------------------------------
1、仅仅Hibernate情况:参考http://www.cjsdn.com/post/view?bid=2&id=104169

net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: .........
这样的问题不知道大家有没有遇到?
SessionFactory sessionFactory= new Configuration().configure().buildSessionFactory();
Session session=sessionFactory.openSession();
User user1=new User("anray");
User user2=new User("anray");
user1.setName("anray1");//假设User是一个持久对象,有一个name属性
user2.setName("anray2");
session.update(user1);
session.update(user2);
这样就会出现上面的异常
看上去上面的代码有点傻,我们编程中不可能出现这样的情况。
但是有一种情况是经常用到的,就是写一个专门的类来管理sessionFactory和session,如下
/*
* Examination System version 0.1
* Data persist layer(Using Hibernate 2.1.2)
* Created on 2004-4-9 11:58:12
*/
package bts.hibernate;
/**
* @author Anray
*/
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
public class HibernateUse
{
   private static final SessionFactory sessionFactory;
   static {
     try {
       sessionFactory = new Configuration().configure().buildSessionFactory();
     } catch (HibernateException ex) {
       throw new RuntimeException("Exception building SessionFactory: " + ex.getMessage(), ex);
     }
   }
   public static final ThreadLocal threadLocal = new ThreadLocal();
 
   /**得到当前线程的session */
   public static final Session getSession() throws HibernateException {
     Session se = (Session) threadLocal.get();
     // Open a new Session, if this Thread has none yet
     if (se == null) {
       se = sessionFactory.openSession();
       threadLocal.set(se) ;
     }
     return se;
   }

   /**关闭当前线程的session */
   public static final void closeSession() throws HibernateException {
     Session s = (Session) threadLocal.get();
     threadLocal.set(null);
     if (s != null)
       s.close();
   }
 
   /**
   *保存一个对象到数据库中,使用完后要自己调用closeSession()
   */
   public static void create(Object object)
   throws HibernateException{
       Session session1 = getSession();
       Transaction transaction1 = session1.beginTransaction();
       try{
         session1.save(object);
         transaction1.commit();
       
       }catch(HibernateException ex){
         if(transaction1!=null)transaction1.rollback();
         closeSession();
         throw ex;
       }
   }
 
   /**
   *更新一个对象到数据库中,使用完后要自己调用closeSession()
   */
   public static void update(Object object)
   throws HibernateException{
     Session session1 = getSession();
     Transaction transaction1 = session1.beginTransaction();
     try{
       session1.update(object);
       transaction1.commit();
     
     }catch(HibernateException ex){
       if(transaction1!=null)transaction1.rollback();
       closeSession();
       throw ex;
     }
   }
}
如果在web编程时用这个类的方法来更新一个user对象,在调用了HibernateUse.update(user)后,没有接着调用HibernateUse.closeSession(),其实为了节省资源也不提倡每次操作都调用HibernateUse.closeSession()关闭session;如果对相同的user对象进行又一次的更新时,碰巧容器又分配了同一个thread进行处理,那么得到的也是同一个session,这样就出现了上面的提到了问题,session里的两个user的识别id一样,但内容不一样。

为了解决这个问题可以在,update前清空session(不是关闭,这样资源消耗比较少),修改后的公用类如下:(就是在update()方法里添加了session1.clear();)
/*
* Examination System version 0.1
* Data persist layer(Using Hibernate 2.1.2)
* Created on 2004-4-9 11:58:12
*/
package bts.hibernate;
/**
* @author Anray
*/
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
public class HibernateUse
{
   private static final SessionFactory sessionFactory;
   static {
     try {
       sessionFactory = new Configuration().configure().buildSessionFactory();
     } catch (HibernateException ex) {
       throw new RuntimeException("Exception building SessionFactory: " + ex.getMessage(), ex);
     }
   }
   public static final ThreadLocal threadLocal = new ThreadLocal();
 
   /**得到当前线程的session */
   public static final Session getSession() throws HibernateException {
     Session se = (Session) threadLocal.get();
     // Open a new Session, if this Thread has none yet
     if (se == null) {
       se = sessionFactory.openSession();
       threadLocal.set(se);
     }
     return se;
   }

   /**关闭当前线程的session */
   public static final void closeSession() throws HibernateException {
     Session s = (Session) threadLocal.get();
     threadLocal.set(null);
     if (s != null)
       s.close();
   }
 
   /**
   *保存一个对象到数据库中,使用完后要自己调用closeSession()
   */
   public static void create(Object object)
   throws HibernateException{
       Session session1 = getSession();
       Transaction transaction1 = session1.beginTransaction();
       try{
         session1.save(object);
         transaction1.commit();
       
       }catch(HibernateException ex){
         if(transaction1!=null)transaction1.rollback();
         closeSession();
         throw ex;
       }
   }
 
   /**
   *更新一个对象到数据库中,使用完后要自己调用closeSession()
   */
   public static void update(Object object)
   throws HibernateException{
     Session session1 = getSession();
     Transaction transaction1 = session1.beginTransaction();
     try{
      session1.clear();
       session1.update(object);
       transaction1.commit();
     }catch(HibernateException ex){
       if(transaction1!=null)transaction1.rollback();
       closeSession();
       throw ex;
     }
   }
}

2、Spring中的Hibernate事务代理遇到该情况

参考:http://hi.baidu.com/fgfd0/blog/item/fe258935b74cee1790ef39ba.html

注意:我这里解决的是:org.springframework.orm.hibernate3.HibernateSystemException: a different object with the same identifier value was already associated with the session:

网上大多数解决的是 :net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:

他们也是有区别的,因为我用的是Spring中的Hibernate事务代理,来自动管理事务的。

Hibernate session中对象重复问题的解决方法(结合Spring应的Hibernate事务管理)

在网上查到的都是单针对Hibernate session对象重复的问题,没有查到在结合Spring事务代理时的Hibernate session对象重复问题的解决方法。
我遇到的问题是,我使用了org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator
所以在:下面的配置中userInfoService等service的事务都是自动的,OK自动事务是我想要的,我需要在对多个对象或多个表操作时在Service层的事务管理,
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
            <list>
            <value>userInfoService</value>
            <value>adminInfoService</value>
            <value>pageService</value>
            <value>companyInfoService</value>
            </list>
</property>
        <property name="interceptorNames">
            <list>
                <value>transactionInterceptor</value>
            </list>
        </property>
    </bean>
但是有时会出现问题也就是:NonUniqueObjectException: a different object with the same identifier value was already associated with the session 异常。
并且经常会出现,这个异常很明显是因为Hibernate session出现了重复的对象,所以Hibernate不能同时更新两个拥有同一ID的对象。

具体详细问题我就不多说是怎么回事了可以看:http://www.cjsdn.com/post/view?bid=2&id=104169

下面是具体的解决方法:这个方法cAwardUpdateUserInfo,要求保存ui1和ui2并且查询他们的子如果他们有子对象责更新子。

public UserInfo cAwardUpdateUserInfo(UserInfo ui1, UserInfo ui2) {

   //最新修改的写法..... 也就是把所有的更新都放在最上面,下面的对象如果有改变Hibernate会自动更新他们,如果没改变Hibernate责不会管他。
   //这里为什么能解决问题我估计是因为手动调用update应该会自动清空session,所以这时session就不会有重复对象了,那下面的更新也就不用我们来管理了,并给Hibernate事务管理吧。
   this.saveUpUserInfo(ui1);
   this.saveUpUserInfo(ui2);


   //这里是出现问题的地方,也就是根据每个对象查出他们的子对象,如果有子对象就更新,
   //没子对象就不更新,所以假设查到子对象了,并更新了子对象。那它的父对象也能也更新。
   List ui1List = this.findUserInfoAllCAwardSub(ui1.getId()+"");
   List ui2List = this.findUserInfoAllCAwardSub(ui2.getId()+"");
 
    //开始 父子调换
    int subFather    = ui1.getUiAwardCjFather();
    int subFatherCj = ui1.getUiAwardCj();
    int subFatherAdd = ui1.getUiAwardAddSum();
  
    ui1.setUiAwardCjFather(ui2.getUiAwardCjFather());
    ui1.setUiAwardCj(ui2.getUiAwardCj());
    ui1.setUiAwardAddSum(ui2.getUiAwardAddSum());
  
    if(ui2List!=null && ui2List.size()>=1){
     System.out.println("ui2List:"+ui2List.size());
     for(int i=0; i<ui2List.size(); i++){
      UserInfo tempSubUi = (UserInfo)ui2List.get(i);
      tempSubUi.setUiAwardCjFather(ui1.getId());
     }
    }

  
  
    ui2.setUiAwardCjFather(subFather);
    ui2.setUiAwardCj(subFatherCj);
    ui2.setUiAwardAddSum(subFatherAdd);
    if(ui1List!=null && ui1List.size()>=1){
     System.out.println("ui1List:"+ui1List.size());
     for(int i=0; i<ui1List.size(); i++){
      UserInfo tempSubUi = (UserInfo)ui1List.get(i);
      tempSubUi.setUiAwardCjFather(ui2.getId());
     }
    }
    return ui1;

// 下面是最起初 错误的写法。
//    if((ui2List!=null && ui2List.size()>=1) && (ui1List!=null && ui1List.size()>=1)){
//     System.out.println("进入全不保存");
//     return ui1;
//    }
//  
//    if((ui1List!=null && ui1List.size()>=1) && (ui2List==null || ui2List.size()<=0)){
//     System.out.println("进入保存ui1");
//     //保存是否成功!
//     if(this.saveUpUserInfo(ui2)!=null){
//      return ui1;
//     }else{
//      return null;
//     }
//    }
//  
//    if((ui2List!=null && ui2List.size()>=1) && (ui1List==null || ui1List.size()<=0)){
//     System.out.println("进入保存ui2");
//     //保存是否成功!
//     if(this.saveUpUserInfo(ui1)!=null){
//      return ui1;
//     }else{
//      return null;
//     }
//
//    }
//  
//    System.out.println("进入全保存!");
//    //保存是否成功!
//    if(this.saveUpUserInfo(ui1)!=null && this.saveUpUserInfo(ui2)!=null){
//     return ui1;
//    }else{
//     return null;
//    }
}

你可能感兴趣的:(java,apache,Hibernate,Web,Security)