2024-04-16 14:51:28.0|分类: mysql|浏览量: 426
使用JDBC向mysql发送查询时,有三种方式: 常规查询:JDBC驱动会阻塞的一次性读取全部查询的数据到 JVM 内存中,或者分页读取 流式查询:每次执行rs.next时会判断数据是否需要从mysql服务器获取, 如果需要触发读取一批数据(可能n行)加载到 JVM 内存进行业务处理 游标查询:通过 fetchSize 参数,控制每次从mysql服务器一次读取多少行数据。 游标查询例子: public static void cursorQuery() throws Exception { Connection connection = DriverManager.getConnection ("jdbc:mysql://localhost:3307/test?useSSL=false&useCursorFetch=true", "root", "123456"); ((JDBC4Connection) connection).setUseCursorFetch(true); //com.mysql.jdbc.JDBC4Connection Statement statement = connection.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); statement.setFetchSize(2000); ResultSet rs = statement.executeQuery(sql); while (rs.next()) { System.out.println(rs.getString(2)); Thread.sleep(5000); } rs.close(); statement.close(); connection.close(); } 驱动mysql-connector-java-5.1.43-sources.jar!/com/mysql/jdbc/MysqlIO.java源码分析: protected ResultSetImpl getResultSet(StatementImpl callingStatement, long columnCount, int maxRows, int resultSetType, int resultSetConcurrency, boolean streamResults, String catalog, boolean isBinaryEncoded, Field[] metadataFromCache) throws SQLException { Buffer packet; // The packet from the server Field[] fields = null; // Read in the column information if (metadataFromCache == null /* we want the metadata from the server */) { fields = new Field[(int) columnCount]; for (int i = 0; i < columnCount; i++) { Buffer fieldPacket = null; fieldPacket = readPacket(); fields[i] = unpackField(fieldPacket, false); } } else { for (int i = 0; i < columnCount; i++) { skipPacket(); } } // There is no EOF packet after fields when CLIENT_DEPRECATE_EOF is set if (!isEOFDeprecated() || // if we asked to use cursor then there should be an OK packet here (this.connection.versionMeetsMinimum(5, 0, 2) && callingStatement != null && isBinaryEncoded && callingStatement.isCursorRequired())) { packet = reuseAndReadPacket(this.reusablePacket); readServerStatusForResultSets(packet); } // // Handle cursor-based fetch first // if (this.connection.versionMeetsMinimum(5, 0, 2) && this.connection.getUseCursorFetch() && isBinaryEncoded && callingStatement != null && callingStatement.getFetchSize() != 0 && callingStatement.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) { ServerPreparedStatement prepStmt = (com.mysql.jdbc.ServerPreparedStatement) callingStatement; boolean usingCursor = true; // // Server versions 5.0.5 or newer will only open a cursor and set this flag if they can, otherwise they punt and go back to mysql_store_results() // behavior // if (this.connection.versionMeetsMinimum(5, 0, 5)) { usingCursor = (this.serverStatus & SERVER_STATUS_CURSOR_EXISTS) != 0; } if (usingCursor) { RowData rows = new RowDataCursor(this, prepStmt, fields); ResultSetImpl rs = buildResultSetWithRows(callingStatement, catalog, fields, rows, resultSetType, resultSetConcurrency, isBinaryEncoded); if (usingCursor) { rs.setFetchSize(callingStatement.getFetchSize()); } return rs; } } RowData rowData = null; if (!streamResults) { rowData = readSingleRowSet(columnCount, maxRows, resultSetConcurrency, isBinaryEncoded, (metadataFromCache == null) ? fields : metadataFromCache); } else { rowData = new RowDataDynamic(this, (int) columnCount, (metadataFromCache == null) ? fields : metadataFromCache, isBinaryEncoded); this.streamingData = rowData; } ResultSetImpl rs = buildResultSetWithRows(callingStatement, catalog, (metadataFromCache == null) ? fields : metadataFromCache, rowData, resultSetType, resultSetConcurrency, isBinaryEncoded); return rs; } |