2012-06-04 11 views
9

Sau khi nâng cấp từ Hibernate 3 lên 4, chúng tôi đang làm việc thông qua một vài kinks xuất hiện trên đường đi. Một trong đó có chúng tôi đặc biệt stumped là một UnsupportedOperationException, nơi một đối tượng hiện có được kéo từ cơ sở dữ liệu, tinh chỉnh, và sáp nhập.UnsupportedOperationException khi kết hợp một đối tượng mô hình Hibernate hiện có?

Vấn đề là Hibernate dường như có thêm một đối tượng đến một AbstractList

này dường như chỉ xảy ra với một loại đối tượng cụ thể, khi lưu trong DAO chúng ta, nhưng là tốt nhất như chúng ta có thể nói:

  1. Chúng tôi không sử dụng bất kỳ phương thức nào trong danh sách con() hoặc asList() sẽ gây ra một trường hợp bất biến được tạo.
  2. Kiểm tra đối tượng đang được lưu (rất lớn và có nhiều trẻ em) Tôi không nghĩ rằng rằng bất kỳ mục con nào của nó đều là loại AbstractList.

Dưới đây là các đoạn mã xung quanh các điểm stack:

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

tài mục của chúng tôi, hiện đang được lưu lại, có một số các mặt hàng trẻ em được xác định như vậy:

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

T Lớp học Project có các trẻ em được chú thích tương tự khác nhưng mọi thứ đều có CascadeType.ALL và được xác định là LazyCollectionOption.FALSE.

Đây là (khá cao) stack trace:

Lưu ý rằng mã của chúng tôi bắt đầu với 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) 

Chúng tôi không chắc chắn nơi AbstractList đến từ, hoặc làm thế nào chúng tôi chịu trách nhiệm. Có bất kỳ cạm bẫy tiềm năng khi làm việc với Hibernate 4 (vấn đề này là mới kể từ khi nâng cấp) có thể dẫn đến các đối tượng không thể sửa đổi một phần không? Hoặc điều đó sẽ khiến Hibernate hành động theo cách dẫn đến việc tạo ra các thể hiện không thể sửa đổi của các đối tượng?

+0

Từ stacktrace, có vẻ như việc hợp nhất đang được cascaded với các đối tượng khác liên quan đến tài khoản. Bạn có bất kỳ bộ sưu tập nào được ánh xạ dưới dạng loại Túi không? –

+0

Đối với tôi nó trông giống như một lỗi trong hibernate, mà sẽ làm cho nó xấu xí để đi xung quanh vấn đề đó. Tôi nghĩ rằng cơ hội duy nhất để có được là, là để tìm ra đứa trẻ hoặc đứa trẻ lớn của sản phẩm tạo ra lỗi này. Đối với các thử nghiệm, bạn có thể hợp nhất thủ công các con (và có thể là các con lớn) của 'item' thay vì để cho thác đó. – Johanna

+0

@mattb Chúng tôi chắc chắn không có bất kỳ loại túi nào - chỉ HashMap và ArrayList. Kiểm tra đối tượng ngay trước khi Hibernate kết hợp nó, có vẻ như là mặc dù nhiều kiểu ArrayList đã thực sự được bao bọc bởi Hibernate trong một PersistentBag. (Tuy nhiên, bên dưới các túi là thực tế cụ thể ArrayList thực hiện, vì vậy tôi không thấy điều này là một vấn đề.) –

Trả lời

1

@OneToMany (cascade = CascadeType.ALL) @LazyCollection (LazyCollectionOption.FALSE) Bản đồ cá nhân associatedProjects = new HashMap();

cách thêm mục này.

@OneToMany (cascade = CascadeType.ALL)

* @ JoinColumn (name = "") *

@LazyCollection (LazyCollectionOption.FALSE) Bản đồ cá nhân relatedProjects = new HashMap();

0

Tôi chạy vào vấn đề này cùng (với Sets không Lists) và nó có vẻ như biến dai dẳng Hibernate của bộ sưu tập trong câu hỏi nỗ lực để uỷ thác cho một lớp cơ sở trừu tượng mà không thực hiện phương pháp add. Giải pháp mà tôi tìm thấy là đặt thành viên dữ liệu thành rỗng, thực hiện merge rồi đặt thành viên dữ liệu trở lại danh sách mới mà tôi muốn chứa. Nhược điểm khá rõ ràng là tôi thổi đi tất cả các hồ sơ ngay cả khi tôi chỉ muốn thêm hoặc xóa một hồ sơ. Ngược ở đây là nó thực sự hoạt động ...

0

Sử dụng loại giao dịch này:

@javax.transaction.Transactional(Transactional.TxType.REQUIRES_NEW) 
Các vấn đề liên quan