首页  编辑  

Java实现海量数据导出不爆内存

Tags: /Java/   Date Created:
SpringBoot实现MySQL百万级数据量导出并避免OOM的解决方案-电子发烧友网 (elecfans.com)
1. 海量数据导出,不能使用Excel,Excel最多也就支持100万条左右的数据,超过后Excel打不开或者文件支持不了。
核心注解如下,需要加入到具体的 Repository 之上。方法的返回类型定义成Stream。Integer.MIN_VALUE 告诉 jdbc driver 逐条返回数据。
@QueryHints(value=@QueryHint(name=HINT_FETCH_SIZE,value=""+Integer.MIN_VALUE))
@Query(value="selecttfromTodot")
StreamstreamAll();

此外还需要在Stream处理数据的方法之上添加

@Transactional(readOnly = true)

保证事务是只读的。同时需要注入javax.persistence.EntityManager,通过detach从内存中移除已经使用后的对象。

@RequestMapping(value="/todos.csv",method=RequestMethod.GET)
@Transactional(readOnly=true)
publicvoidexportTodosCSV(HttpServletResponseresponse){
    response.addHeader("Content-Type","application/csv");
    response.addHeader("Content-Disposition","attachment;filename=todos.csv");
    response.setCharacterEncoding("UTF-8");
    try(StreamtodoStream=todoRepository.streamAll()){
        PrintWriterout=response.getWriter();
        todoStream.forEach(rethrowConsumer(todo->{
            Stringline=todoToCSV(todo);
            out.write(line);
            out.write("");
            entityManager.detach(todo);
        }));
        out.flush();
    } catch(IOExceptione){
        log.info("Exceptionoccurred"+e.getMessage(),e);
        thrownewRuntimeException("Exceptionoccurredwhileexportingresults",e);
    }
}