【问题标题】:Spring Batch - how to COMPLETE a job when the JdbcPagingItemReader returns no dataSpring Batch - 当 JdbcPagingItemReader 没有返回数据时如何完成作业
【发布时间】:2016-08-30 06:07:44
【问题描述】:

我的问题与existing SO question 正好相反。

JdbcPagingItemReader 的行为似乎与该问题中描述的相反,即如果JdbcPagingItemReader 未找到任何记录,则作业被标记为FAILED。

日志表明作业被标记为FAILED,因为阅读器无法从病房的第1页获取页面,SELECT由于SQLCODE=-313而失败,即

-313 指定的主机变量数不等于参数标记数

因此,整个步骤被标记为失败,导致作业失败。

对于病房第1页的查询,排序键包含在SELECT中,如PAYMENT_ID > ?,我猜因为没有PAYMENT_IDs,所以找不到占位符的值所以错误。

在这种特殊情况下,如何忽略此错误并将作业标记为COMPLETE?

我尝试了 Trever Shick 在其他问题的回答中指定的解决方案并返回

if(stepExecution.getReadCount() == 0 ){
            return ExitStatus.COMPLETED;
        }

没有解决问题。

块大小和阅读器页面大小都等于 10 并且 THROTTLE_LIMIT=20。

@Bean
    public Step step1(StepBuilderFactory stepBuilderFactory,
            ItemReader<RemittanceVO> syncReader, ItemWriter<RemittanceClaimVO> writer,
            ItemProcessor<RemittanceVO, RemittanceClaimVO> processor) {

        return stepBuilderFactory.get("step1")
                .<RemittanceVO, RemittanceClaimVO> chunk(Constants.SPRING_BATCH_CHUNK_SIZE)
                .reader(syncReader)
                .listener(afterReadListener)
                .processor(processor)
                .writer(writer)
                .taskExecutor(simpleAsyntaskExecutor)
                .throttleLimit(Constants.THROTTLE_LIMIT)
                .build();
    }

不是完整的堆栈跟踪,而是来自日志的一行,

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [SELECT PAYMENT_ID,INSURED_LAST_NM,INSURED_FIRST_NM,LAST_NM,FIRST_NM,CONTRACT_NUM,CARRIER_CD,CARRIER_GROUP,CONTRACT_NUM,REL_AR_SEQ_NUM,FROM_DOS_DT,THRU_DOS_DT,BILL_AMT,RX_NUM_BP,CERT_NUM_LEFT_BP,MODIFIER,PROC_CD ,DEPOSIT_ID,PRNT_CONTRACT_NUM,REMIT_TYPE_CD AS RMT_TYPE FROM AR.PAYMENTS WHERE (CONTRACT_NUM IN (SELECT CONTRACT_NUM FROM AR.PAYMENTS WHERE RMTST_RF='M' AND DELETE_IND='N' GROUP BY CONTRACT_NUM ) AND DELETE_IND='N' AND RMTST_RF='M') AND ((PAYMENT_ID > ?)) ORDER BY PAYMENT_ID ASC FETCH FIRST 50 ROWS ONLY]; nested exception is com.ibm.db2.jcc.am.SqlException: DB2 SQL Error: SQLCODE=-313, SQLSTATE=07004, SQLERRMC=null, DRIVER=4.11.77

PAYMENT_ID 列是我的排序键,AND ((PAYMENT_ID &gt; ?)) 部分已由 Spring Batch 添加。

我的读者豆,

@Bean
    public ItemReader<RemittanceVO> syncReader() {
        SynchronizedItemStreamReader<RemittanceVO> syncReader = new SynchronizedItemStreamReader<RemittanceVO>();
        syncReader.setDelegate(reader());
        return syncReader;
    }

    @Bean
    public ItemStreamReader<RemittanceVO> reader() {
        JdbcPagingItemReader<RemittanceVO> reader = new JdbcPagingItemReader<RemittanceVO>();
        reader.setDataSource(dataSource);
        reader.setRowMapper(new RemittanceRowMapper());
        reader.setQueryProvider(queryProvider);
        reader.setPageSize(Constants.SPRING_BATCH_READER_PAGE_SIZE);
        return reader;
    }

查询提供者 bean,

@Bean
    public PagingQueryProvider queryProvider() throws Exception{
        SqlPagingQueryProviderFactoryBean queryProviderBean= new SqlPagingQueryProviderFactoryBean();
        queryProviderBean.setDataSource(dataSource);
        queryProviderBean.setDatabaseType("DB2");
        queryProviderBean.setSelectClause(Constants.REMITTANCES_SELECT_CLAUSE);
        queryProviderBean.setFromClause(Constants.REMITTANCES_FROM_CLAUSE);
        queryProviderBean.setWhereClause(Constants.REMITTANCES_WHERE_CLAUSE);
        queryProviderBean.setSortKey(Constants.REMITTANCES_SORT_KEY);
        PagingQueryProvider queryProvider = queryProviderBean.getObject();
        return queryProvider;
    }   

【问题讨论】:

  • 条件,如果遇到这种情况,stepExecution.getReadCount() == 0 仍然为真,但框架无法识别由Step 或Job 的侦听器设置或返回的ExitStatus。
  • 我的意思是说框架在调试日志中转储的值是相同的——设置或返回不同的值没有影响。比原来的。
  • 我也是同样的问题,如果你发现了请更新解决方案
  • @vsr:感谢您的提问。看看我的回答有没有帮助。我记得做过类似的事情,但不是 100% 确定。

标签: spring-batch


【解决方案1】:

我无法确定,但我认为,我在 step & job listeners 中做了以下工作。

我基本上写了一个StepExecutionListener并覆盖afterStep方法如下,

@Override
        public ExitStatus afterStep(StepExecution stepExecution) {
        if (stepExecution.getReadCount() == 0) {
            logger.info(
                "!!! Step is marked as FAILED because no rows OR no valid rows  were read by reader of this step !");
            ExitStatus newExitStatus = ExitStatus.COMPLETED;
            stepExecution.setExitStatus(newExitStatus);
            return newExitStatus;
        }
        return null;
        }

还写了一个工作级别的监听器 - JobExecutionListenerSupport,把类似的东西放在覆盖的 afterJob 方法中,

    @Override
    public void afterJob(JobExecution jobExecution) {
        .......
        .......
        .......
        .......    
        boolean zeroRead = true;
        for (StepExecution stepExecution : stepExecutions) {
        if (stepExecution.getReadCount() != 0) {
            zeroRead = false;
        }
        }
        if (zeroRead) {
        logger.info("***** JOB is FAILED because read count is Zero *****");
        jobExecution.setExitStatus(ExitStatus.COMPLETED);
        return;
        }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 2019-05-29
    • 2019-08-17
    • 2016-05-23
    • 1970-01-01
    • 2020-05-05
    相关资源
    最近更新 更多