UnsupportedOperationException при объединении существующего объекта модели Hibernate?

После обновления с Hibernate 3 до 4 мы работаем над несколькими перегибами, которые появились по пути. Один из них, который ставит нас в тупик, — это исключение UnsupportedOperationException, где существующий объект извлекается из базы данных, настраивается и объединяется.

Проблемазаключается в том, что Hibernate, по-видимому, добавляет объект в 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);
    }
}

Наш элемент User,который сохраняется, имеет ряд дочерних элементов, определенных следующим образом:

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

В классе Projectесть другие аналогично аннотированные дети, но у всего есть CascadeType.ALLи LazyCollectionOption.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 действовать таким образом, что это приведет к попытке создать неизменяемые экземпляры объектов?

10
задан Craig Otis 4 June 2012 в 22:40
поделиться