2

我已经实现了一个ObservableSet包装 Set 并实现 Set 接口和 Observable 模式的类,在添加或删除元素时向注册的侦听器触发事件​​。我想在 Hibernate 映射的类中使用这个 ObservableSet。Hibernate 需要 getter 和 setter Set,并将它们设置为PersistentSet.As in this question from 2010的实例,我最初尝试向 Getter 和 Setter 添加逻辑,以使用 ObservableSet 包装传入的任何 Set,但这会导致异常:Exception in thread "main" org.hibernate.HibernateException: A collection with cascade="all-delete-orphan" was no longer referenced by the owning entity instance: ...

我不需要监听 Hibernate 内部的变化。我主要担心的是,一旦我从数据库中反序列化对象,我就可以监听更改。我可以编写第二个(非beans)getter,它只返回包装器ObservableSet,然后通过编码约定强制我们不改变内部集的内容,除非通过我们通过这个方法获得的包装器,但这看起来很友好的不愉快和hacky。

想法?

4

1 回答 1

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

List 或 Map 的实现方式相同。

于 2014-06-03T13:20:04.320 回答