在自定义实现中包装Hibernate PersistentSet的正确方法?

时间:2012-09-28 23:49:25

标签: java hibernate

我已经实现了一个包含Set的ObservableSet类,并实现了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中监听更改。我主要担心的是,一旦我从数据库反序列化对象,我就可以听取更改。我可以编写第二个(非bean)getter,它只返回包装器ObservableSet,然后通过编码约定强制执行,我们不会改变内部集的内容,除非通过我们通过这个方法获得的包装器,但这似乎是善良的不愉快和hacky。

思想?

1 个答案:

答案 0 :(得分:2)

您可以使用注释注释One-To-Many集合,如下所示:

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

列表或地图以相同的方式实施。