在春季批次的ItemWriter中无法捕获异常
我正在编写一个Spring批处理过程来将数据集从一个系统迁移到另一个系统。在本例中,这与使用RowMapper
实现在将对象移交给ItemWriter
之前从查询构建对象一样简单。ItemWriter
调用我的DAO上的save
方法(定义为接口,由Spring数据处理)
DataIntegrityViolationException
。我曾尝试在ItemWriter
中捕获它,以允许我记录没有导入记录,但是在执行过程中,它从未进入该catch语句。我也曾尝试捕获Exception
和Throwable
,但都无济于事。
据我所知,在我的DAO的"save"方法上有一个@Transactional
注释,我希望在其中发生提交和刷新。Spring Batch会以任何方式改变这个事务吗?以便@Transactional
批注应用于ItemWriter
?
我甚至可以捕获此类中的异常吗?
我在下面提供了代码片段,如果您需要更多信息,请让我知道。
非常感谢您能提供的任何帮助
ItemWriter
@Component
public class MyItemWriter implements ItemWriter<MyItem> {
private static final Logger LOG = LoggerFactory.getLogger(MyItemWriter.class);
@Resource
private MyItemDao myItemDao;
@Override
public void write(List<? extends MyItem> myItems) throws Exception {
for (MyItem myItem : myItems) {
try {
myItemDao.save(myItem);
} catch (Throwable ex) {
LOG.warn("Failed to import MyItem: {}: {} ", myItem.getId(), ex.toString());
}
}
}
}
DAO
public interface MyItemDao extends PagingAndSortingRepository<MyItem, Integer> {
[Custom methods omitted]
}
Spring批量配置
<batch:job id="myImportJob" restartable="true" job-repository="jobRepository">
<batch:step id="myImportStep" allow-start-if-complete="true">
<batch:tasklet>
<batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="50" />
</batch:tasklet>
</batch:step>
</batch:job>
解决方案
这里有几点:
- 删除DAO上的
@Transactional
批注。@Transactional
和Spring Batch通常玩得不好。Spring Batch将事务作为框架功能的一部分进行管理,尝试操作该功能可能会导致意想不到的副作用。 - 正如M.Deinum所指出的,您的
ItemWriter
,因此您的DAO正在参与Spring Batch管理的事务。因此,在事务提交之前,您不会获得该异常。
考虑上述因素后,您有两个选择:
- 您可以配置跳过逻辑以跳过引发该异常的记录。如果您需要记录项目,可以将
SkipListener
添加到混合中,以便记录导致异常的项目。但是,此方法需要付出性能损失,因为抛出异常将导致事务回滚并一次重放一个项目。 - 您可以通过
ItemProcessor
对商品进行过滤点评。这可节省跳过逻辑的性能影响。
您可以在5.1.5节中阅读有关Spring Batch跳过逻辑的更多信息:http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html
相关文章