[英]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.