Spring Batch - 当JdbcPagingItemReader没有返回任何数据时如何完成作业

时间:2016-08-30 06:07:45

标签: spring-batch

我的问题与此existing SO question相反。

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

日志表明作业已标记为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 > ?))部分。

我的读者豆,

@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;
    }   

1 个答案:

答案 0 :(得分:1)

我无法确定自己是否记得,但我想,我在下面的步骤和工作监听器中做了。

我基本上写了一个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;
        }