【问题标题】:Spring Batch: Skip Exception not behaving as expectedSpring Batch:跳过异常未按预期运行
【发布时间】:2020-04-04 00:31:43
【问题描述】:

我在下面配置了我的 Spring Batch 应用程序:

<batch:job id="mPortRiskJob">
    <batch:step id="mPortRiskStep">
        <tasklet throttle-limit="10">
           <chunk reader="MPortRiskReader"  processor="MPortRiskProcessor" writer="MPortRiskWriter" commit-interval="10"
            skip-limit="1">
               <batch:skippable-exception-classes>
                   <include class="com.common.exception.ERDException"/>
               </batch:skippable-exception-classes>
           </chunk>
            <batch:no-rollback-exception-classes>
                <include class="com.common.exception.ERDException"/>
            </batch:no-rollback-exception-classes>
        </tasklet>
    </batch:step>   
    <batch:listeners>
        <batch:listener ref="MJobExecutionListener"/>
    </batch:listeners>    
</batch:job>

在我的作者中,我有一个将记录插入数据库的 for 循环。代码如下:

for (String id : keylist) {
  try {
      insertRecord(id);
  } catch (Exception e) {
      throw new ERDException("Failure in write method", e);
  }
}

我想要的是,例如,如果第一条记录抛出DuplicateKeyException,则该记录将被跳过,并插入下一条记录。发生的事情是,当ERDException 被抛出时,Spring Batch 会重试所有记录,包括重复记录。我希望它丢弃该特定记录并插入其他记录。有没有办法做到这一点?

【问题讨论】:

    标签: spring-batch


    【解决方案1】:

    对于任何感兴趣的人,我通过将no-rollback-exception-classesskip-policy 结合起来解决了我的问题!我在定义自己的跳过策略时可能有点过火了——开箱即用的 Spring 策略之一就可以了。见下文:

    <bean id="skipPolicy" class="com.trp.erd.batch.ERDSkipPolicy">
    
    <batch:job id="midrPortRiskJob">
        <batch:step id="midrPortRiskStep">
            <tasklet throttle-limit="10">
               <chunk reader="MIDRPortRiskReader"  processor="MIDRPortRiskProcessor" writer="MIDRPortRiskWriter" commit-interval="10"
                skip-limit="1" skip-policy="skipPolicy">
                   <batch:skippable-exception-classes>
                       <include class="com.trp.erd.common.exception.ERDException"/>
                   </batch:skippable-exception-classes>
               </chunk>
                <batch:no-rollback-exception-classes>
                    <include class="com.trp.erd.common.exception.ERDException"/>
                </batch:no-rollback-exception-classes>
            </tasklet>
        </batch:step>   
        <batch:listeners>
            <batch:listener ref="MIDRJobExecutionListener"/>
        </batch:listeners>    
    </batch:job>
    

    以及跳过策略的实施:

    public class ERDSkipPolicy implements SkipPolicy {
    
        @Override
        public boolean shouldSkip(Throwable t, int skipCount) {
            if (t instanceOf ERDException) {
                return true;
            }
        }    
    }
    

    【讨论】:

      【解决方案2】:

      好吧,由于您的异常在提交间隔为 10 的写入器中引发,因此它再次重试所有 10 条记录,因为它需要确定哪个记录引发异常。一旦确定了记录,它将跳过该记录并处理其他记录。

      请参阅this 帖子。

      【讨论】:

      • 这是否意味着我的跳过限制也应该是 10?我希望它只尝试一次,这就是我将限制设置为 1 的原因。
      • 没有。对于作家来说,它会尝试两次。你无能为力。但它不应该尝试超过两次。
      • 写我自己的 SkipListener 能帮我实现我想要的吗?
      猜你喜欢
      • 1970-01-01
      • 2014-04-26
      • 1970-01-01
      • 2021-02-04
      • 1970-01-01
      • 2017-11-18
      • 1970-01-01
      • 1970-01-01
      • 2019-04-09
      相关资源
      最近更新 更多