【问题标题】:Correct Way to Wrap a Hibernate PersistentSet in a Custom Implementation?在自定义实现中包装 Hibernate PersistentSet 的正确方法?
【发布时间】:2012-09-28 23:49:24
【问题描述】:

我实现了一个 ObservableSet 类,它包装了一个 Set 并实现了 Set 接口和 Observable 模式,在添加或删除元素时向注册的侦听器触发事件​​。我想在 Hibernate 映射的类中使用这个 ObservableSet。 Hibernate 想要 Set 的 getter 和 setter,并将它们设置为 PersistentSet. 的实例 就像在 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。

想法?

【问题讨论】:

  • 为什么需要向监听器触发事件​​?

标签: java hibernate


【解决方案1】:

您可以使用如下注解来注解一对多集合:

@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 的实现方式相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 2020-06-29
    • 1970-01-01
    相关资源
    最近更新 更多