我正在研究一个检查和更新Oracle数据库中数据的过程。我在我的应用程序中使用了hibernate和spring框架。
应用程序读取csv文件,处理内容,然后持久化实体:
public class Main() {
Input input = ReadCSV(path);
EntityList resultList = Process.process(input);
WriteResult.write(resultList);
...
}
// Process class that loops over input
public class Process{
public EntityList process(Input input) :
EntityList results = ...;
...
for(Line line : input.readLine()){
results.add(ProcessLine.process(line))
...
}
return results;
}
// retrieving and updating entities
Class ProcessLine {
@Autowired
DomaineRepository domaineRepository;
@Autowired
CompanyDomaineService companydomaineService
@Transactional
public MyEntity process(Line line){
// getcompanyByXX is CrudRepository method with @Query that returns an entity object
MyEntity companyToAttach = domaineRepository.getCompanyByCode(line.getCode());
MyEntity companyToDetach = domaineRepository.getCompanyBySiret(line.getSiret());
if(companyToDetach == null || companyToAttach == null){
throw new CustomException("Custom Exception");
}
// AttachCompany retrieves some entity relationEntity, then removes companyToDetach and adds CompanyToAttach. this updates relationEntity.company attribute.
companydomaineService.attachCompany(companyToAttach, companyToDetach);
return companyToAttach;
}
}
public class WriteResult{
@Autowired
DomaineRepository domaineRepository;
@Transactional
public void write(EntityList results) {
for (MyEntity result : results){
domaineRepository.save(result)
}
}
}
字符串
该应用程序在行数较少的文件上运行良好,但当我尝试处理大文件(200000行)时,性能急剧下降,并且我会得到SQL超时。我怀疑缓存问题,但我想知道在处理结束时保存所有实体是否不是一个坏的做法?
2条答案
按热度按时间cwdobuhd1#
对于你读的每一行,你在这里做了2次读操作
MyEntity companyToAttach = domaineRepository.getCompanyByCode(line.getCode()); MyEntity companyToDetach = domaineRepository.getCompanyBySiret(line.getSiret());
您可以读取多行并使用in查询,然后处理该公司列表
ybzsozfc2#
问题是for循环对结果进行单独保存,因此单个插入会减慢速度。Hibernate和Spring支持批量插入,并且应该在可能的情况下进行。
domaineRepository.saveAll(results)
由于您正在处理大量的数据,所以最好是分批处理,因此与其获取一个公司附加,您应该获取一个公司列表,以附加流程,然后获取一个公司列表,以分离和处理这些
字符串
上面的代码只是伪代码,为您指明正确的方向,需要找出适合您的方法。