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

Java 在删除操作之前,清除JPA或Hibernate EntityManager或合并实体,java,spring,spring-boot,jpa,hibernate-entitymanager,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) p

我有一个通用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;
    }
...
}
@组件
@事务性(transactionManager=“ubldbTransactionManager”)
公共类目录存储impl{
...
@PersistenceContext(unitName=eu.nimble.utility.Configuration.UBL\u PERSISTENCE\u UNIT\u NAME)
私人实体管理者;
公共实体(T实体){
如果(!em.contains(实体)){
实体=em.merge(实体);
}
em.remove(实体);
}
公共列表getEntities(字符串queryStr){
Query Query=em.createQuery(queryStr);
List result=query.getResultList();
返回结果;
}
...
}
在某个时刻,我意识到一些实体并没有被删除。然后,我发现一些
托管的
实体导致删除取消,如所述:

由于该方法是泛型的,因此它包含各种类型的实体。作为一种解决方法,我想消除导致删除取消的实体,并在
deleteEntity
方法的开头添加了
em.flush()
em.clear()
。虽然这样做有效,但我觉得这是一个肮脏的解决办法

所以,我想问一下这种情况下的一些最佳实践。例如,在
deleteEntity
中创建一个新的
EntityManager
会是一种选择吗?我不希望这样,因为我希望Spring能够管理
EntityManager
事务的范围


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

如果您使用的是Hibernate,则在删除实体之前不需要执行
合并
。这只是JPA的要求,但Hibernate在这方面更为宽松

您还可以执行以下操作:

entity = em.getReference(entity.getClass(), entity.getId());
em.remove(entity);
如果这不起作用,可能是因为您没有将删除操作级联到子关联


您可以让
T
参数扩展一个定义
getId
方法的
identification
接口,并让您的实体实现这个接口,这样您的方法就更通用了。

为什么要手工维护而不是使用Spring数据存储库?因为实体类型太多,我不想为每种实体类型创建单独的存储库。另外,针对删除操作中包含的实体类型,我还尝试创建一个
JpaRepository
,但结果是相同的。所以,我认为使用的是同一个EntityManager实例。我想知道如果我创建了个人存储库,是否会遇到这样的问题。非常感谢您的回复。是的,我使用Hibernate。然而,尽管所有的子关联(B->C1,B->C2,…)都有
cascade={CascadeType.all}
,但它没有工作。但是,我想原因是在同一个实体管理器中有一个托管父对象a,(a->B)。因为我仍然看到
unscheduling entity deletation
日志。实际上,没有双向关联。关联的形式为
A->B
B->C
。所有关联都有
CascadeType.All
B
是我尝试删除的实体,实体管理器中有引用我尝试删除的B实例的
A
实例。因此,我想我可以
取消A对B的引用,并
更新
A
。由于实体也有
orphanRemoving=true
关联,
B
将被删除。但是,您认为在
删除之前执行
刷新
清除
有意义吗?还是一种有效的模式?请尝试复制它,以便我可以在实践中看到问题。