使用 spring 数据和 JDBC 模板进行事务处理

问题描述

我想批量删除而不先为每个对象做一个选择。我没有找到使用 spring 数据 jpa 和实体管理器来执行此操作的方法。出于这个原因,我尝试了 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() );
   } 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 操作也会在查询执行之前刷新到数据库中,因此差异并不大。

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

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

DELETE FROM foo

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

DELETE FROM foo
LIMIT 100;