簡體   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