如何使用jpa分页将数据从32k行excel持久化到mysql数据库?

8iwquhpp  于 2021-07-07  发布在  Java
关注(0)|答案(1)|浏览(355)

我有一个大的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());
        }
    }
dphi5xsq

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之外,还有其他更适合这项工作的方法。有些数据库有非常高效的工具来加载平面文件。

相关问题