0

作为集成测试的一部分,我使用以下代码查询实体,然后将其从底层数据存储中删除:

Country country = countryRepository.findById("CH").await().indefinitely();
countryRepository.remove(country).await().indefinitely();

相应的实现由抽象存储库类给出:

public abstract class AbstractRepository<Entity extends AbstractEntity,Id> implements Repository<Entity, Id> {

    @Inject
    private Mutiny.SessionFactory sessionFactory;
    private final Class<Entity> _class;

    public AbstractRepository(Class<Entity> _class){
        this._class = _class;
    }

    @Override
    public Uni<List<Entity>> findAll() {
        return sessionFactory.withSession(s->s.createQuery("SELECT e from "+ _class.getName()+" e", _class)
                .getResultList())
                .onItem().invoke(l-> l.forEach(AbstractEntity::markAsPersistent));
    }

    @Override
    public Uni<Entity> findById(Id id) {
        return sessionFactory.withSession(s->s.find(_class, id));
    }

    @Override
    public Uni<Entity> add(Entity entity) {
        if(entity.isPersistent()){
            return sessionFactory.withSession(s ->s.merge(entity));
        }else{
            entity.markAsPersistent();
            return sessionFactory.withSession(s ->s.persist(entity).chain(s::flush).replaceWith(entity));
        }
    }

    @Override
    public Uni<Void> remove(Entity entity) {
        return sessionFactory.withSession(s -> s.remove(entity));
    }
}

使用休眠/叛变正确检索实体,但是当尝试删除它时,remove 方法会触发异常:

javax.persistence.PersistenceException: org.hibernate.HibernateException: java.util.concurrent.CompletionException: java.lang.IllegalArgumentException: unmanaged instance passed to remove()
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
    at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181)
    at org.hibernate.reactive.session.impl.ReactiveExceptionConverter.convert(ReactiveExceptionConverter.java:31)

当我编辑我的问题时,刚刚意识到我正在使用两个不相交的会话(一个用于检索实体,另一个用于删除实体),这可能是我收到错误的原因。

但是不确定我应该如何重构代码以使其工作。

4

1 回答 1

1

好的,事实证明我的问题有一个相对简单的解决方案。我需要做的就是首先使用 SessionFactory.find() 检索实体,然后使用 remove 链接:

    @Override
    public Uni<Void> remove(Entity entity) {
        return sessionFactory.withTransaction((s,t) -> s.find(_class, entity.getId()).chain(s::remove));
    }

可能不是最好的方法,特别是如果实体有很多预先加载的关联。但是这个问题确实被触发了,因为我试图删除一个实体,该实体是在另一个会话中检索到的

编辑 实际上,没有默认的预先加载关联,如文档中所述

于 2021-12-29T21:36:51.527 回答