" />

亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

SpringBoot查詢數(shù)據(jù)庫導(dǎo)出報表文件方式

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

一、背景

1、需求

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

2、問題

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

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

3、解決

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

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

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

1、mapper文件

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

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

2、讀取寫入文件

  • @Transactional(readOnly = true):搭配數(shù)據(jù)庫Cursor查詢使用,事務(wù)注解為只讀,保證數(shù)據(jù)整體的一致性
  • fieldArr:字段數(shù)組,規(guī)定要寫入文件的字段項(xiàng),比如查詢的全部字段為a,b,c,d,而我只想顯示a,c,d
  • headerArr:字段名數(shù)組,對應(yīng)文件標(biāo)題欄,需要不字段數(shù)組a,c,d名稱一一對應(yīng)
  • CsvUtils:一個簡單的工具類,后續(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");
    //查詢數(shù)據(jù)
    Cursor<UserReport> modelStream = xxMapper.selectCursorByCondition();
 
    try {
      PrintWriter out = response.getWriter();
      try {
        //寫入標(biāo)題行
        out.write(CsvUtils.getTitleLine(headerArr));
        //寫入數(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工具類

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í)體對象
   * @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 {
        // 獲取對象對應(yīng)的Field
        if (objFiled.contains(field)) {
          Field objField = srcClass.getDeclaredField(field);
          objField.setAccessible(true); //設(shè)置private可訪問
          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é)

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

    Spring Boot讀取自定義配置文件

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

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

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

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

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

    Springboot項(xiàng)目因?yàn)閗ackson版本問題啟動報錯解決方案

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

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

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

    Springboot異常日志輸出方式

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

最新評論