" />

最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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é)點,可以如TXT一樣持續(xù)向文件追加內(nèi)容

二、代碼實現(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ī)定要寫入文件的字段項,比如查詢的全部字段為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      實體對象
   * @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)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Seata?AT模式啟動過程圖文示例詳解

    Seata?AT模式啟動過程圖文示例詳解

    這篇文章主要為大家介紹了Seata?AT模式啟動過程圖文示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • Java實現(xiàn)飛機大戰(zhàn)游戲?附完整源碼

    Java實現(xiàn)飛機大戰(zhàn)游戲?附完整源碼

    這篇文章主要介紹了Java實現(xiàn)飛機大戰(zhàn)游戲,本文給大家分享完整源代碼和效果圖展示,對java飛機大戰(zhàn)游戲?qū)崿F(xiàn)代碼感興趣的朋友一起看看吧
    2022-05-05
  • Spring mvc整合mybatis(crud+分頁插件)操作mysql

    Spring mvc整合mybatis(crud+分頁插件)操作mysql

    這篇文章主要介紹了Spring mvc整合mybatis(crud+分頁插件)操作mysql的步驟詳解,需要的朋友可以參考下
    2017-04-04
  • Mybatis調(diào)用SQL?Server存儲過程的實現(xiàn)示例

    Mybatis調(diào)用SQL?Server存儲過程的實現(xiàn)示例

    在軟件開發(fā)過程中,經(jīng)常會使用到存儲過程,本文就來介紹一下Mybatis調(diào)用SQL?Server存儲過程的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • springboot自定義Starter的具體流程

    springboot自定義Starter的具體流程

    這篇文章主要介紹了springboot自定義Starter的具體流程,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-09-09
  • Java插入排序算法實現(xiàn)方法例子

    Java插入排序算法實現(xiàn)方法例子

    所謂排序,是將一組數(shù)據(jù)按照特定順序重新排列的過程,穩(wěn)定排序算法中相同鍵值的元素排序后保持原有順序,直接插入排序和希爾排序是插入排序的兩種形式,這篇文章主要介紹了Java插入排序算法實現(xiàn)的相關(guān)資料,需要的朋友可以參考下
    2024-10-10
  • Java反射與Fastjson的危險反序列化詳解

    Java反射與Fastjson的危險反序列化詳解

    在?Java?中,Computer.class是一個引用,它表示了?Computer?的字節(jié)碼對象(Class對象),這個對象被廣泛應(yīng)用于反射、序列化等操作中,那么為什么?parseObject?需要這個引用呢,帶著這個問題我們一起通過本文學(xué)習(xí)下吧
    2024-07-07
  • SpringBoot接口或方法進行失敗重試的實現(xiàn)方式

    SpringBoot接口或方法進行失敗重試的實現(xiàn)方式

    為了防止網(wǎng)絡(luò)抖動,影響我們核心接口或方法的成功率,通常我們會對核心方法進行失敗重試,如果我們自己通過for循環(huán)實現(xiàn),會使代碼顯得比較臃腫,所以本文給大家介紹了SpringBoot接口或方法進行失敗重試的實現(xiàn)方式,需要的朋友可以參考下
    2024-07-07
  • win7 64位系統(tǒng)JDK安裝配置環(huán)境變量教程

    win7 64位系統(tǒng)JDK安裝配置環(huán)境變量教程

    這篇文章主要為大家詳細(xì)介紹了win7 64位系統(tǒng)JDK安裝配置環(huán)境變量教程,感興趣的小伙伴們可以參考一下
    2016-06-06
  • java設(shè)計模式之外觀模式學(xué)習(xí)筆記

    java設(shè)計模式之外觀模式學(xué)習(xí)筆記

    這篇文章主要為大家詳細(xì)介紹了java設(shè)計模式之外觀模式學(xué)習(xí)筆記,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-10-10

最新評論

庆元县| 南华县| 寿阳县| 政和县| 苏州市| 炉霍县| 固阳县| 望城县| 杨浦区| 宜宾市| 裕民县| 胶州市| 青川县| 普兰店市| 翁牛特旗| 开远市| 山丹县| 沂南县| 屏山县| 盈江县| 汉源县| 全州县| 博兴县| 台州市| 吉安县| 临江市| 江城| 太仓市| 峨山| 华蓥市| 南京市| 开原市| 遂宁市| 福州市| 东光县| 梧州市| 环江| 清苑县| 巴彦淖尔市| 宜阳县| 铅山县|