2012-09-28 43 views
2

我已經實現了一個ObservableSet類,該類封裝了一個Set並實現了Set接口和Observable模式,當添加或刪除元素時將事件觸發到註冊的偵聽器。我想在Hibernate映射的類中使用這個ObservableSet。 Hibernate想要Set的getter和setter,並將它們設置爲PersistentSet.的實例如在this question from 2010中,我最初嘗試向Getter和Setter添加邏輯以包裝傳入的任何Set與ObservableSet,但這會導致例外:Exception in thread "main" org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: ...在自定義實現中封裝Hibernate PersistentSet的正確方法?

我不需要監聽Hibernate中的更改。我主要關心的是,一旦我從數據庫中反序列化對象,我就可以聽取更改。我可以編寫第二個(非bean)getter,它只是返回包裝器ObservableSet,然後通過編碼約定強制我們不改變內部集合的內容,除非通過我們通過這個方法獲得的包裝器,令人不快和哈克。

想法?

+0

爲什麼你需要向聽衆發射事件? –

回答

2

您可以批註一到,許多集合與註釋如下:

@OneToMany(...) 
@CollectionType(type = "some.collection.Type") 
public Set<Entity> getEntities() { 
    return entities; 
} 

並實行some.collection.Type使得它包裹PersistentSet:

public class TestCollectionType implements UserCollectionType { 
    @Override 
    public PersistentCollection instantiate(SessionImplementor session, CollectionPersister persister) 
        throws HibernateException { 
      return new Wrapper(new PersistentSet(session)); 
    } 
    @Override 
    public Object instantiate(int anticipatedSize) { 
      return new Wrapper(new HashSet<>()); 
    } 

    @Override 
    public PersistentCollection wrap(SessionImplementor session, Object collection) { 
      return new Wrapper(new PersistentSet(session, (Set<?>)collection)); 
    } 

    @Override 
    public Iterator getElementsIterator(Object collection) { 
      return ((Set<?>)collection).iterator(); 
    } 

    @Override 
    public boolean contains(Object collection, Object entity) { 
      return ((Set<?>)collection).contains(entity); 
    } 

    @Override 
    public Object indexOf(Object collection, Object entity) { 
      throw new UnsupportedOperationException(); 
    } 

    @Override 
    public Object replaceElements(Object original, Object target, CollectionPersister persister, Object owner, 
        Map copyCache, SessionImplementor session) throws HibernateException { 
      ((Set<?>)target).clear(); 
      ((Set<?>)target).addAll((Set)original); 
      return target; 
    } 
} 

列表或地圖以相同的方式實施。

相關問題