首页 > 解决方案 > Spring Batch + JPA + PostgreSQL 当前事务被中止,命令被忽略直到事务块结束

问题描述

我面临以下示例中描述的问题。我正在使用 Spring Batch ItemWriter 将数据插入数据库。数据导入成功后,我还想将批处理状态插入到另一个表中。但是,如果之前有失败的查询,Postgres 不允许我这样做。

import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.item.ItemWriter;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.stereotype.Component;

@JobScope
@Component
@Slf4j
public class CsvWriter implements ItemWriter<List<CsvEntity>> {

  // these are org.springframework.data.jpa.repository.JpaRepository
  DataRepository dataRepository;
  BatchStatusRepository batchStatusRepository;

  @Override
  public void write(List<? extends List<DataEntity>> data) {
    Long batchId = data.get(0).get(0).getBatchId(); // each data belongs to a batch with batch id;
    try {
      csvRepository.saveAll(data.get(0)); // save data

      batchStatusRepository.save( // if data was ok, write status Ok
        BatchStatusEntity.builder()
          .batchId(batchId)
          .status("Ok")
          .build());
    } catch (DataIntegrityViolationException e) { // if there is inconsistency in data (duplicates), I want to set an Error status
      log.error("Duplicate entity", e);

      batchStatusRepository.save( // this throws org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
        BatchStatusEntity.builder()
          .batchId(batchId)
          .status("Error")
          .build());
      }
  }
}

据我了解,我需要回滚第一个事务,但我不知道如何。我试图用 将saveAll分成单独的方法@Transactional(value = "transactionManager", rollbackFor = DataIntegrityViolationException.class),但它没有用。

标签: javaspringpostgresqlspring-bootjpa

解决方案


推荐阅读