在自定义实现中包装Hibernate PersistentSet的正确方法? [英] Correct Way to Wrap a Hibernate PersistentSet in a Custom Implementation?

查看:50
本文介绍了在自定义实现中包装Hibernate PersistentSet的正确方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have implemented an ObservableSet class that wraps a Set and implements the Set interface and the Observable pattern, firing events to registered listeners when elements are added or removed. I'd like to use this ObservableSet in a class that Hibernate maps. Hibernate wants getters and setters for Set, and sets them to be instances of PersistentSet. As in this question from 2010, I initially tried adding logic to the Getter and Setter to wrap whatever Set was passed in with an ObservableSet, but this results in the exception: 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.

I don't need to listen for changes from within Hibernate. My main concern is that once I deserialize the object from the database, I can listen to changes. I could write a second (non-beans) getter that just returns the wrapper ObservableSet, and then enforce through coding convention that we don't alter the contents of the inner set except through the wrapper we get through this method, but that seems kind of unpleasant and hacky.

有想法吗?

推荐答案

您可以使用注释对一对多集合进行注释,如下所示:

You can annotate a One-To-Many collection with an annotation as follows:

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

并实现some.collection.Type,使其包装PersistentSet:

And implement some.collection.Type such that it wraps the 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 or Map is implemented the same way.

这篇关于在自定义实现中包装Hibernate PersistentSet的正确方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆