Spring Batch SkipPolicy在处理异常时陷入无限循环

Posted

技术标签:

【中文标题】Spring Batch SkipPolicy在处理异常时陷入无限循环【英文标题】:Spring Batch SkipPolicy stuck in infinite loop when handling exception 【发布时间】:2020-11-09 23:45:20 【问题描述】:

使用自定义跳过策略处理在所有记录加载到数据库后引发的异常的 Spring 批处理作业。我的步骤看起来像......

    @Bean
    public Step trialBalanceLoadStep(JdbcBatchItemWriter<TrialBalance> trialBalanceWriter) throws ParseException 
        return stepBuilderFactory.get("trialBalanceLoadStep")
                .<TrialBalance, TrialBalance> chunk(1000)
                .reader(trialBalanceReader())
                .writer(trialBalanceWriter)
                .faultTolerant()
                .skipPolicy(new CustomSkipPolicy())
                .build();
    

我的 CustomSkipPolicy 类是...

public class CustomSkipPolicy implements SkipPolicy 

    @Override
    public boolean shouldSkip(Throwable throwable, int i) 
        if (throwable instanceof Exception) 
            return true;
        
        return false;
    

我处理异常只是为了测试目的。但是我看到的是 org.springframework.dao.DuplicateKeyException 被抛出。

此文件中没有重复项。请不要问。没有。我已经删除了整个文件。它们不存在。事实上,整个记录计数正在加载到数据库中。即使在这项工作失败后,如果我对表进行计数,我也会得到文件的整个记录​​数。所以这个异常是在所有记录都被加载之后抛出的。

仅当此表上存在特定索引时才会发生这种情况。创建索引是因为我们有一个实时进程查询该表,并且索引的查询运行时间明显更快。所以我们想保留索引。但同样,索引(可能会也可能不会导致问题)正在引发异常,现在我们的批量加载作业将无法运行。

所以我试图通过创建这个 CustomSkipPolicy 类来处理抛出的这个异常,但是当我这样做时它会处于无限循环中(如果我在我的 return 语句之前放置一个 println,它只会继续输出)

编辑 添加 schema 和 trialBalanceWriter

当我运行描述时...

Name                           Null?    Type         
------------------------------ -------- ------------ 
BAT_PROC_DT                    NOT NULL DATE         
ETL_TS                                  TIMESTAMP(6) 
PROC_APPL_CD                            VARCHAR2(3)  
FIRM_BNK_ID                    NOT NULL VARCHAR2(4)  
ACCT_NB                        NOT NULL VARCHAR2(15) 
ACCT_TYPE_CD                            VARCHAR2(2)  
CUST_ACCT_OWNR_SHRT_NM                  VARCHAR2(20) 
ACCT_CURR_BAL_AM                        NUMBER(15,2) 
ACCT_PROD_GP_CD                         VARCHAR2(3)  
SO_SCRTY_NB_ID                          NUMBER(9)    
ACCT_BR_ID                              NUMBER(7)    
ACCT_OPN_DT                             DATE         
CHK_OR_SV_LFCYC_STS_CD                  VARCHAR2(2)  
ACC_ROLL_12MO_OD_INSTN_CN               NUMBER(3)    
CHK_OR_SVACC_RCNCL_TXN_TYPE_CD          VARCHAR2(1)  
ACC_SRVC_FEE_BILL_SYS_CD                CHAR(1)      
CHK_OR_SVACC_LOB_CD                     VARCHAR2(3)  
CHK_OR_SVACC_LOB_OWNR_CD                VARCHAR2(2)  
CHK_ACCT_PSTV_PAY_IN                    CHAR(1)      
CHK_OR_SVACC_OD_TXN_PYMT_CD             CHAR(1)      
ACC_LAST_DAY_TOT_DEP_AM                 NUMBER(13)   
PRNT_ACCT_NB                            NUMBER(15)   
CARD_ACCT_NB                            NUMBER(17)   
CHK_OR_SVACC_OD_AM                      NUMBER(11)   
ACC_MO_TO_DT_OD_INSTN_DAY_CN            NUMBER(3)    
CHK_OR_SVACC_OD_PRTC_CD                 CHAR(1)      
CHK_OR_SVACC_OD_LAST_2PRTC_CD           CHAR(1)      
CHK_OR_SVACC_OD_LAST_3PRTC_CD           CHAR(1)      
CHK_OR_SVACC_LAST_MNTR_ACTV_DT          DATE         
CHK_OR_SVACC_LAST_DEP_DT                DATE         
CHK_OR_SVACC_MOST_RCNT_OD_DT            DATE         
STOP_PYMT_CD                            CHAR(1)      
CNTPR_TYPE_CD                           VARCHAR2(2)  
RISK_AVD_CD                             CHAR(1)      
RET_MAIL_STS_CD                         CHAR(1)      
AUTM_CLR_HS_IN                          CHAR(1)      
FED_TAX_WHLD_CD                         VARCHAR2(2)  
LAST_OD_DSPN_CD                         NUMBER(1)    
ACC_CAL_MO_TO_DT_ALB_AM                 NUMBER(15,2) 
ACC_MO_TO_DT_OD_INSTN_CN                NUMBER(3)    
ACCT_MO_TO_DT_RET_ITEM_CN               NUMBER(3)    
ACCT_MO_TO_DT_NSF_ITEM_CN               NUMBER(3)    
ACCT_CTL_DISB_CD                        CHAR(1)      
ACC_ROLL_12MO_AVG_COLL_BAL_AM           NUMBER(13)   
ACC_ROLL_12MO_OD_INSTN_DAY_CN           NUMBER(3)    
ACCT_ROLL_12MO_NSF_ITEM_CN              NUMBER(3)    
ACC_12MO_NSF_PTNL_RET_ITEM_CN           NUMBER(5)    
ACCT_ROLL_12MO_RET_ITEM_CN              NUMBER(3)    
CHK_OR_SVACC_OPN_DT                     DATE         
ACC_OD_PRTC_AVAL_FUND_AM                NUMBER(15,2) 
DBCD_LAST_CHRG_DT                       DATE         
CHK_OR_SVACC_PRC_RGN_NB                 NUMBER(5)    
DEP_ACCT_FUND_PRPS_CD                   CHAR(1)      
CHK_OR_SVACC_OD_PRTC_PROD_CD            NUMBER(1)    
UNVS_PROD_CAT_CD                        VARCHAR2(4)  
SGNTR_RVW_THLD_AM                       NUMBER(9)    
TXN_MIN_SGNTR_CN                        NUMBER(1)    
ACH_DEP_LTST_DT                         DATE         
TELR_BLK_TXN_TYPE_CD                    CHAR(1)      
PRVT_BNK_REL_CD                         CHAR(1)      
CHK_OR_SV_AVAL_BAL_AM                   NUMBER(15,2) 
CHK_OR_SVACC_COLL_BAL_AM                NUMBER(15,2) 
DDA_PNDG_HARD_HOLD_AM                   NUMBER(15,2) 
RCNT_CYC_CR_AM                          NUMBER(15,2) 
RCNT_CYC_DR_AM                          NUMBER(15,2) 
ACCT_PRPS_CD                            VARCHAR2(2)  
PYMT_FUND_SRC_CD                        VARCHAR2(2)  
CHK_ACCT_CHK_ENCST_CD                   CHAR(1)      
ACCT_ROLL_12MO_ALB_AM                   NUMBER(13)   
ACCT_ACTV_CD                            CHAR(1)      
OV_DRFT_PRTC_ACCT_NB                    NUMBER(15)   
OV_DRFT_PRTC_ACCT_LNK_DT                DATE         
ACCT_CLSE_DT                            DATE         
STOP_NOTE_IN                            CHAR(1)      
RCNT_CYC_CR_ITEM_CN                     NUMBER(7)    
RCNT_CYC_DR_ITEM_CN                     NUMBER(7)    
ADDL_WDRW_FEE_WVE_IN                    CHAR(1)      
ACCT_CLSE_SPRS_CD                       CHAR(1)      
ACCT_RCNT_ACTV_DT                       DATE         
GL_CC_NB                                NUMBER(7)    
ACCT_LAST_CNTC_DT                       DATE         
CHK_OR_SVACC_OD_DAY_CN                  NUMBER(3)    
UNVS_PROD_FAM_CD                        VARCHAR2(4)  

trialBalanceWriter 如下...

    @Bean
    public JdbcBatchItemWriter<TrialBalance> trialBalanceWriter(final DataSource dataSource) 
        return new JdbcBatchItemWriterBuilder<TrialBalance>()
                .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
                .sql(Constants.trialBalanceInsertStatement)
                .assertUpdates(false)
                .dataSource(dataSource)
                .build();
    

【问题讨论】:

【参考方案1】:

主键列有问题,要么包含 NULL,要么它的值(pk 列,而不是记录本身)不是唯一的。

之所以在添加完所有记录后抛出它,很可能是因为此时事务已提交。

【讨论】:

这更多的是评论而不是答案。请不要只为一些想法创建答案 如果文件中只有 10 条记录,就会发生这种情况。我明显看到没有主键重复。即使我要使用重复的主键创建一列,也会引发此异常,而不是在加载记录的末尾。在提交那批记录后抛出它。 @BrianCode 你介意添加架构甚至可能是 trialBalanceWriter 吗? @Stefan 刚刚用这两个编辑。你想要一个表的模式?这就是我发布的内容

以上是关于Spring Batch SkipPolicy在处理异常时陷入无限循环的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring-boot 上将 Spring Batch 与 spring-batch-admin-manager 集成时出错

Spring-batch:如何在 Spring Batch 中使用 skip 方法捕获异常消息?

spring batch ftp 集成超时错误 - 使用 spring-boot/spring-batch 进行 ETL

陪你解读Spring Batch带你入手Spring Batch

Spring boot spring.batch.job.enabled=false 无法识别

Spring boot spring.batch.job.enabled=false 无法识别