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