繁体   English   中英

Spring 批处理 - 即使块引发一些异常,是否有办法提交数据?

[英]Spring Batch - Is there a way to commit data even if the chunk raise some exception?

我有一个从队列中读取、处理并写入数据库的进程。 即使过程失败,我也必须存储在数据库中。 但是 Spring 批处理步骤是事务性的,并且总是回滚更改。 那么,即使块引发一些异常,有没有办法提交数据?

编辑我:

我尝试使用 Tasklet,但得到了相同的行为。

提前致谢。

在配置步骤时,可以使用noRollback()来配置一个不会导致回滚的异常列表。 作为已配置异常的子类的任何异常都不会回滚。 这意味着如果您只是想永不回滚,请将其设置为Exception ,它是所有异常的父级。

可以从文档中找到一个示例:

@Bean
public Step step1() {
    return this.stepBuilderFactory.get("step1")
                .<String, String>chunk(2)
                .reader(itemReader())
                .writer(itemWriter())
                .faultTolerant()
                .noRollback(Exception.class)
                .build();
}

我尝试按照 Ken Chan 的建议使用noRollback()但没有奏效。 还尝试放置特定的异常,但它一直在做回滚。

条件流在步骤级别没有项目级别,所以它对我没有帮助。 也尝试过 Listeners 但文档说:

This listener is designed to work around the lifecycle of an item. This means that each method should be called once within the lifecycle of an item and in fault tolerant scenarios, any transactional work that is done in one of these methods would be rolled back and not re-applied. Because of this, it is recommended to not perform any logic using this listener that participates in a transaction.

我使用面向分块的解决方案的 Tasklet 解决了我的问题,并将 @Transactional 添加到 Tasklet 的执行方法中。

@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE, noRollbackFor = {
        ErrorInternoServidorException.class, SolicitudIncorrectaException.class,
        RegistroNoEncontradoException.class, SolicitudEventoObjetaException.class,
        SolicitudEventoValidaException.class, MimCargueSolicitudException.class, ConflictException.class,
        UnauthorizedException.class, ForbiddenException.class }) 
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

Spring 面向批量分块的解决方案被包装在一个带有他自己事务的 Tasklet 中,所以我尝试使用自己的规则创建一个新的。

感谢大家的回复。 我学到了很多。

即使在处理过程中引发异常,您也可以编写 JOB 以提交所有数据的一种方法是使用 SkipPolicy 并将数据写入那里的目标数据库。

SkipPolicy 的主要好处之一是通过处理记录导致和异常的数据,并且记录部分甚至可以将记录插入数据库中的临时表中。

public class FileVerificationSkipper implements SkipPolicy {

    private static final int MAX_VALUES_TO_SKIP = 1000;
    private JdbcTemplate jdbcTemplate;

    public FileVerificationSkipper(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    @Override
    public boolean shouldSkip(Throwable exception, int skipCount) throws SkipLimitExceededException {
        if (exception instanceof FlatFileParseException && skipCount <= MAX_VALUES_TO_SKIP) {
            jdbcTemplate.update("INSERT INTO YourTable(column1, column2) VALUES(?,?)");
            return true;
        } else {
            return false;
        }
    }
}

希望这可以帮助。

暂无
暂无

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

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