PG jdbc的查詢結果集獲取方式html
1 簡單所有結果集查詢java
默認狀況下,pgjdbc是一次獲取所有查詢結果的,而且結果集的類型和併發性分別爲ResultSet.TYPE_FORWARD_ONLY和ResultSet.CONCUR_READ_ONLY。也就是pgjdbc默認會一次獲取所有查詢結果,只能從前日後取,是隻讀的。sql
stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery(sql);
while(rs.next())
{
...
}
經過修改結果集的類型和併發性,還分別能夠得到(不)可滑動的,對變化(不)敏感的,(不)可更新的結果集。數據庫
ResultSet類型API: http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#TYPE_SCROLL_SENSITIVE
後端
ResultSet.TYPE_FORWARD_ONLY ResultSet.CONCUR_READ_ONLYapi
ResultSet.TYPE_SCROLL_INSENSITIVE ResultSet.CONCUR_UPDATABLE緩存
ResultSet.TYPE_SCROLL_SENSITIVE
併發
該方法一次獲取所有結果:對於數據量小的查詢來講,速度更快,結果集有多種靈活的獲取方式;但對於數據量很大的查詢,容易形成很大的內存消耗,甚至內存溢出。oracle
2 基於遊標的批量結果集查詢app
經過設置setFetchSize(int size)獲取基於遊標cursor的結果集,size>0表示開啓遊標,一次只獲取size行結果集,該size取完後在獲取下一size的結果集;size=0表示關閉遊標,結果集一次取出所有行。
基於遊標的結果集的使用是有條件的,若是不知足條件setFechSize(int size)將不起做用,pgjdbc仍是會一次獲取所有結果集。基於遊標的結果集使用條件以下:
1.連到數據庫服務的鏈接必須是基於V3協議的,V3協議是7.4及更新版本PG才能支持的,而且是他們的默認協議;
2.Connection必須是非自動提交模式.後端會在事務的結束的時候關閉遊標,因此,在自動提交模式裏,還沒從遊標裏獲取任何東西的時候,後端就已經把遊標關閉了。
3.Statement必須以ResultSet.TYPE_FORWARD_ONLY的類型來建立,該結果集類型是默認的,因此能夠直接使用stmt = conn.createStatement()來建立(或者stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY)).所以基於遊標的結果集是隻能向前獲取,不能向後或者跳躍獲取的。
4. 查詢sql語句必須是一個單一的語句,不能是由分好分隔的多個語句。
// make sure autocommit is off conn.setAutoCommit(false); Statement st = conn.createStatement(); // Turn use of the cursor on. st.setFetchSize(50);ResultSet rs = st.executeQuery("SELECT * FROM mytable"); while (rs.next()) { System.out.print("a row was returned."); } rs.close(); // Turn the cursor off. st.setFetchSize(0); rs = st.executeQuery("SELECT * FROM mytable"); while (rs.next()) { System.out.print("many rows were returned."); } rs.close();
該方法分批獲取結果集,一次僅獲取一個批量的數據,只有一個小批量的行集緩存在鏈接的客戶端,當該批量用盡後纔會經過重定位遊標來獲取下一批量的行集:對於數據量小的查詢,因爲分批獲取,會致使查詢速度下降,結果集取得的靈活性也不可用了;可是對於數據量大的查詢,分批獲取,首次得到結果的速度加快,下降了內存的消耗的閥值,能夠避免內存溢出的問題。
橋哥的博客:http://blog.chinaunix.net/uid-20726500-id-4844406.html
JAVA API: http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html#TYPE_SCROLL_SENSITIVE
PG JDBC Last Doc: https://jdbc.postgresql.org/documentation/head/query.html#query-with-cursor
原文以下:
Chapter 5. Issuing a Query and Processing the Result
Table of Contents
Getting results based on a cursor
Using the Statement or PreparedStatement Interface
Using the ResultSet Interface
Performing Updates
Creating and Modifying Database Objects
Any time you want to issue SQL statements to the database, you require a Statement or PreparedStatement instance. Once you have a Statement or PreparedStatement, you can use issue a query. This will return a ResultSet instance, which contains the entire result (see the section called 「Getting results based on a cursor」 here for how to alter this behaviour). Example 5.1, 「Processing a Simple Query in JDBC」 illustrates this process.
Example 5.1. Processing a Simple Query in JDBC
This example will issue a simple query and print out the first column of each row using a Statement.
Statement st = conn.createStatement(); ResultSet rs = st.executeQuery("SELECT * FROM mytable WHERE columnfoo = 500"); while (rs.next()) { System.out.print("Column 1 returned "); System.out.println(rs.getString(1)); } rs.close(); st.close();
This example issues the same query as before but uses a PreparedStatement and a bind value in the query.
int foovalue = 500; PreparedStatement st = conn.prepareStatement("SELECT * FROM mytable WHERE columnfoo = ?"); st.setInt(1, foovalue); ResultSet rs = st.executeQuery(); while (rs.next()) { System.out.print("Column 1 returned "); System.out.println(rs.getString(1)); } rs.close(); st.close();
Getting results based on a cursor
By default the driver collects all the results for the query at once. This can be inconvenient for large data sets so the JDBC driver provides a means of basing a ResultSet on a database cursor and only fetching a small number of rows.
A small number of rows are cached on the client side of the connection and when exhausted the next block of rows is retrieved by repositioning the cursor.
Note
Cursor based ResultSets cannot be used in all situations. There a number of restrictions which will make the driver silently fall back to fetching the whole ResultSet at once.
The connection to the server must be using the V3 protocol. This is the default for (and is only supported by) server versions 7.4 and later.
The Connection must not be in autocommit mode. The backend closes cursors at the end of transactions, so in autocommit mode the backend will have closed the cursor before anything can be fetched from it. *The Statement must be created with a ResultSet type of ResultSet.TYPE_FORWARD_ONLY. This is the default, so no code will need to be rewritten to take advantage of this, but it also means that you cannot scroll backwards or otherwise jump around in the ResultSet.
The query given must be a single statement, not multiple statements strung together with semicolons.
Example 5.2. Setting fetch size to turn cursors on and off.
Changing code to cursor mode is as simple as setting the fetch size of the Statement to the appropriate size. Setting the fetch size back to 0 will cause all rows to be cached (the default behaviour).
// make sure autocommit is off conn.setAutoCommit(false); Statement st = conn.createStatement(); // Turn use of the cursor on. st.setFetchSize(50); ResultSet rs = st.executeQuery("SELECT * FROM mytable"); while (rs.next()) { System.out.print("a row was returned."); } rs.close(); // Turn the cursor off. st.setFetchSize(0); rs = st.executeQuery("SELECT * FROM mytable"); while (rs.next()) { System.out.print("many rows were returned."); } rs.close(); // Close the statement. st.close();