您好,登錄后才能下訂單哦!
本篇內容介紹了“用java怎么快速從系統報表頁面導出20w條數據”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠學有所成!
先不談技術,先看效果,(完整案例代碼文末提供)
數據庫為mysql(理論上此套方案支持任何結構化數據庫),準備一張測試表t_person
。表結構如下:
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個字段。我們先創建測試數據。
案例代碼提供了一個簡單的頁面,點以下按鈕一次性可以創建5w條測試數據:
這里我連續點了4下,很快就生成了20w條數據,這里為了展示下數據的大致樣子,我直接跳轉到了最后一頁
然后點開下載大容量文件
,點擊執行執行按鈕,開始下載t_person
這張表里的全部數據
點擊執行按鈕之后,點下方刷新按鈕,可以看到一條異步下載記錄,狀態是P
,表示pending
狀態,不停刷新刷新按鈕,大概幾秒后,這一條記錄就變成S
狀態了,表示Success
然后你就可以下載到本地,文件大小大概31M左右
看到這里,很多童鞋要疑惑了,這下載下來是csv?csv其實是文本文件,用excel打開會丟失格式和精度。這解決不了問題啊,我們要excel格式啊!!
其實稍微會一點excel技巧的童鞋,可以利用excel導入數據這個功能,數據->導入數據,根據提示一步步,當中只要選擇逗號分隔就可以了,關鍵列可以定義格式,10秒就能完成數據的導入
你只要告訴運營小姐姐,根據這個步驟來完成excel的導入就可以了。而且下載過的文件,還可以反復下。
是不是從本質上解決了下載大容量數據集的問題?
學弟聽到這里,很興奮的說,這套方案能解決我這里的痛點。快和我說說原理。
其實這套方案核心很簡單,只源于一個知識點,活用JdbcTemplate
的這個接口:
@Override public void query(String sql, @Nullable Object[] args, RowCallbackHandler rch) throws DataAccessException { query(sql, newArgPreparedStatementSetter(args), rch); }
sql就是select * from t_person
,RowCallbackHandler
這個回調接口是指每一條數據遍歷后要執行的回調函數。現在貼出我自己的RowCallbackHandler
的實現
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){ ... } }
這個CsvRowCallbackHandler
做的事就是每次從數據庫取出500條,然后寫入服務器上的本地文件中,這樣,無論你這條sql查出來是20w條還是100w條,內存理論上只占用500條數據的存儲空間。等文件寫完了,我們要做的,只是從服務器把這個生成好的文件download到本地就可以了。
因為內存中不斷刷新的只有500條數據的容量,所以,即便多線程下載的環境下。內存也不會因此而溢出。這樣,完美解決了多人下載的場景。
當然,太多并行下載雖然不會對內存造成溢出,但是會大量占用IO資源。為此,我們還是要控制下多線程并行的數量,可以用線程池來提交作業
ExecutorService threadPool = Executors.newFixedThreadPool(5); threadPool.submit(new Thread(){ @Override public void run() { 下載大數據集代碼 } }
最后測試了下50w這樣子的person數據的下載,大概耗時9秒,100w的person數據,耗時19秒。這樣子的下載效率,應該可以滿足大部分公司的報表導出需求吧。
“用java怎么快速從系統報表頁面導出20w條數據”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識可以關注億速云網站,小編將為大家輸出更多高質量的實用文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。