poi之大數據量導出

<dependencies>
		<dependency>
			<groupId>dom4j</groupId>
			<artifactId>dom4j</artifactId>
			<version>1.6.1</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.35</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi</artifactId>
			<version>3.10-FINAL</version>
		</dependency>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>3.10-FINAL</version>
		</dependency>

		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml-schemas</artifactId>
			<version>3.10-FINAL</version>
		</dependency>
		<dependency>
			<groupId>org.apache.xmlbeans</groupId>
			<artifactId>xmlbeans</artifactId>
			<version>2.3.0</version>
		</dependency>

	</dependencies>


package com.tanlei.test.export;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;

public class BigDataExport {

	public static void main(String[] args) throws Exception {
		String name = ManagementFactory.getRuntimeMXBean().getName();
		System.out.println(name);
		// get pid
		String pid = name.split("@")[0];
		System.out.println("Pid is:" + pid);

		BigDataExport tm = new BigDataExport();
		tm.jdbcex(true);
		Thread.sleep(1000 * 40);
	}

	public void jdbcex(boolean isClose) throws InstantiationException, IllegalAccessException, ClassNotFoundException,
			SQLException, IOException, InterruptedException {

		String xlsFile = "f:/poiSXXFSBigData.xlsx"; // 輸出文件
		// 內存中只創建100個對象,寫臨時文件,當超過100條,就將內存中不用的對象釋放。
		Workbook wb = new SXSSFWorkbook(100); // 關鍵語句
		Sheet sheet = null; // 工作表對象
		Row nRow = null; // 行對象
		Cell nCell = null; // 列對象

		// 使用jdbc鏈接數據庫
		Class.forName("com.mysql.jdbc.Driver").newInstance();
		String url = "jdbc:mysql://xxx.xxx.xxx.xxx/dbname?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8&useFastDateParsing=false&zeroDateTimeBehavior=convertToNull";
		String user = "root";
		String password = "root1234";
		// 獲取數據庫連接
		Connection conn = DriverManager.getConnection(url, user, password);
		Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
		String sql = "select * from tb_applyflow_rpt"; // 100萬+測試數據
		ResultSet rs = stmt.executeQuery(sql);

		ResultSetMetaData rsmd = rs.getMetaData();
		long startTime = System.currentTimeMillis(); // 開始時間
		System.out.println("strat execute time: " + startTime);

		int rowNo = 0; // 總行號
		int pageRowNo = 0; // 頁行號

		while (rs.next()) {
			// 打印300000條後切換到下個工作表,可根據需要自行拓展,2百萬,3百萬...數據一樣操作,只要不超過1048576就可以
			if (rowNo % 300000 == 0) {
				System.out.println("Current Sheet:" + rowNo / 300000);
				sheet = wb.createSheet("我的第" + (rowNo / 300000) + "個工作簿");// 建立新的sheet對象
				sheet = wb.getSheetAt(rowNo / 300000); // 動態指定當前的工作表
				pageRowNo = 0; // 每當新建了工作表就將當前工作表的行號重置爲0
			}
			rowNo++;
			nRow = sheet.createRow(pageRowNo++); // 新建行對象

			// 打印每行,每行有6列數據 rsmd.getColumnCount()==6 --- 列屬性的個數
			for (int j = 0; j < rsmd.getColumnCount(); j++) {
				nCell = nRow.createCell(j);
				nCell.setCellValue(rs.getString(j + 1));
			}

			if (rowNo % 10000 == 0) {
				System.out.println("row no: " + rowNo);
			}
			// Thread.sleep(1); //休息一下,防止對CPU佔用,其實影響不大
		}

		long finishedTime = System.currentTimeMillis(); // 處理完成時間
		System.out.println("finished execute  time: " + (finishedTime - startTime) / 1000 + "m");

		FileOutputStream fOut = new FileOutputStream(xlsFile);
		wb.write(fOut);
		fOut.flush(); // 刷新緩衝區
		fOut.close();

		long stopTime = System.currentTimeMillis(); // 寫文件時間
		System.out.println("write xlsx file time: " + (stopTime - startTime) / 1000 + "m");

		if (isClose) {
			this.close(rs, stmt, conn);
		}
	}

	// 執行關閉流的操作
	private void close(ResultSet rs, Statement stmt, Connection conn) throws SQLException {
		rs.close();
		stmt.close();
		conn.close();
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章