deleteAllInBatch() 和deleteAll() 有什么区别?

Asm*_*fri 7 hibernate jpa spring-boot

我是休眠和春季启动的新手。最近,我被分配了一项任务来创建一个关系查询应用程序。问题是我正在遵循的教程使用的是 JPARepository,而我正在处理的代码中的先前工作是使用 CRUDRepository。

我的问题是,我可以使用 crudRepository deleteAll() 的功能来代替 JPARepository 的方法 deleteAllInBatch() 吗?另外,这两个接口有什么不同?

我在网上没有找到任何有用的文档,因此进行查询。

Ale*_*rov 9

简短的回答是,是的,您可以使用deleteAll而不是deleteAllInBatch。但你需要知道这些功能的实现是非常不同的。deleteAllInBatch 通过使用一个删除查询来完成其工作。

@Transactional
public void deleteAllInBatch() {
    em.createQuery(getDeleteAllQueryString()).executeUpdate();
}
private String getDeleteAllQueryString() {
    return getQueryString(DELETE_ALL_QUERY_STRING, entityInformation.getEntityName());
}
public static final String DELETE_ALL_QUERY_STRING = "delete from %s x";
Run Code Online (Sandbox Code Playgroud)

另一方面,deleteAll() 导致 findAll,之后我们将迭代所有实体并为每个实体调用删除。

@Transactional
public void deleteAll() {

    for (T element : findAll()) {
        delete(element);
    }
}
Run Code Online (Sandbox Code Playgroud)

正如我们所看到的,deleteAll 会导致 N+1 个请求,其中 N 是目标表的总大小。

  • 我想补充一点,虽然deleteAllInBatch() 速度更快,但应谨慎使用。在我们的生产系统中,要删除的对象数量非常大。这就是为什么我首先使用批量删除的原因。但是,当 Hibernate 将查询转换为单个本机查询时,查询字符串可能会很长,从而导致 java.lang.StackOverflowError。我在 Spring Boot 2.4.13 和 Hibernate 5.4.32 中发生过这种情况。 (2认同)