JDBC流式讀取MySQL表

一張MySQL大表,我們希望遍歷表中的數據,一般情況下都是一次性讀進內存中,這樣就會給服務器增大很大的壓力,那我們可以不可以流式讀取MySQL表呢,就像ElasticSearch的scrollSearch一樣的效果。
答案是可以的。

經過看Statement的源碼找到了如下片段:

 /**
     * We only stream result sets when they are forward-only, read-only, and the
     * fetch size has been set to Integer.MIN_VALUE
     * 
     * @return true if this result set should be streamed row at-a-time, rather
     *         than read all at once.
     */
    protected boolean createStreamingResultSet() {
        return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY) && (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY)
                && (this.fetchSize == Integer.MIN_VALUE));
    }

也就是說流式讀mysql表可以通過設置三個參數實現:

  • resultSetType = forward-only(默認)
  • resultSetConcurrency = read-only(默認)
  • fetchSize = Integer.MIN_VALUE

完整測試代碼如下。

try {
    
       Class.forName("com.mysql.cj.jdbc.Driver");
       Connection connection = DriverManager.getConnection(
               "jdbc:mysql://test01:3306/test_db?characterEncoding=utf8&useSSL=true", "xxxx",
               "xxxxxx");
       PreparedStatement pstm = connection.prepareStatement("select * from test_table",
               ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
       pstm.setFetchSize(Integer.MIN_VALUE);
       ResultSet resultSet = pstm.executeQuery();
       int columnCount;
       JSONObject jsonObject;
       while (resultSet.next()) {
           ResultSetMetaData metaData = resultSet.getMetaData();
           jsonObject = new JSONObject();
           columnCount = metaData.getColumnCount();
           for (int m = 1; m <= columnCount; m++) {
               jsonObject.put(metaData.getColumnName(m), resultSet.getString(m));
           }
           System.out.println(jsonObject);
       }
} catch (Exception e) {
    e.printStackTrace();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章