Spring 批处理:跳过异常未按预期运行
Spring Batch: Skip Exception not behaving as expected
我已经在下面配置了我的 Spring 批处理应用程序:
<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 重试所有记录,包括重复项。我希望它丢弃该特定记录并插入其他记录。有办法实现吗?
因为您的异常是在提交间隔为 10 的编写器中抛出的,所以它会再次重试所有 10 条记录,因为它需要确定哪个记录抛出异常。一旦确定了记录,它将只跳过该记录并处理其他记录。
请参阅 this post。
对于任何感兴趣的人,我通过将 no-rollback-exception-classes
与 skip-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;
}
}
}
我已经在下面配置了我的 Spring 批处理应用程序:
<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 重试所有记录,包括重复项。我希望它丢弃该特定记录并插入其他记录。有办法实现吗?
因为您的异常是在提交间隔为 10 的编写器中抛出的,所以它会再次重试所有 10 条记录,因为它需要确定哪个记录抛出异常。一旦确定了记录,它将只跳过该记录并处理其他记录。
请参阅 this post。
对于任何感兴趣的人,我通过将 no-rollback-exception-classes
与 skip-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;
}
}
}