简体   繁体   中英

Detached entity issue using Hibernate with mutiny

As part of my integration tests, I am using the following code to query for an entity and then remove it from the underlying datastore:

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

The corresponding implementations are given by an abstract repository class:

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

The entity is retrieved correctly using hibernate/mutiny, however when trying to remove it, the remove method triggers an exception:

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)

As I am editing my question, just realized that I am using two disjoint sessions (one for retrieving the entity and then another one for removing the entity), which is probably the reason why I am getting the error.

However not sure how I should refactor the code to make it work.

OK it turns out there is a relatively simple solution to my problem. All I need to do is to first retrieve the entity using SessionFactory.find() and then chain with a remove:

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

Probably not the best way to do this, especially if the entity has lots of eager-loaded associations. But the issue was indeed triggered because I was trying to remove an entity, which was retrieved in another session

Edit Actually, there is no default eager-loading of associations, as explained in the docs

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM