2012-06-04 5 views
9

Nach einem Upgrade von Hibernate 3 auf 4 arbeiten wir ein paar Knicke, die auf dem Weg auftauchen. Eine, die uns besonders ratlos macht, ist eine UnsupportedOperationException, bei der ein existierendes Objekt aus der Datenbank gezogen, optimiert und zusammengeführt wird.Nicht unterstützteOperationException beim Zusammenführen eines vorhandenen Hibernate-Modellobjekts?

Das Problem ist, dass Hibernate zu einem AbstractList Hinzufügen eines Objekts zu sein scheint nur

Dies zu einem bestimmten Objekttyp zu geschehen scheint, wenn in unserer DAO gespeichert, aber so gut wie wir sagen können:

  1. Wir verwenden keine sublist() - oder asList() - Methoden, die eine unveränderbare Instanz erstellen würden.
  2. Untersuchen Sie das Objekt, das gespeichert wird (das ist enorm und hat viele Kinder) Ich glaube nicht denken, dass eines seiner Kinder Elemente AbstractList Typen sind.

Hier sind die Code-Schnipsel um den Stapel Punkte:

HibernateDao.save():

@Transactional 
public void save(T item) { 
    try { 
     getSessionFactory().getCurrentSession().merge(item); 
    } catch (Exception ex) { 
     LOGGER.debug("Unable to merge", ex); 
     LOGGER.warn("Unable to merge item, saving instead. (Of type " + item.getClass() + ")"); 
     getSessionFactory().getCurrentSession().saveOrUpdate(item); 
    } 
} 

Unsere Benutzer Artikel, die eine Nummer gespeichert wird von Kinderartikel wie folgt definiert:

@OneToMany(cascade = CascadeType.ALL) 
@LazyCollection(LazyCollectionOption.FALSE) 
private Map<String, Project> associatedProjects = new HashMap<String, Project>(); 

T er Project Klasse hat andere ähnlich annotierte Kinder, aber alles hat CascadeType.ALL und LazyCollectionOption.FALSE definiert. Hier

ist die (ziemlich groß) Stack-Trace:

Beachten Sie, dass unser Code beginnt mit com.company.application

06/04 18:15:45 DEBUG [Thread-19258] hibernate.HibernateDao.save- Unable to merge 
java.lang.UnsupportedOperationException 
     at java.util.AbstractList.add(AbstractList.java:148) 
     at java.util.AbstractList.add(AbstractList.java:108) 
     at org.hibernate.collection.internal.PersistentBag.add(PersistentBag.java:292) 
     at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:496) 
     at org.hibernate.type.CollectionType.replace(CollectionType.java:563) 
     at org.hibernate.type.AbstractType.replace(AbstractType.java:178) 
     at org.hibernate.type.TypeHelper.replaceAssociations(TypeHelper.java:261) 
     at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:398) 
     at org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:221) 
     at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:282) 
     at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151) 
     at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:914) 
     at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:896) 
     at org.hibernate.engine.spi.CascadingAction$6.cascade(CascadingAction.java:288) 
     at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
     at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
     at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
     at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
     at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
     at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
     at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
     at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
     at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:439) 
     at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:308) 
     at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151) 
     at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:914) 
     at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:896) 
     at org.hibernate.engine.spi.CascadingAction$6.cascade(CascadingAction.java:288) 
     at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
     at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
     at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
     at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
     at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
     at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
     at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
     at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
     at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:439) 
     at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:308) 
     at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151) 
     at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:914) 
     at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:896) 
     at org.hibernate.engine.spi.CascadingAction$6.cascade(CascadingAction.java:288) 
     at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:380) 
     at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) 
     at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
     at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:409) 
     at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:350) 
     at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) 
     at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:208) 
     at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:165) 
     at org.hibernate.event.internal.DefaultMergeEventListener.cascadeOnMerge(DefaultMergeEventListener.java:439) 
     at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:308) 
     at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151) 
     at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76) 
     at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:904) 
     at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:888) 
     at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:892) 
     at com.company.hibernate.HibernateDao.save(HibernateDao.java:129) 
     at sun.reflect.GeneratedMethodAccessor62.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:601) 
     at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
     at $Proxy53.save(Unknown Source) 
     at com.company.application.UserManager.save(UserManager.java:46) 
     at sun.reflect.GeneratedMethodAccessor67.invoke(Unknown Source) 
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
     at java.lang.reflect.Method.invoke(Method.java:601) 
     at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:318) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
     at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
     at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
     at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
     at $Proxy66.save(Unknown Source) 
     at com.company.application.UserOperationController.saveUser(UserOperationController.java:533) 

Wir sind nicht sicher sind, wo die AbstractList herkommt, oder wie wir sind verantwortlich. Gibt es mögliche Probleme bei der Arbeit mit Hibernate 4 (dieses Problem ist seit der Aktualisierung neu), die zu teilweise nicht änderbaren Objekten führen können? Oder würde Hibernate so agieren, dass es versucht, nicht änderbare Instanzen von Objekten zu erstellen?

+0

Vom stacktrace, es klingt wie die Zusammenführung auf andere Objekte mit dem Benutzer in Verbindung stehen kaskadiert wird. Haben Sie Sammlungen als Bag-Typ? –

+0

Für mich sieht es aus wie ein Fehler im Ruhezustand, der es hässlich machen würde, dieses Problem zu umgehen. Ich denke, die einzige Chance zu bekommen ist, herauszufinden, welches Kind oder Enkelkind des Gegenstandes diesen Fehler erzeugt. Bei Tests können Sie die untergeordneten Elemente (und vielleicht Grand-Child-Elemente) von "item" manuell zusammenführen, anstatt sie in Kaskade zu stellen. – Johanna

+0

@mattb Wir haben definitiv keine Bag-Typen - nur HashMap und ArrayList. Wenn das Objekt untersucht wird, kurz bevor Hibernate es zusammenführt, scheint es so, als würden viele der ArrayList-Typen tatsächlich von Hibernate in einem PersistentBag eingeschlossen. (Aber, unter den Taschen waren tatsächliche konkrete ArrayList-Implementierungen, so sah ich das nicht als ein Problem.) –

Antwort

1

@OneToMany (Kaskade = CascadeType.ALL) @LazyCollection (LazyCollectionOption.FALSE) Privat Map associatedProjects = new HashMap();

wie wäre es, dies hinzuzufügen.

@OneToMany (cascade = CascadeType.ALL)

* @ JoinColumn (name = "") *

@LazyCollection (LazyCollectionOption.FALSE) private Karte associatedProjects = new HashMap();

0

Ich lief in das gleiche Problem (mit Sets nicht Lists) und es scheint, wie die Hibernate Persistent Variante der Sammlung in Frage versucht, eine abstrakte Basisklasse zu delegieren, die nicht die add Methode nicht implementiert. Die Lösung, die ich gefunden habe, war, das Datenelement auf null zu setzen, eine merge auszuführen und dann das Datenelement auf die neue Liste zurückzusetzen, die es enthalten soll. Der offensichtliche Nachteil ist, dass ich alle Datensätze wegbreche, auch wenn ich nur einen hinzufügen oder entfernen möchte. Der Vorteil ist, dass es tatsächlich funktioniert ...

0

Mit dieser Bewegungsart:

@javax.transaction.Transactional(Transactional.TxType.REQUIRES_NEW)