" />

欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot查詢(xún)數(shù)據(jù)庫(kù)導(dǎo)出報(bào)表文件方式

 更新時(shí)間:2024年04月19日 15:36:12   作者:偷代碼的貓  
這篇文章主要介紹了SpringBoot查詢(xún)數(shù)據(jù)庫(kù)導(dǎo)出報(bào)表文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

一、背景

1、需求

幾千萬(wàn)條報(bào)表數(shù)據(jù)導(dǎo)出到Excel中

2、問(wèn)題

在數(shù)據(jù)量導(dǎo)出不大時(shí),我們的常規(guī)做法是使用MySQL直接查詢(xún)出全部數(shù)據(jù),整理規(guī)劃成Excel列表,使用POI寫(xiě)入到Excel文件中

但是當(dāng)數(shù)據(jù)量較大時(shí),使用MySQL查詢(xún)出所有數(shù)據(jù),一會(huì)超時(shí)斷開(kāi)連接,二會(huì)內(nèi)存溢出,使用POI暫時(shí)不支持分布寫(xiě)入數(shù)據(jù)到Excel中

3、解決

使用數(shù)據(jù)庫(kù)流式讀取可以解決數(shù)據(jù)庫(kù)讀取時(shí)間過(guò)長(zhǎng),內(nèi)存溢出問(wèn)題,這個(gè)解決了一次性讀取全部數(shù)據(jù)到內(nèi)存中

使用CSV文件代替xlsx/xls文件寫(xiě)入,CSV也可以使用Excel打開(kāi)操作,并且也可另存為xlsx/xls,CSV本質(zhì)是文本文件,不用確定尾結(jié)點(diǎn),可以如TXT一樣持續(xù)向文件追加內(nèi)容

二、代碼實(shí)現(xiàn)

1、mapper文件

使用Cursor游標(biāo)標(biāo)識(shí),流式查詢(xún)數(shù)據(jù)數(shù)據(jù)

  @Select("<script>"
      + "select * from `user_report`"
      + "</script>")
  Cursor<UserReport> selectCursorByCondition();

2、讀取寫(xiě)入文件

  • @Transactional(readOnly = true):搭配數(shù)據(jù)庫(kù)Cursor查詢(xún)使用,事務(wù)注解為只讀,保證數(shù)據(jù)整體的一致性
  • fieldArr:字段數(shù)組,規(guī)定要寫(xiě)入文件的字段項(xiàng),比如查詢(xún)的全部字段為a,b,c,d,而我只想顯示a,c,d
  • headerArr:字段名數(shù)組,對(duì)應(yīng)文件標(biāo)題欄,需要不字段數(shù)組a,c,d名稱(chēng)一一對(duì)應(yīng)
  • CsvUtils:一個(gè)簡(jiǎn)單的工具類(lèi),后續(xù)貼代碼
/**
   * 導(dǎo)出Excel
   * @param fieldArr       字段數(shù)組
   * @param headerArr      字段名數(shù)組
   * @param fileName       文件名
   */
  @Transactional(readOnly = true)
  public void exportList(HttpServletResponse response,
      String[] fieldArr, String[] headerArr, String fileName) {
    //設(shè)置文件格式
    response.setCharacterEncoding("UTF-8");
    response.addHeader("Content-Type", "application/csv");
    try {
       //文件名 設(shè)置為中文
      fileName = new String(fileName.getBytes("gb2312"), "iso8859-1");
    } catch (Exception e) {
      log.error("file name show error:{}", e.getMessage());
    }
    //響應(yīng)頭部
    response.addHeader("Content-Disposition", "attachment; filename=" + fileName + "(" +
        DateUtil.format(DateUtil.date(), DatePattern.NORM_DATETIME_PATTERN) + ").csv");
    //查詢(xún)數(shù)據(jù)
    Cursor<UserReport> modelStream = xxMapper.selectCursorByCondition();
 
    try {
      PrintWriter out = response.getWriter();
      try {
        //寫(xiě)入標(biāo)題行
        out.write(CsvUtils.getTitleLine(headerArr));
        //寫(xiě)入數(shù)據(jù)行
        modelStream.forEach(item -> {
          out.write(CsvUtils.getRowLine(fieldArr, item));
        });
        out.flush();
      } catch (Exception e) {
        log.error("write file error:{}", e.getMessage());
      } finally {
        out.close();
      }
    } catch (Exception e) {
      log.error("exportList error:{}", e.getMessage());
    }
 
 
  }

3、CsvUtils工具類(lèi)

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Set;
 
/**
 * @Author: catcoder
 * @Desc:
 * @Time: 10:05 2021/8/2
 **/
public class CsvUtils {
 
  /**
   * CSV文件列分隔符
   */
  public static final String CSV_COLUMN_SEPARATOR = ",";
 
  /**
   * CSV文件行分隔符
   */
  public static final String CSV_ROW_SEPARATOR = System.lineSeparator();
 
 
  /**
   * 獲取標(biāo)題行
   *
   * @param headerArr 標(biāo)題數(shù)組
   * @return
   */
  public static String getTitleLine(String[] headerArr) {
    StringBuffer line = new StringBuffer("");
    for (String title : headerArr) {
      line.append(title).append(CSV_COLUMN_SEPARATOR); //添加標(biāo)題行數(shù)據(jù)
    }
    line.append(CSV_ROW_SEPARATOR); //換行數(shù)據(jù)
    return line.toString();
  }
 
  /**
   * 或去數(shù)據(jù)行
   *
   * @param fieldArr 字段數(shù)組
   * @param obj      實(shí)體對(duì)象
   * @return
   */
  public static String getRowLine(String[] fieldArr, Object obj) {
    StringBuffer line = new StringBuffer("");
    Class<?> srcClass = obj.getClass();
 
    //獲取Obj 所有字段
    Set<String> objFiled = new HashSet<>();
    Field[] fields = obj.getClass().getDeclaredFields();
    for (Field field : fields) {
      objFiled.add(field.getName());
    }
 
    for (String field : fieldArr) {
      try {
        // 獲取對(duì)象對(duì)應(yīng)的Field
        if (objFiled.contains(field)) {
          Field objField = srcClass.getDeclaredField(field);
          objField.setAccessible(true); //設(shè)置private可訪(fǎng)問(wèn)
          Object value = objField.get(obj);
          line.append(value); //添加元素
        }
      } catch (Exception e) {
        e.printStackTrace();
      } finally {
        line.append(CSV_COLUMN_SEPARATOR); //CSV間隔數(shù)據(jù)
      }
    }
    line.append(CSV_ROW_SEPARATOR);//換行數(shù)據(jù)
    return line.toString();
  }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于java實(shí)現(xiàn)一個(gè)脫敏組件

    基于java實(shí)現(xiàn)一個(gè)脫敏組件

    這篇文章主要為大家詳細(xì)介紹了如何基于java實(shí)現(xiàn)一個(gè)脫敏組件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • Java詳解線(xiàn)上內(nèi)存暴漲問(wèn)題定位和解決方案

    Java詳解線(xiàn)上內(nèi)存暴漲問(wèn)題定位和解決方案

    本篇文章介紹了我在開(kāi)發(fā)過(guò)程中遇到的線(xiàn)上內(nèi)存暴漲的問(wèn)題,以及定位問(wèn)題原因和解決該問(wèn)題的過(guò)程及思路,通讀本篇對(duì)大家的學(xué)習(xí)或工作具有一定的價(jià)值,需要的朋友可以參考下
    2021-10-10
  • IDEA創(chuàng)建SpringBoot的五種方式

    IDEA創(chuàng)建SpringBoot的五種方式

    在軟件開(kāi)發(fā)的浩瀚海洋中,Spring?Boot以其獨(dú)特的魅力和強(qiáng)大的功能,為開(kāi)發(fā)者開(kāi)辟了一條通往高效、便捷開(kāi)發(fā)之路,本文旨在給大家介紹IDEA創(chuàng)建SpringBoot的五種方式,并通過(guò)代碼和圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • 詳解Java數(shù)據(jù)庫(kù)連接JDBC基礎(chǔ)知識(shí)(操作數(shù)據(jù)庫(kù):增刪改查)

    詳解Java數(shù)據(jù)庫(kù)連接JDBC基礎(chǔ)知識(shí)(操作數(shù)據(jù)庫(kù):增刪改查)

    這篇文章主要介紹了詳解Java數(shù)據(jù)庫(kù)連接JDBC基礎(chǔ)知識(shí)(操作數(shù)據(jù)庫(kù):增刪改查),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • Spring Boot讀取自定義配置文件

    Spring Boot讀取自定義配置文件

    在Spring Boot項(xiàng)目中我們經(jīng)常需要讀取application.yml配置文件的自定義配置,今天就來(lái)羅列一下從yaml讀取配置文件的一些常用手段和方法。
    2021-05-05
  • 一篇文章帶你了解Java基礎(chǔ)-接口

    一篇文章帶你了解Java基礎(chǔ)-接口

    這篇文章主要介紹了java接口基礎(chǔ)知識(shí),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • Java中數(shù)組越界異常的優(yōu)雅解決方式

    Java中數(shù)組越界異常的優(yōu)雅解決方式

    ?數(shù)組越界報(bào)錯(cuò)通常發(fā)生在嘗試訪(fǎng)問(wèn)數(shù)組中不存在的索引時(shí),這可能導(dǎo)致程序崩潰或異常,這篇文章主要給大家介紹了關(guān)于Java中數(shù)組越界異常的優(yōu)雅解決方式,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-07-07
  • Springboot項(xiàng)目因?yàn)閗ackson版本問(wèn)題啟動(dòng)報(bào)錯(cuò)解決方案

    Springboot項(xiàng)目因?yàn)閗ackson版本問(wèn)題啟動(dòng)報(bào)錯(cuò)解決方案

    這篇文章主要介紹了Springboot項(xiàng)目因?yàn)閗ackson版本問(wèn)題啟動(dòng)報(bào)錯(cuò)解決方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • java虛擬機(jī)指令dup詳解

    java虛擬機(jī)指令dup詳解

    這篇文章主要為大家詳細(xì)介紹了java虛擬機(jī)指令dup,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-10-10
  • Springboot異常日志輸出方式

    Springboot異常日志輸出方式

    這篇文章主要介紹了Springboot異常日志輸出方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評(píng)論