2012-06-04 22 views
9

從Hibernate 3升級到4之後,我們正在努力通過一些在一路上彈出的扭結。讓我們特別難過的是一個UnsupportedOperationException,其中一個現有對象從數據庫中提取,調整和合並。合併現有的Hibernate模型對象時UnsupportedOperationException?

問題是休眠似乎是將對象添加到AbstractList

這似乎只發生在一個特定的對象類型,當保存在我們的DAO,但作爲最好的,我們可以告訴:

  1. 我們沒有使用會導致創建不可變實例的任何sublist()或asList()方法。
  2. 檢查正在保存的對象(這是巨大的,有很多孩子)我不認爲它的任何子項是AbstractList類型。

下面是圍繞堆疊點代碼片斷:

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); 
    } 
} 

我們用戶項,被保存,具有許多兒童用品如下定義:

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

T他Project班有其他有類似註釋的孩子,但一切都有CascadeType.ALLLazyCollectionOption.FALSE定義。

這裏是(相當高)堆棧跟蹤:

請注意,我們的代碼開始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) 

我們不知道在哪裏的AbstractList的是從,或未來如何我們負責。使用Hibernate 4時是否有任何潛在的缺陷(這是升級後的新問題),可能導致部分不可修改的對象?或者這會導致Hibernate以一種導致它嘗試創建不可修改的對象實例的方式行事?

+0

從堆棧跟蹤,這聽起來像合併被級聯到與用戶相關聯的其他對象。你有任何收藏映射爲袋類型? –

+0

對我來說,它看起來像一個在休眠的錯誤,這將使它難以解決這個問題。我認爲唯一得到的機會是找出項目的哪個孩子或大孩子產生這個錯誤。對於測試,您可以手動合併「item」的子項(也可能是盛大的子項),而不是讓它級聯。 – Johanna

+0

@mattb我們絕對沒有任何Bag類型 - 只有HashMap和ArrayList。在Hibernate合併之前檢查對象,看起來好像很多ArrayList類型實際上被Hibernate包裝在PersistentBag中。 (但是,在包的下面是實際的具體ArrayList實現,所以我沒有看到這是一個問題。) –

回答

1

@OneToMany(級聯= CascadeType.ALL) @LazyCollection(LazyCollectionOption.FALSE) 私人地圖associatedProjects =新的HashMap();

如何添加此項。

@OneToMany(級聯= CascadeType.ALL)

* @ JoinColumn(名稱= 「」)*

@LazyCollection(LazyCollectionOption。FALSE) private Map associatedProjects = new HashMap();

0

我遇到了同樣的問題(與SetsLists),它看起來像Hibernate的問題收集的持續變種試圖委託給不實現add方法的抽象基類。我找到的解決方案是將數據成員設置爲空,執行merge,然後將數據成員設置回我希望它包含的新列表。相當明顯的缺點是,即使我只想添加或刪除記錄,我也會將所有記錄都刪除。好處是,它的實際工作...

0

使用此交易類型:

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