Очистка JPA или Hibernate EntityManager или объединение объекта перед операцией удаления - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть общая реализация репозитория JPA, имеющая дело со многими типами сущностей следующим образом:

@Component
@Transactional(transactionManager = "ubldbTransactionManager")
public class CatalogueRepositoryImpl {
...

    @PersistenceContext(unitName = eu.nimble.utility.Configuration.UBL_PERSISTENCE_UNIT_NAME)
    private EntityManager em;

    public <T> void deleteEntity(T entity) {
        if(!em.contains(entity)) {
            entity = em.merge(entity);
        }
        em.remove(entity);
    }

    public <T> List<T> getEntities(String queryStr) {
        Query query = em.createQuery(queryStr);
        List<T> result = query.getResultList();
        return result;
    }
...
}

В какой-то момент я понял, что некоторые сущности не были удалены.Затем я обнаружил, что некоторые managed сущности вызывают отмену удаления, как описано в: https://stackoverflow.com/a/16901857/502059

Поскольку метод является универсальным, он включает в себя различные типы сущностей внутри.В качестве обходного пути я хотел избавиться от сущностей, вызывающих отмену удаления, и добавил em.flush() и em.clear() в начале метода deleteEntity.Хотя это сработало, я чувствую, что это грязный обходной путь.

Итак, я спрашиваю некоторые передовые практики для такого случая.Например, будет ли создание нового EntityManager в deleteEntity альтернативой?Я не хотел этого, так как я хотел, чтобы Spring управлял областью действия EntityManagers и transactions.

И еще один момент о EntityManager, управляемом Spring * : Мне также интересно, является ли em в примере, управляемом Spring, областью применения?Если так, разве он не сохранит все найденные объекты и не будет постоянно расширяться?

1 Ответ

0 голосов
/ 29 ноября 2018

Если вы используете Hibernate, вам не нужно делать merge перед удалением объекта.Это только требование JPA, но Hibernate более мягок в этом отношении.

Вы также можете сделать что-то вроде:

entity = em.getReference(entity.getClass(), entity.getId());
em.remove(entity);

Если это не сработает, это может быть потому, что вы некаскадная операция REMOVE для дочерних ассоциаций.

Вы можете сделать аргумент T расширением интерфейса Identifiable, который определяет метод getId, и ваши сущности реализуют этот интерфейс, чтобы ваш метод был более универсальным.

...