【问题标题】:Transaction handling with spring data and JDBC Template使用 spring 数据和 JDBC 模板进行事务处理
【发布时间】:2021-08-02 03:11:33
【问题描述】:

我想在不先为每个对象进行选择的情况下进行批量删除。我没有找到使用 spring data 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 的解决方案效果很好:“您可以简单地重复请求第一页并将其删除。”

【问题讨论】:

  • 不接受以前的一个答案。
  • '看起来删除是直接执行的' - ummmmm...为什么不呢?你真的让我很困惑
  • 另外,为什么你觉得你需要分页来删除数据库表中的所有内容?只需致电DELETE FROM foo 即可完成
  • 好吧,删除查询仅限于 id。这也是一个演示示例,但描述了问题。不幸的是,这并不容易
  • @K.Nicholas 随时回答未决问题。这将是一个很大的帮助:)

标签: spring-data-jpa jdbctemplate spring-transactions


【解决方案1】:

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

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

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

DELETE FROM foo

如果您想批量删除,您仍然可以这样做,而无需在应用程序中加载任何内容。细节可能取决于数据库,但类似的东西应该可以很好地工作:

DELETE FROM foo
LIMIT 100;

【讨论】:

  • 感谢 Jens 的回答。该示例只是以简单的方式显示了问题。在应用程序中,执行 querydsl 查询,选择应该删除的 ID。如果 DELETE 总是立即执行,那么回滚会发生什么?那么只有部分被回滚,因为之前的部分已经在执行?我在更新时遇到了同样的问题,即在这里我必须一遍又一遍地浏览第一页?还是我有机会像 JPA 一样设计行为,以便在方法/事务结束时执行所有语句?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-04
  • 2013-02-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多