JSF - Hibernate - Exception bei Update (org.hibernate.NonUniqueObjectException)

alan79

Mitglied
Hallo miteinander

Ich habe ein Problem in einer JSF Webapplikation. Ich nutze Hibernate für die Persistenz.

Beim Save eines Records erhalte ich folgende Exception:

HTML:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.antavis.groupware.model.News#4]

Hier die ganze Exception:
HTML:
javax.faces.FacesException: Error calling action method of component with id form:j_id19
	at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:69)
	at javax.faces.component.UICommand.broadcast(UICommand.java:121)
	at javax.faces.component.UIViewRoot._broadcastForPhase(UIViewRoot.java:292)
	at javax.faces.component.UIViewRoot.process(UIViewRoot.java:209)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:117)
	at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)
	at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103)
	at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:76)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:148)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:147)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at com.antavis.groupware.hibernate.HibernateFilter.doFilter(HibernateFilter.java:48)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:525)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
	at java.lang.Thread.run(Thread.java:619)
Caused by: javax.faces.el.EvaluationException: javax.el.ELException: /pages/news_mgmt_edit.xhtml @45,81 action="#{newsHandler.saveEditedRecord}": org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.antavis.groupware.model.News#4]
	at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:79)
	at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:54)
	... 27 more
Caused by: javax.el.ELException: /pages/news_mgmt_edit.xhtml @45,81 action="#{newsHandler.saveEditedRecord}": org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.antavis.groupware.model.News#4]
	at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:74)
	at javax.faces.component._MethodExpressionToMethodBinding.invoke(_MethodExpressionToMethodBinding.java:75)
	... 28 more
Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.antavis.groupware.model.News#4]
	at org.hibernate.engine.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:587)
	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 com.antavis.groupware.dao.Dao.saveOrUpdate(Dao.java:21)
	at com.antavis.groupware.handler.NewsHandler.saveEditedRecord(NewsHandler.java:108)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.el.parser.AstValue.invoke(AstValue.java:152)
	at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
	at com.sun.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:68)
	... 29 more

Das Problem scheint zu sein, dass das Objekt "News" in der Session 2x mal geladen wird. Mir ist hier die Einschränkung von Hibernate nicht ganz klar?

Es geht in diesem Fall darum, dass ich von einer Liste einen Datensatz auswähle und diesen in einer Detailansicht anzeige. Soweit funktioniert alles bestens. Doch beim Update kommt dann die Exception.

Ich probiers mal ohne Quellcode. Möglicherweise hab ich ja einfach ein bekanntes Verständnisproblem? :-)
Ansonsten häng ich gerne noch den Code an.

Vielen Dank für Eure Hifle!
Grüsse
Alan
 
Zuletzt bearbeitet:
Soooo.. Problem gelöst.

Ich habe anstatt der methode Session.saveOrUpdate(o) die Methode Session.merge() verwendet. Und alles funktioniert wunderbar.

merge() scheint die richtige Methode zu sein, wenn ein Datensatz bereits in der Datenbank existiert und bereits in der Session auf diesen Datensatz zugegriffen wird. Merge() führt dann die Änderungen mit dem bestehenden Datensatz zusammen.

saveOrUpdate() scheint besser geeignet für den Insert in die Tabelle.

Mit dem Risiko, dass das so auch nicht genau stimmt.....
 
Kleine Korrektur:

saveOrUpdate speichert ein Objekt was in der Hibernate Session liegt. Da kann es der Fall sein, dass das Objekt neu ist - dann flgt ein INSERT, oder das Objekt ist schon in der DB vorhanden (ID gibt es schon in der DB) - dann folgt ein Update.

Java:
Person person = session.get(Person.class, 25);
person.serFirstname("Fubar");
session.save(person);

Merge speicher eine Entität die NICHT mehr mit einer Hibernate Session verbunden ist.

Java:
Person person = session.get(Person.class, 25);
session.close();

// Person ist jetzt detached

Session session = sessionFactory.openSession();
session.merge(person);

// Person ist wieder mit der Session verbunden

Gruß
Ollie
 
Zurück