我正在编写一个Spring Batch流程来将数据集从一个系统迁移到另一个系统。在这种情况下,这就像使用RowMapper
实现在切换到ItemWriter
之前从查询构建对象一样简单。 ItemWriter
在我的DAO上调用save
方法(定义为接口并由spring数据处理)
问题是:我对MyItem表有一个唯一约束,因此保存重复记录将导致DataIntegrityViolationException
。我已经尝试在ItemWriter
内捕获它以允许我记录未导入记录,但是在执行期间它永远不会进入此catch语句。我试图抓住Exception
和Throwable
也无济于事。
从我注意到的内容中,有一个@Transactional
注释'保存'我的DAO的方法,我希望提交和刷新发生。 Spring Batch是否以任何方式改变了这个交易?这样@Transactional
注释适用于“写入”#39; 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配置
<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>
答案 0 :(得分:2)
这里有几点:
@Transactional
注释。 @Transactional
和Spring Batch通常不会很好。 Spring Batch将事务作为框架功能的一部分进行管理,并且尝试操作该功能可能会导致意外的副作用。ItemWriter
因此您的DAO正在参与Spring Batch正在管理的事务。因此,在事务提交之前,您不会得到该异常。考虑到上述考虑因素,您有两种选择:
SkipListener
,以便记录导致异常的项目。但是,使用此方法需要支付性能损失,因为抛出异常将导致事务被回滚并一次重放一个项目。ItemProcessor
过滤相关项目。这样可以节省跳过逻辑的性能损失。您可以在5.1.5节中阅读有关Spring Batch跳过逻辑的更多信息:http://docs.spring.io/spring-batch/trunk/reference/html/configureStep.html