Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用spring批处理读取具有关联的JPA实体_Java_Spring_Jpa_Spring Batch - Fatal编程技术网

Java 如何使用spring批处理读取具有关联的JPA实体

Java 如何使用spring批处理读取具有关联的JPA实体,java,spring,jpa,spring-batch,Java,Spring,Jpa,Spring Batch,我的任务是将数据从一个使用SpringDataJPA的“遗留”web应用程序迁移到一个更新的系统。我最初的想法是使用SpringBatch。我使用JpaPagingItemReader读取遗留实体,使用自定义ItemProcessor转换实体,使用ItemWriter通过http rest调用将数据发布到新系统 这些实体有很多一对多的关联。LegacyEntity与entityA有一对多关系,entityA与entityB有一对多关系 我的问题是JpaPagingItemReader是由jpql

我的任务是将数据从一个使用SpringDataJPA的“遗留”web应用程序迁移到一个更新的系统。我最初的想法是使用SpringBatch。我使用
JpaPagingItemReader
读取遗留实体,使用自定义
ItemProcessor
转换实体,使用
ItemWriter
通过http rest调用将数据发布到新系统

这些实体有很多一对多的关联。LegacyEntity与entityA有一对多关系,entityA与entityB有一对多关系

我的问题是JpaPagingItemReader是由jpql驱动的。我希望读者在所有关联都已完全加载的情况下输出每个LegacyEntity中的一个。我曾研究过在jpql中使用fetch连接,但它似乎不支持嵌套关联并发出重复项

最好的处理方法是什么?如果我使用的是普通的老jdbc,我将如何处理这个问题


Spring批处理读取器和处理器都专注于一次处理一条记录,只在后台使用分页,所以我通常如何在批处理中读取具有大量关联的对象?

通常您会使用驱动查询模式。您的
ItemReader
将读取ID(或最小实体)。然后,
ItemProcessor
将使用所需的任何其他内容来丰富项目。
ItemWriter
将拥有完整的实体来编写。您可以在这里的Spring批处理文档中阅读有关此模式的更多信息:

我用jdbc而不是jpa解决了这个问题

public class LegacyEntityReader extends JdbcPagingItemReader<LegacyEntity> {
private NamedParameterJdbcTemplate jdbcTemplate;

public LegacyEntityReader(DataSource dataSource, int pageSize) {
    //setup reader for loading legacyENtity without associations here
}

@Override
protected void doReadPage() {
    super.doReadPage();//this loads a page of root entities into a list exposed as a protected field: "results"
    List<Long> resultIds = results.stream().map(LegacyEntity::getId).collect(Collectors.toList());

    //DO queries to load associations here where legacyEntity.id in resultIds
    //Then associate in memory with the results in the results field
}
}
公共类LegacyEntityReader扩展JdbcPagingItemReader{
私有名称参数jdbcTemplate jdbcTemplate;
公共LegacyEntityReader(数据源数据源,int pageSize){
//设置读取器以在此处加载没有关联的legacyENtity
}
@凌驾
受保护的无效数据读取页(){
super.doReadPage();//这会将一页根实体加载到一个作为受保护字段公开的列表中:“results”
List resultitds=results.stream().map(LegacyEntity::getId).collect(Collectors.toList());
//在ResultId中的legacyEntity.id所在的位置执行查询以加载关联
//然后将内存中的结果与结果字段中的结果关联
}
}
不能使用JPA在一个使用分页的JPA查询中加载具有关联的实体。查询将不可避免地产生重复数据,并且需要在内存中的整个结果集上执行重复数据消除,这可能会导致内存不足错误


这让我很难过:(.

使用ETL工具进行一次传输,然后安排接下来的负载传输。我对JPA的了解越多,我就越意识到它从来没有打算处理带有复杂图形的大结果集的查询,而这些复杂图形永远不会被写回数据库。JPA在这方面非常出色“读一个东西,更新内存中的东西,将它保存到数据库中“Flowsb但是我得到了n+1查询问题。问题是itemProcessor一次只能处理一个项目。我真的希望能够在将项目发送到处理器之前在整个页面上进行更多的充实查询。另一种选择是,您的项目是一个聚合(例如
列表
)这将传递到
项目处理器
,然后您进行循环。答案正确,但我最终选择了另一条路线。请参见下面的答案