当前位置: 首页 > 知识库问答 >
问题:

Spring Boot通过RESTendpoint将大型数据库导出到csv

尉迟宣
2023-03-14

我需要构建一个Spring Boot应用程序,它公开一个RESTendpoint,以将一个巨大的数据库表导出为具有不同过滤器参数的CSV文件。我正试图找到一个有效的解决这个问题的办法。

目前,我使用spring数据jpa查询数据库表,该表返回POJO列表。然后使用Apache Commons CSV将此列表作为CSV文件写入HttpServletResponse。这种方法有几个问题。首先,它将所有数据加载到内存中。其次,速度很慢。

我没有对数据进行任何业务逻辑,在这种情况下是否需要使用jpa和实体(POJO)。我觉得这就是造成问题的地方。

共有2个答案

邹博裕
2023-03-14

首先从DataBuffer创建控制器Flux:


@GetMapping(path = "/report/detailReportFile/{uid}" ,  produces = "text/csv")

public Mono<Void> getWorkDoneReportDetailSofkianoFile (@PathVariable(name = "uid") String uid,
                                                       @RequestParam(name = "startDate", required = false, defaultValue = "0") long start,
                                                       @RequestParam(name = "endDate" , required = false, defaultValue = "0") long end,
                                                       ServerHttpResponse response) {

    var startDate = start == 0 ? GenericData.GENERIC_DATE : new Date(start);

    var endDate = end == 0 ? new Date() : new Date(end);

    response.getHeaders().set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename="+uid+".csv");
    response.getHeaders().add("Accept-Ranges", "bytes");

    Flux<DataBuffer> df = queryWorkDoneUseCase.findWorkDoneByIdSofkianoAndDateBetween(uid, startDate, endDate).collectList()
            .flatMapMany(workDoneList -> WriteCsvToResponse.writeWorkDone(workDoneList));

    return response.writeWith(df);
}

现在必须创建DataBuffer,在我的示例中,使用带有StringBuffer的opencsv创建它

public static Flux<DataBuffer> writeWorkDone(List<WorkDone> workDoneList) {

        try {
            StringWriter writer = new StringWriter();

            ColumnPositionMappingStrategy<WorkDone> mapStrategy = new ColumnPositionMappingStrategy<>();

            mapStrategy.setType(WorkDone.class);

            String[] columns = new String[]{"idSofkiano", "nameSofkiano","idProject", "nameProject", "description", "hours", "minutes", "type"};
            mapStrategy.setColumnMapping(columns);

            StatefulBeanToCsv<WorkDone> btcsv = new StatefulBeanToCsvBuilder<WorkDone>(writer)
                    .withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
                    .withMappingStrategy(mapStrategy)
                    .withSeparator(',')
                    .build();

            btcsv.write(workDoneList);

            return Flux.just(stringBuffer(writer.getBuffer().toString()));

        } catch (CsvException ex) {

            return Flux.error(ex.getCause());
        }
    }


    private static DataBuffer stringBuffer(String value) {
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);

        NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
        DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
        buffer.write(bytes);
        return buffer;
    }

庄飞
2023-03-14

您可以尝试Spring 5:https://www.baeldung.com/spring-webflux中引入的新SpringWebFlow

 类似资料:
  • 问题内容: 我想通过php将MYSQL数据导出到Excel / CSV。这样我以后可以使用我的数据库,或者有人可以使用和理解它。 问题答案: 我想这就是你要找的 您可以通过检查以下地址来创建自己的文件:http : //www.programmingfacts.com/export-mysql-data-into- excelcsv-via-php/ 我不能在这里添加工作代码,这是错误的= / 但

  • 我有一个独立的H2服务器,正在收集数据。为了进行测试,我希望将数据从服务器中提取到CSV文件中。有什么工具吗?

  • 问题内容: 如何在MAMP上导出/导入大型数据库?使用PHPMyAdmin无法正常工作。 问题答案: 应该通过如下所示的终端来完成。 在终端中,使用以下命令导航到MAMP的文件夹 使用此命令导出文件。EG将是 行应该出现在说。在这里输入MySQL密码。请记住,这些字母不会出现,但是它们在那里。 如果需要导入,请使用BigDump,这是一个MySQL Dump Importer。

  • 问题内容: 我想通过可手动运行以更新数据的PHP脚本将表格从CSV文件导入SQLite DB。 以下是我要实现的目标的列表: 将旧表(称为“ produkte”)重命名为product-currentdate(或删除表) 然后从CSV文件导入文件(分隔并使用ISO 8859-1字符集/ CSV文件的第一行包含表标题) 将日期保存在表“产品”中 我发现了一个由于某种原因无法运行的脚本: 我希望有人知

  • 同样地,为需要存储数据的每个JPA实体创建单独的存储库类是否理想?或者有什么更好的方法可以在有限的存储库类的情况下将数据存储到数据库?

  • 问题内容: 我一直在尝试通过phpMyAdmin导入数据库。我的数据库文件是,它的大小是1.2 GB,我正在尝试将其导入本地,并且phpMyAdmin表示: 您可能试图上传太大的文件。请参阅文档以了解解决此限制的方法。 请帮助我,我真的需要这个工作。 问题答案: 这是由于PHP对上传文件具有文件大小限制。 如果您具有终端机/外壳程序访问权限,则以上答案@Kyotoweb将起作用。 一种实现方法是创