讀取操作開始遇到的問題是當sql查詢數據量比較大時候基本讀不出來。開始以爲是server端處理太慢。但是在控制檯是可以立即返回數據的。於是在應用這邊抓包,發現也是發送sql後立即有數據返回。但是執行ResultSet的next方法確實阻塞的。查文檔翻代碼原來mysql驅動默認的行爲是需要把整個結果全部讀取到內存中才開始允許應用讀取結果。顯然與期望的行爲不一致,期望的行爲是流的方式讀取,當結果從myql服務端返回後立即還是讀取處理。這樣應用就不需要大量內存來存儲這個結果集。正確的流式讀取方式代碼示例:
PreparedStatement ps = connection.prepareStatement("select .. from ..",
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
//forward only read only也是mysql 驅動的默認值,所以不指定也是可以的 比如: PreparedStatement ps = connection.prepareStatement("select .. from ..");
ps.setFetchSize(Integer.MIN_VALUE); //也可以修改jdbc url通過defaultFetchSize參數來設置,這樣默認所以的返回結果都是通過流方式讀取.
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("fieldName"));
}
代碼分析:下面是mysql判斷是否開啓流式讀取結果的方法,有三個條件forward-only,read-only,fatch
size是Integer.MIN_VALUE/**
* 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() {
try {
synchronized(checkClosed().getConnectionMutex()) {
return ((this.resultSetType == java.sql.ResultSet.TYPE_FORWARD_ONLY)
&& (this.resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY) && (this.fetchSize == Integer.MIN_VALUE));
}
} catch (SQLException e) {
// we can't break the interface, having this be no-op in case of error is ok
return false;
}
}