在删除操作之前,清除JPA或Hibernate EntityManager或合并实体

时间:2018-11-28 21:38:10

标签: java spring spring-boot jpa hibernate-entitymanager

我有一个通用的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处理EntityManagerstransactions的范围的管理。

关于Spring管理的EntityManager的最后一点 :我还想知道Spring管理的示例中的em是否是应用程序范围的?如果是这样,它是否不保留所有检索到的实体并不断扩展?

1 个答案:

答案 0 :(得分:1)

如果您使用的是Hibernate,则无需在删除实体之前执行merge。这只是一个JPA要求,但是Hibernate在这方面更宽容。

您还可以执行以下操作:

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

如果这不起作用,那可能是因为您没有将REMOVE操作级联到子关联。

您可以使T参数扩展一个Identifiable接口,该接口定义了getId方法,并让您的实体实现此接口,以便您的方法更通用。