使用 spring 数据和 JDBC 模板进行交易处理

Transaction handling with spring data and JDBC Template

我想在不先为每个对象创建 Select 的情况下进行批量删除。我没有找到使用 spring 数据 jpa 和实体管理器来执行 this.For 的方法,因此我尝试了 JDBC 模板。 但是,我遇到了可分页的问题。 这段代码工作正常,所有删除都是通过批处理执行的。不幸的是,每个实体都有一个不必要的 select。

@Transactional
public void deleteFoos() {

   Page<Foo> page = repository.findAll(PageRequest.of(0,50);
   Pageable pageable = null;
   do {
      if ( pageable != null ) {
         page = repository.findAll( pageable );
      }
      repository.deleteAll( page.getContent() );
   } while ( (pageable = page.nextPageable()) != Pageable.unpaged() );
}

我现在尝试的是直接用 JDBC 模板实现整个事情。

@Transactional
    public void deleteFoos() {
    
       Page<Foo> page = repository.findAll(PageRequest.of(0,50);
       Pageable pageable = null;
       do {
          if ( pageable != null ) {
             page = repository.findAll( pageable );
          }
          //repository.deleteAll( page.getContent() );
 jdbcTemplate.batchUpdate(
         "DELETE FROM foo WHERE (id = ?)",
         page.getContent(),
         page.getTotalItems(),
         ( preparedStatement, argument ) -> {
            preparedStatement.setObject( 1, argument.getId() );
         } );
       } while ( (pageable = page.nextPageable()) != Pageable.unpaged() );
    }

但是,第三页和第四页始终是空的。似乎直接执行了删除。自动提交已关闭,还有什么问题吗?

编辑:Jens 的解决方案工作正常:“您可以简单地重复请求第一页并将其删除。”

JdbcTemplate 只是执行 SQL 语句,所以是的,它们会立即执行。与 JPA 操作一样,不涉及缓存。 但即使是 JPA 操作也会在执行查询之前刷新到数据库中,所以差别并不大。

您可以简单地重复请求第一页并删除它。

但是使用带删除的分页没有多大意义,您可以只删除 table 中的所有行并在一次往返数据库中完成:

DELETE FROM foo

如果您想批量删除,您仍然可以在不加载任何应用程序的情况下执行此操作。详细信息可能取决于数据库,但与此类似的东西应该可以很好地工作:

DELETE FROM foo
LIMIT 100;