繁体   English   中英

Spring Batch 步骤不立即提交事务

[英]Spring Batch step not committing transaction immediately

我配置了读取和验证数据的步骤。 如果任何验证失败,我将更新错误表(创建以跟踪文件详细信息)状态为失败,原因为验证消息(BatchFileDetail 是以下代码中的错误表)。 一旦将其保存在数据库中,我立即根据错误表状态抛出异常

下面是我的代码

    @Bean
    public Job fileParserJob() {
        return jobBuilderFactory.get("fileParserJob")
                .incrementer(new RunIdIncrementer())
                .start(validateFileStep())
                .build();
    }

    public Step validateFileStep() {
        return stepBuilderFactory.get("validateFileStep")
                .tasklet(fileTasklet)
                .build();
    }

    @Override
    @Transactional(dontRollbackOn=BatchServiceException.class)
    public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws 
    Exception {
        Resource resource = new FileSystemResource(filePath);
        BatchFileDetail batchFileDetail = new BatchFileDetail();
        batchFileDetail.setFileId(String.valueOf(System.currentTimeMillis()));
        batchFileDetail.setFileName(resource.getFilename());
        batchFileDetail.setStatus("STARTED");
        batchFileDetail.setProcessedOn(new Date());
        CommonUtillity.validateBatchResource(resource, StringConstants.FILE_NAME, batchFileDetail);
        validateBatchFileDetail(resource.getFile(), batchFileDetail);
        batchFileDetailRepository.saveAndFlush(batchFileDetail);
        if(CBOSConstants.FAILED.equals(batchFileDetail.getStatus())) {
            throw new BatchServiceException(batchFileDetail.getReason());
        }
        return RepeatStatus.FINISHED;
    }

}

但是我在错误表中保存的数据正在回滚。 处理异常导致继续执行另一个步骤,但我想通过错误表中的条目终止当前作业。 任何帮助表示赞赏。

您正在使用@Transactional(dontRollbackOn=BatchServiceException.class)注释您的 tasklet。 这不是告诉 Spring Batch 不回滚给定异常类型的事务的方式。

您的 tasklet 将在 Spring Batch 控制的事务范围内执行,您可以通过事务属性对其进行自定义,请参阅AbstractTaskletStepBuilder#transactionAttribute

因此,在您的情况下,您应该能够通过删除 tasklet 上的@Transactional来实现您的要求,并使用以下内容定义您的步骤:

@Bean
public Step validateFileStep() {
    TransactionAttribute transactionAttributes = new DefaultTransactionAttribute() {
        @Override
        public boolean rollbackOn(Throwable exception) {
            return !(exception instanceof BatchServiceException);
        }
    };

    return stepBuilderFactory.get("validateFileStep")
            .tasklet(fileTasklet)
            .transactionAttribute(transactionAttributes)
            .build();
}

这是一个简单的tasklet。 对于面向块的 tasklet,可以使用FaultTolerantStepBuilder#noRollback(Class)来做到这一点。

我找到的解决方案可能不是最好的,但现在我继续下面。

@Bean
public Job fileParserJob() {
    return jobBuilderFactory.get("fileParserJob")
            .incrementer(new RunIdIncrementer())
            .start(validateFileStep())
            .next(validateFileStatusStep())
            .build();
}

public Step validateFileStep() {
    return stepBuilderFactory.get("validateFileStep")
            .tasklet(fileTasklet)
            .build();
}

public Step validateFileStatusStep() {
    return stepBuilderFactory.get("validateFileStatusStep")
            .tasklet(validateBatchFileDetailTasklet)
            .build();
}

FileTasklet.java
-----------------
@Override
@Transactional(dontRollbackOn=BatchServiceException.class)
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
    Resource resource = new FileSystemResource(filePath);
    BatchFileDetail batchFileDetail = new BatchFileDetail();
    batchFileDetail.setFileId(String.valueOf(System.currentTimeMillis()));
    batchFileDetail.setFileName(resource.getFilename());
    batchFileDetail.setStatus("STARTED");
    batchFileDetail.setProcessedOn(new Date());
    CommonUtillity.validateBatchResource(resource, StringConstants.FILE_NAME, batchFileDetail);
    validateBatchFileDetail(resource.getFile(), batchFileDetail);
    batchFileDetailRepository.saveAndFlush(batchFileDetail);
    return RepeatStatus.FINISHED;
}

}

ValidateBatchFileDetailTasklet
------------------------------
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
    BatchFileDetail batchFileDetail = batchFileDetailRepository.getRecentFailedTransactionStatus(StringConstants.FILE_NAME);
    if(StringConstants.FAILED.equals(batchFileDetail.getStatus())) {
        throw new BatchServiceException(batchFileDetail.getReason());
    }
    return RepeatStatus.FINISHED;
}

使用此解决方案,第一个错误表会更新失败状态和失败原因,然后一步提交事务。 下一步根据文件名获取最近的记录并检查获取的记录的状态。 如果是FAILED ,则抛出异常以终止当前作业。

如果状态不仅仅是FAILED ,则必须处理下一个数据。 如果状态为FAILED ,我们必须终止当前的批处理作业。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM