我有一个大的excel文件,有32k行,还有一个javaspring代码将excel数据持久化到mysql数据库。我的代码适用于大约6k行,但由于jpa的限制,不能适用于整个excel。我读到可以用jpa分页来完成,但到目前为止,我只找到了从db收集数据(已经用数据持久化)并呈现到ui的信息。excel文件包含32k个药品,这些行将被保存到db中。
我使用以下方法创建此控制器层:
public ResponseEntity<ResponseMessage> uploadFile(@RequestParam("file") MultipartFile file,
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "6000") int size) {
String message = "";
if (ExcelHelper.hasExcelFormat(file)) {
try {
// the following 6 row are my patetic attempt to resolve with pagination
List<Medicine> medicines = new ArrayList<>();
Pageable paging = PageRequest.of(page, size);
Page<Medicine> pageMedicamente = medicineRepositoryDao.save(paging);
medicines = pageMedicamente.getContent();
medicineService.save(file);
message = "Uploaded the file successfully: " + file.getOriginalFilename();
return ResponseEntity.status(HttpStatus.OK).body(new ResponseMessage(message));
} catch (Exception e) {
message = "Could not upload the file: " + file.getOriginalFilename() + "!";
return ResponseEntity.status(HttpStatus.EXPECTATION_FAILED).body(new ResponseMessage(message));
}
}
以及存储库层:
@Repository
public interface MedicineRepositoryDao extends JpaRepository<Medicine, Long> {
Page<Medicine> save( Pageable pageable);
}
以及服务层:
try {
List<Medicine> medicines = ExcelHelper.excelToMedicine(file.getInputStream());
medicineRepositoryDao.saveAll(medicines);
} catch (IOException e) {
throw new RuntimeException("fail to store excel data: " + e.getMessage());
}
}
1条答案
按热度按时间dphi5xsq1#
我觉得你有一些想法。
我不认为spring对您可能在这里保留的行数有任何相关的限制。但jpa有。jpa不保留对您保存在其一级缓存中的任何实体的引用。因此,对于大量的行/实体,这会占用内存,并且会使某些操作变得更慢,因为实体会被逐个查找或处理。
分页是用于读取实体,而不是用于保存。
在这种情况下你有几个选择。
不要使用jpa。对于简单地从文件中写入数据并将其写入数据库来说,jpa几乎没有任何好处。这几乎可以通过使用
JdbcTemplate
或者NamedParameterJdbcTemplate
而且会快得多,因为jpa的开销被跳过了,在这个场景中,您无论如何都不会从中受益。如果您想使用orm,您可能想看看spring数据jdbc,它在概念上更简单,不保留对实体的引用,因此在这个场景中应该显示更好的特性。我建议不要在这里使用orm,因为您似乎没有从拥有实体中获益,所以创建实体然后让orm从中提取数据确实是浪费时间。把你的进口分成几批。这意味着,在继续下一个1000行之前,要持久化(例如,一次保存1000行),将它们写入数据库并提交事务。对于jpa来说,出于上述原因,这几乎是必要的。使用jdbc(即。
JdbcTemplate
&co)这对于32k行可能不是必需的,但可能会提高性能,并且在插入失败时有助于恢复。springbatch将帮助您实现这一点。虽然前面的一点讨论的是批处理,即将导入分解成块,但是您还应该研究jdbc端的批处理,在jdbc端,您可以将多个语句,或者一个包含多组参数的语句一次性发送到数据库,这同样可以提高性能。
最后,除了javaverse之外,还有其他更适合这项工作的方法。有些数据库有非常高效的工具来加载平面文件。