溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

發(fā)布時(shí)間:2021-11-17 11:56:11 來源:億速云 閱讀:141 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

先不談技術(shù),先看效果,(完整案例代碼文末提供)

數(shù)據(jù)庫為mysql(理論上此套方案支持任何結(jié)構(gòu)化數(shù)據(jù)庫),準(zhǔn)備一張測試表t_person。表結(jié)構(gòu)如下:

CREATE TABLE `t_person` (
  `id` bigint(20) NOT NULL auto_increment,
  `name` varchar(20) default NULL,
  `age` int(11) default NULL,
  `address` varchar(50) default NULL,
  `mobile` varchar(20) default NULL,
  `email` varchar(50) default NULL,
  `company` varchar(50) default NULL,
  `title` varchar(50) default NULL,
  `create_time` datetime default NULL,
  PRIMARY KEY  (`id`)
);

一共9個(gè)字段。我們先創(chuàng)建測試數(shù)據(jù)。

案例代碼提供了一個(gè)簡單的頁面,點(diǎn)以下按鈕一次性可以創(chuàng)建5w條測試數(shù)據(jù):

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

這里我連續(xù)點(diǎn)了4下,很快就生成了20w條數(shù)據(jù),這里為了展示下數(shù)據(jù)的大致樣子,我直接跳轉(zhuǎn)到了最后一頁

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

然后點(diǎn)開下載大容量文件,點(diǎn)擊執(zhí)行執(zhí)行按鈕,開始下載t_person這張表里的全部數(shù)據(jù)

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

點(diǎn)擊執(zhí)行按鈕之后,點(diǎn)下方刷新按鈕,可以看到一條異步下載記錄,狀態(tài)是P,表示pending狀態(tài),不停刷新刷新按鈕,大概幾秒后,這一條記錄就變成S狀態(tài)了,表示Success

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

然后你就可以下載到本地,文件大小大概31M左右

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

看到這里,很多童鞋要疑惑了,這下載下來是csv?csv其實(shí)是文本文件,用excel打開會(huì)丟失格式和精度。這解決不了問題啊,我們要excel格式啊??!

其實(shí)稍微會(huì)一點(diǎn)excel技巧的童鞋,可以利用excel導(dǎo)入數(shù)據(jù)這個(gè)功能,數(shù)據(jù)->導(dǎo)入數(shù)據(jù),根據(jù)提示一步步,當(dāng)中只要選擇逗號分隔就可以了,關(guān)鍵列可以定義格式,10秒就能完成數(shù)據(jù)的導(dǎo)入

用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)

你只要告訴運(yùn)營小姐姐,根據(jù)這個(gè)步驟來完成excel的導(dǎo)入就可以了。而且下載過的文件,還可以反復(fù)下。

是不是從本質(zhì)上解決了下載大容量數(shù)據(jù)集的問題?

原理和核心代碼

學(xué)弟聽到這里,很興奮的說,這套方案能解決我這里的痛點(diǎn)??旌臀艺f說原理。

其實(shí)這套方案核心很簡單,只源于一個(gè)知識點(diǎn),活用JdbcTemplate的這個(gè)接口:

@Override
public void query(String sql, @Nullable Object[] args, RowCallbackHandler rch) throws DataAccessException {
  query(sql, newArgPreparedStatementSetter(args), rch);
}

sql就是select * from t_personRowCallbackHandler這個(gè)回調(diào)接口是指每一條數(shù)據(jù)遍歷后要執(zhí)行的回調(diào)函數(shù)?,F(xiàn)在貼出我自己的RowCallbackHandler的實(shí)現(xiàn)

private class CsvRowCallbackHandler implements RowCallbackHandler{

    private PrintWriter pw;

    public CsvRowCallbackHandler(PrintWriter pw){
        this.pw = pw;
    }

    public void processRow(ResultSet rs) throws SQLException {
        if (rs.isFirst()){
            rs.setFetchSize(500);
            for (int i = 0; i < rs.getMetaData().getColumnCount(); i++){
                if (i == rs.getMetaData().getColumnCount() - 1){
                    this.writeToFile(pw, rs.getMetaData().getColumnName(i+1), true);
                }else{
                    this.writeToFile(pw, rs.getMetaData().getColumnName(i+1), false);
                }
            }
        }else{
            for (int i = 0; i < rs.getMetaData().getColumnCount(); i++){
                if (i == rs.getMetaData().getColumnCount() - 1){
                    this.writeToFile(pw, rs.getObject(i+1), true);
                }else{
                    this.writeToFile(pw, rs.getObject(i+1), false);
                }
            }
        }
        pw.println();
    }

    private void writeToFile(PrintWriter pw, Object valueObj, boolean isLineEnd){
        ...
    }
}

這個(gè)CsvRowCallbackHandler做的事就是每次從數(shù)據(jù)庫取出500條,然后寫入服務(wù)器上的本地文件中,這樣,無論你這條sql查出來是20w條還是100w條,內(nèi)存理論上只占用500條數(shù)據(jù)的存儲空間。等文件寫完了,我們要做的,只是從服務(wù)器把這個(gè)生成好的文件download到本地就可以了。

因?yàn)閮?nèi)存中不斷刷新的只有500條數(shù)據(jù)的容量,所以,即便多線程下載的環(huán)境下。內(nèi)存也不會(huì)因此而溢出。這樣,完美解決了多人下載的場景。

當(dāng)然,太多并行下載雖然不會(huì)對內(nèi)存造成溢出,但是會(huì)大量占用IO資源。為此,我們還是要控制下多線程并行的數(shù)量,可以用線程池來提交作業(yè)

ExecutorService threadPool = Executors.newFixedThreadPool(5);

threadPool.submit(new Thread(){
	@Override
	public void run() {
    下載大數(shù)據(jù)集代碼
  }
}

最后測試了下50w這樣子的person數(shù)據(jù)的下載,大概耗時(shí)9秒,100w的person數(shù)據(jù),耗時(shí)19秒。這樣子的下載效率,應(yīng)該可以滿足大部分公司的報(bào)表導(dǎo)出需求吧。

“用java怎么快速從系統(tǒng)報(bào)表頁面導(dǎo)出20w條數(shù)據(jù)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI