The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
The following method, 以下方法CoffeesTable.viewTable
outputs the contents of the COFFEES
tables, and demonstrates the use of ResultSet
objects and cursors:CoffeesTable.viewTable
输出COFFEES
表的内容,并演示ResultSet
对象和游标的使用:
public static void viewTable(Connection con) throws SQLException { String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; try (Statement stmt = con.createStatement()) { ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String coffeeName = rs.getString("COF_NAME"); int supplierID = rs.getInt("SUP_ID"); float price = rs.getFloat("PRICE"); int sales = rs.getInt("SALES"); int total = rs.getInt("TOTAL"); System.out.println(coffeeName + ", " + supplierID + ", " + price + ", " + sales + ", " + total); } } catch (SQLException e) { JDBCTutorialUtilities.printSQLException(e); } }
A ResultSet
object is a table of data representing a database result set, which is usually generated by executing a statement that queries the database. ResultSet
对象是表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。For example, the 例如,CoffeeTables.viewTable
method creates a ResultSet
, rs
, when it executes the query through the Statement
object, stmt
. CoffeeTables.viewTable
方法通过Statement
对象stmt
执行查询时,会创建一个ResultSet
、rs
。Note that a 请注意,可以通过实现ResultSet
object can be created through any object that implements the Statement
interface, including PreparedStatement
, CallableStatement
, and RowSet
.Statement
接口的任何对象创建ResultSet
对象,包括PreparedStatement
、CallableStatement
和RowSet
。
You access the data in a 您可以通过游标访问ResultSet
object through a cursor. ResultSet
对象中的数据。Note that this cursor is not a database cursor. 请注意,此游标不是数据库游标。This cursor is a pointer that points to one row of data in the 此游标是指向ResultSet
. ResultSet
中一行数据的游标。Initially, the cursor is positioned before the first row. 最初,游标位于第一行之前。The method 方法ResultSet.next
moves the cursor to the next row. ResultSet.next
将游标移动到下一行。This method returns 如果游标位于最后一行之后,则此方法返回false
if the cursor is positioned after the last row. false
。This method repeatedly calls the 此方法使用ResultSet.next
method with a while
loop to iterate through all the data in the ResultSet
.while
循环重复调用ResultSet.next
方法,以遍历ResultSet
中的所有数据。
This page covers the following topics:本页涵盖以下主题:
The ResultSet
interface provides methods for retrieving and manipulating the results of executed queries, and ResultSet
objects can have different functionality and characteristics. ResultSet
接口提供了检索和操作已执行查询结果的方法,ResultSet
对象可以具有不同的功能和特征。These characteristics are type, concurrency, and cursor holdability.这些特征是类型、并发性和游标保持性。
The type of a ResultSet
object determines the level of its functionality in two areas: the ways in which the cursor can be manipulated, and how concurrent changes made to the underlying data source are reflected by the ResultSet
object.ResultSet
对象的类型决定了它在两个方面的功能级别:游标的操作方式,以及ResultSet
对象如何反映对基础数据源所做的并发更改。
The sensitivity of a ResultSet
object is determined by one of three different ResultSet
types:ResultSet
对象的敏感度由以下三种不同ResultSet
类型之一决定:
TYPE_FORWARD_ONLY
TYPE_SCROLL_INSENSITIVE
TYPE_SCROLL_SENSITIVE
The default 默认的ResultSet
type is TYPE_FORWARD_ONLY
.ResultSet
类型为TYPE_FORWARD_ONLY
。
Note: Not all databases and JDBC drivers support all :并非所有数据库和JDBC驱动程序都支持所有ResultSet
types. ResultSet
类型。The method 如果指定的DatabaseMetaData.supportsResultSetType
returns true
if the specified ResultSet
type is supported and false
otherwise.ResultSet
类型受支持,则DatabaseMetaData.supportsResultSetType
方法返回true
,否则返回false
。
The concurrency of a ResultSet
object determines what level of update functionality is supported.ResultSet
对象的并发性决定了支持哪一级别的更新功能。
There are two concurrency levels:有两个并发级别:
CONCUR_READ_ONLY
ResultSet
object cannot be updated using the ResultSet
interface.ResultSet
接口更新ResultSet
对象。CONCUR_UPDATABLE
ResultSet
object can be updated using the ResultSet
interface.ResultSet
接口更新ResultSet
对象。The default 默认ResultSet
concurrency is CONCUR_READ_ONLY
.ResultSet
并发性为CONCUR_READ_ONLY
。
Note: Not all JDBC drivers and databases support concurrency. :并非所有JDBC驱动程序和数据库都支持并发。The method 如果驱动程序支持指定的并发级别,则方法DatabaseMetaData.supportsResultSetConcurrency
returns true
if the specified concurrency level is supported by the driver and false
otherwise.DatabaseMetaData.supportsResultSetConcurrency
返回true
,否则返回false
。
The method CoffeesTable.modifyPrices
demonstrates how to use a ResultSet
object whose concurrency level is CONCUR_UPDATABLE
.CoffeesTable.modifyPrices
方法演示了如何使用并发级别为CONCUR_UPDATABLE
的ResultSet
对象。
Calling the method 调用方法Connection.commit
can close the ResultSet
objects that have been created during the current transaction. Connection.commit
可以关闭在当前事务期间创建的ResultSet
对象。In some cases, however, this may not be the desired behavior. 然而,在某些情况下,这可能不是期望的行为。The ResultSet
property holdability gives the application control over whether ResultSet
objects (cursors) are closed when commit is called.ResultSet
属性holdability使应用程序可以控制在调用commit
时是否关闭ResultSet
对象(游标)。
The following 以下ResultSet
constants may be supplied to the Connection
methods createStatement
, prepareStatement
, and prepareCall
:ResultSet
常量可提供给Connection
方法createStatement
、prepareStatement
和prepareCall
:
HOLD_CURSORS_OVER_COMMIT
ResultSet
cursors are not closed; they are holdable: they are held open when the method commit
is called. Holdable cursors might be ideal if your application uses mostly read-only ResultSet
objects.ResultSet
游标未关闭;它们是可保持的:当调用commit
方法时,它们保持打开状态。如果应用程序主要使用只读ResultSet
对象,则可保持游标可能是理想的选择。CLOSE_CURSORS_AT_COMMIT
ResultSet
objects (cursors) are closed when the commit
method is called. ResultSet
对象(游标)在调用commit
方法时关闭。The default cursor holdability varies depending on your DBMS.默认游标保持能力因DBMS而异。
Note: Not all JDBC drivers and databases support holdable and non-holdable cursors. :并非所有JDBC驱动程序和数据库都支持可保持和不可保持游标。The following method, 以下方法JDBCTutorialUtilities.cursorHoldabilitySupport
, outputs the default cursor holdability of ResultSet
objects and whether HOLD_CURSORS_OVER_COMMIT
and CLOSE_CURSORS_AT_COMMIT
are supported:JDBCTutorialUtilities.cursorHoldabilitySupport
输出ResultSet
对象的默认游标保持能力,以及是否支持HOLD_CURSORS_OVER_COMMIT
和CLOSE_CURSORS_AT_COMMIT
:
public static void cursorHoldabilitySupport(Connection conn) throws SQLException { DatabaseMetaData dbMetaData = conn.getMetaData(); System.out.println("ResultSet.HOLD_CURSORS_OVER_COMMIT = " + ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println("ResultSet.CLOSE_CURSORS_AT_COMMIT = " + ResultSet.CLOSE_CURSORS_AT_COMMIT); System.out.println("Default cursor holdability: " + dbMetaData.getResultSetHoldability()); System.out.println("Supports HOLD_CURSORS_OVER_COMMIT? " + dbMetaData.supportsResultSetHoldability( ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println("Supports CLOSE_CURSORS_AT_COMMIT? " + dbMetaData.supportsResultSetHoldability( ResultSet.CLOSE_CURSORS_AT_COMMIT)); }
The ResultSet
interface declares getter methods (for example, getBoolean
and getLong
) for retrieving column values from the current row. ResultSet
接口声明用于从当前行检索列值的getter
方法(例如getBoolean
和getLong
)。You can retrieve values using either the index number of the column or the alias or name of the column. 可以使用列的索引号或列的别名或名称检索值。The column index is usually more efficient. 列索引通常更有效。Columns are numbered from 1. 列从1开始编号。For maximum portability, result set columns within each row should be read in left-to-right order, and each column should be read only once.为了实现最大的可移植性,每行中的结果集列应该按从左到右的顺序读取,并且每列只应该读取一次。
For example, the following method, 例如,以下方法CoffeesTable.alternateViewTable
, retrieves column values by number:CoffeesTable.alternateViewTable
按编号检索列值:
public static void alternateViewTable(Connection con) throws SQLException { String query = "select COF_NAME, SUP_ID, PRICE, SALES, TOTAL from COFFEES"; try (Statement stmt = con.createStatement()) { ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String coffeeName = rs.getString(1); int supplierID = rs.getInt(2); float price = rs.getFloat(3); int sales = rs.getInt(4); int total = rs.getInt(5); System.out.println(coffeeName + ", " + supplierID + ", " + price + ", " + sales + ", " + total); } } catch (SQLException e) { JDBCTutorialUtilities.printSQLException(e); } }
Strings used as input to getter methods are case-insensitive. 用作getter方法输入的字符串不区分大小写。When a getter method is called with a string and more than one column has the same alias or name as the string, the value of the first matching column is returned. 当使用字符串调用getter方法并且多个列具有与字符串相同的别名或名称时,将返回第一个匹配列的值。The option to use a string as opposed to an integer is designed to be used when column aliases and names are used in the SQL query that generated the result set. 使用字符串而不是整数的选项是为了在生成结果集的SQL查询中使用列别名和名称时使用。For columns that are not explicitly named in the query (for example, 对于查询中未显式命名的列(例如,select * from COFFEES
) it is best to use column numbers. select * from COFFEES
),最好使用列号。If column names are used, the developer should guarantee that they uniquely refer to the intended columns by using column aliases. 如果使用了列名,开发人员应该通过使用列别名来保证它们唯一地引用了预期的列。A column alias effectively renames the column of a result set. 列别名可以有效地重命名结果集的列。To specify a column alias, use the SQL 要指定列别名,请在AS
clause in the SELECT
statement.SELECT
语句中使用SQL AS
子句。
The getter method of the appropriate type retrieves the value in each column. 适当类型的getter方法检索每个列中的值。For example, in the method 例如,在方法CoffeeTables.viewTable
, the first column in each row of the ResultSet
rs
is COF_NAME
, which stores a value of SQL type VARCHAR
. CoffeeTables.viewTable
中,ResultSet
rs
每行的第一列是COF_NAME
,它存储SQL类型VARCHAR
的值。The method for retrieving a value of SQL type 检索SQL类型VARCHAR
is getString
. VARCHAR
的值的方法是getString
。The second column in each row stores a value of SQL type 每行的第二列存储SQL类型INTEGER
, and the method for retrieving values of that type is getInt
.INTEGER
的值,检索该类型值的方法是getInt
。
Note that although the method 请注意,尽管建议使用getString
is recommended for retrieving the SQL types CHAR
and VARCHAR
, it is possible to retrieve any of the basic SQL types with it. getString
方法检索SQL类型CHAR
和VARCHAR
,但也可以使用它检索任何基本SQL类型。Getting all values with 使用getString
can be very useful, but it also has its limitations. getString
获取所有值非常有用,但也有其局限性。For instance, if it is used to retrieve a numeric type, 例如,如果用于检索数值类型,则getString
converts the numeric value to a Java String
object, and the value has to be converted back to a numeric type before it can be operated on as a number. getString
将数值转换为JavaString
对象,并且必须将该值转换回数值类型,然后才能将其作为数字进行操作。In cases where the value is treated as a string anyway, there is no drawback. Furthermore, if you want an application to retrieve values of any standard SQL type other than SQL3 types, use the 在值被视为字符串的情况下,没有缺点。此外,如果希望应用程序检索SQL3类型以外的任何标准SQL类型的值,请使用getString
method.getString
方法。
As mentioned previously, you access the data in a 如前所述,您可以通过游标访问ResultSet
object through a cursor, which points to one row in the ResultSet
object. ResultSet
对象中的数据,游标指向ResultSet
对象中的一行。However, when a 但是,当第一次创建ResultSet
object is first created, the cursor is positioned before the first row. ResultSet
对象时,游标位于第一行之前。The method 方法CoffeeTables.viewTable
moves the cursor by calling the ResultSet.next
method. CoffeeTables.viewTable
通过调用ResultSet.next
方法来移动游标。There are other methods available to move the cursor:还有其他方法可用于移动游标:
next
true
if the cursor is now positioned on a row and false
if the cursor is positioned after the last row.true
;如果游标位于最后一行之后,则返回false
。previous
true
if the cursor is now positioned on a row and false
if the cursor is positioned before the first row.true
;如果游标位于第一行之前,则返回false
。first
ResultSet
object. ResultSet
对象中的第一行。true
if the cursor is now positioned on the first row and false
if the ResultSet
object does not contain any rows.true
;如果ResultSet
对象不包含任何行,则返回false
。last
ResultSet
object. ResultSet
对象中的最后一行。true
if the cursor is now positioned on the last row and false
if the ResultSet
object does not contain any rows.true
;如果ResultSet
对象不包含任何行,则返回false
。beforeFirst
ResultSet
object, before the first row. ResultSet
对象的开头,第一行之前。ResultSet
object does not contain any rows, this method has no effect.ResultSet
对象不包含任何行,则此方法无效。afterLast
ResultSet
object, after the last row. ResultSet
对象的末尾,最后一行之后。ResultSet
object does not contain any rows, this method has no effect.ResultSet
对象不包含任何行,则此方法无效。relative(int rows)
absolute(int row)
row
.row
指定的行上。Note that the default sensitivity of a 请注意,ResultSet
is TYPE_FORWARD_ONLY
, which means that it cannot be scrolled; you cannot call any of these methods that move the cursor, except next
, if your ResultSet
cannot be scrolled. ResultSet
的默认敏感度为TYPE_FORWARD_ONLY
,这意味着它无法滚动;如果无法滚动结果集,则不能调用这些移动游标的方法中的任何一个,除非调用next
。The method 下一节介绍的方法CoffeesTable.modifyPrices
, described in the following section, demonstrates how you can move the cursor of a ResultSet
.CoffeesTable.modifyPrices
演示了如何移动ResultSet
的游标。
You cannot update a default 无法更新默认的ResultSet
object, and you can only move its cursor forward. ResultSet
对象,只能向前移动其游标。However, you can create 但是,您可以创建可以ResultSet
objects that can be scrolled (the cursor can move backwards or move to an absolute position) and updated.ResultSet
(游标可以向后移动或移动到绝对位置)和更新的ResultSet
对象。
The following method, 以下方法CoffeesTable.modifyPrices
, multiplies the PRICE
column of each row by the argument percentage
:CoffeesTable.modifyPrices
将每行的PRICE
列乘以参数percentage
:
public void modifyPrices(float percentage) throws SQLException { try (Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { ResultSet uprs = stmt.executeQuery("SELECT * FROM COFFEES"); while (uprs.next()) { float f = uprs.getFloat("PRICE"); uprs.updateFloat("PRICE", f * percentage); uprs.updateRow(); } } catch (SQLException e) { JDBCTutorialUtilities.printSQLException(e); } }
The field 字段ResultSet.TYPE_SCROLL_SENSITIVE
creates a ResultSet
object whose cursor can move both forward and backward relative to the current position and to an absolute position. ResultSet.TYPE_SCROLL_SENSITIVE
创建一个ResultSet
对象,其游标可以相对于当前位置和绝对位置向前和向后移动。The field 字段ResultSet.CONCUR_UPDATABLE
creates a ResultSet
object that can be updated. ResultSet.CONCUR_UPDATABLE
创建一个可以更新的ResultSet
对象。See the 请参阅ResultSet
Javadoc for other fields you can specify to modify the behavior of ResultSet
objects.ResultSet
Javadoc,了解可以指定用于修改ResultSet
对象行为的其他字段。
The method 方法ResultSet.updateFloat
updates the specified column (in this example, PRICE
with the specified float
value in the row where the cursor is positioned. ResultSet.updateFloat
使用游标所在行中指定的float
值更新指定列(在本例中为PRICE
)。ResultSet
contains various updater methods that enable you to update column values of various data types. ResultSet
包含各种更新程序方法,使您能够更新各种数据类型的列值。However, none of these updater methods modifies the database; you must call the method 但是,这些更新程序方法都不会修改数据库;必须调用ResultSet.updateRow
to update the database.ResultSet.updateRow
方法来更新数据库。
Statement
, PreparedStatement
and CallableStatement
objects have a list of commands that is associated with them. Statement
、PreparedStatement
和CallableStatement
对象具有与其关联的命令列表。This list may contain statements for updating, inserting, or deleting a row; and it may also contain DDL statements such as 此列表可能包含用于更新、插入或删除行的语句;它还可能包含DDL语句,如CREATE TABLE
and DROP TABLE
. CREATE TABLE
和DROP TABLE
。It cannot, however, contain a statement that would produce a 但是,它不能包含将生成ResultSet
object, such as a SELECT
statement. ResultSet
对象的语句,例如SELECT
语句。In other words, the list can contain only statements that produce an update count.换句话说,列表只能包含生成更新计数的语句。
The list, which is associated with a 创建时与Statement
object at its creation, is initially empty. Statement
对象关联的列表最初为空。You can add SQL commands to this list with the method 您可以使用addBatch
and empty it with the method clearBatch
. addBatch
方法将SQL命令添加到此列表,并使用clearBatch
方法将其清空。When you have finished adding statements to the list, call the method 将语句添加到列表后,调用executeBatch
to send them all to the database to be executed as a unit, or batch.executeBatch
方法将它们全部发送到数据库,作为一个单元或批处理执行。
For example, the following method 例如,以下方法CoffeesTable.batchUpdate
adds four rows to the COFFEES
table with a batch update:CoffeesTable.batchUpdate
通过批更新将四行添加到COFFEES
表中:
public void batchUpdate() throws SQLException { con.setAutoCommit(false); try (Statement stmt = con.createStatement()) { stmt.addBatch("INSERT INTO COFFEES " + "VALUES('Amaretto', 49, 9.99, 0, 0)"); stmt.addBatch("INSERT INTO COFFEES " + "VALUES('Hazelnut', 49, 9.99, 0, 0)"); stmt.addBatch("INSERT INTO COFFEES " + "VALUES('Amaretto_decaf', 49, 10.99, 0, 0)"); stmt.addBatch("INSERT INTO COFFEES " + "VALUES('Hazelnut_decaf', 49, 10.99, 0, 0)"); int[] updateCounts = stmt.executeBatch(); con.commit(); } catch (BatchUpdateException b) { JDBCTutorialUtilities.printBatchUpdateException(b); } catch (SQLException ex) { JDBCTutorialUtilities.printSQLException(ex); } finally { con.setAutoCommit(true); } }
The following line disables auto-commit mode for the 下一行禁用Connection
object con so that the transaction will not be automatically committed or rolled back when the method executeBatch
is called.Connection
对象con
的自动提交模式,以便在调用方法executeBatch
时不会自动提交或回滚事务。
con.setAutoCommit(false);
To allow for correct error handling, you should always disable auto-commit mode before beginning a batch update.为了允许正确的错误处理,您应该在开始批处理更新之前始终禁用自动提交模式。
The method 方法Statement.addBatch
adds a command to the list of commands associated with the Statement
object stmt
. Statement.addBatch
将命令添加到与Statement
对象stmt
关联的命令列表中。In this example, these commands are all 在本例中,这些命令都是INSERT INTO
statements, each one adding a row consisting of five column values. INSERT INTO
语句,每个命令添加一行,该行由五个列值组成。The values for the columns COF_NAME
and PRICE
are the name of the coffee and its price, respectively. COF_NAME
和PRICE
列的值分别是咖啡的名称和价格。The second value in each row is 49 because that is the identification number for the supplier, Superior Coffee. 每行的第二个值是49,因为这是供应商Superior Coffee的标识号。The last two values, the entries for the columns 最后两个值,即SALES
and TOTAL
, all start out being zero because there have been no sales yet. SALES
和TOTAL
列的条目,由于还没有销售,所有值都开始为零。((SALES
is the number of pounds of this row's coffee sold in the current week; TOTAL
is the total of all the cumulative sales of this coffee.)SALES
是指该行咖啡在本周售出的磅数;TOTAL
是该咖啡所有累计销售额的总和。)
The following line sends the four SQL commands that were added to its list of commands to the database to be executed as a batch:下一行将添加到其命令列表中的四个SQL命令发送到要作为批处理执行的数据库:
int[] updateCounts = stmt.executeBatch();
Note that 请注意,stmt
uses the method executeBatch
to send the batch of insertions, not the method executeUpdate
, which sends only one command and returns a single update count. stmt
使用方法executeBatch
发送插入批,而不是方法executeUpdate
,后者只发送一个命令并返回一个更新计数。The DBMS executes the commands in the order in which they were added to the list of commands, so it will first add the row of values for Amaretto, then add the row for Hazelnut, then Amaretto decaf, and finally Hazelnut decaf. DBMS按照命令添加到命令列表的顺序执行命令,因此它将首先为Amaretto添加值行,然后为Hazelnut添加值行,然后为Amaretto decaf添加值行,最后为Hazelnut decaf添加值行。If all four commands execute successfully, the DBMS will return an update count for each command in the order in which it was executed. 如果所有四个命令都成功执行,DBMS将按照执行顺序返回每个命令的更新计数。The update counts that indicate how many rows were affected by each command are stored in the array 表示每个命令影响多少行的更新计数存储在数组updateCounts
.updateCounts
中。
If all four of the commands in the batch are executed successfully, 如果批处理中的所有四个命令都成功执行,updateCounts
will contain four values, all of which are 1 because an insertion affects one row. updateCounts
将包含四个值,因为插入会影响一行,所以所有值都是1。The list of commands associated with 与stmt
will now be empty because the four commands added previously were sent to the database when stmt
called the method executeBatch
. stmt
关联的命令列表现在将为空,因为以前添加的四个命令是在stmt
调用方法executeBatch
时发送到数据库的。You can at any time explicitly empty this list of commands with the method 您可以随时使用clearBatch
.clearBatch
方法显式清空此命令列表。
The Connection.commit
method makes the batch of updates to the COFFEES
table permanent. Connection.commit
方法使对COFFEES
表的批量更新永久化。This method needs to be called explicitly because the auto-commit mode for this connection was disabled previously.需要显式调用此方法,因为此连接的自动提交模式以前已禁用。
The following line enables auto-commit mode for the current 下一行为当前Connection
object.Connection
对象启用自动提交模式。
con.setAutoCommit(true);
Now each statement in the example will automatically be committed after it is executed, and it no longer needs to invoke the method 现在,示例中的每个语句将在执行后自动提交,并且不再需要调用commit
.commit
方法。
It is also possible to have a parameterized batch update, as shown in the following code fragment, where 还可以进行参数化批量更新,如以下代码片段所示,其中con
is a Connection
object:con
是Connection
对象:
con.setAutoCommit(false); PreparedStatement pstmt = con.prepareStatement( "INSERT INTO COFFEES VALUES( " + "?, ?, ?, ?, ?)"); pstmt.setString(1, "Amaretto"); pstmt.setInt(2, 49); pstmt.setFloat(3, 9.99); pstmt.setInt(4, 0); pstmt.setInt(5, 0); pstmt.addBatch(); pstmt.setString(1, "Hazelnut"); pstmt.setInt(2, 49); pstmt.setFloat(3, 9.99); pstmt.setInt(4, 0); pstmt.setInt(5, 0); pstmt.addBatch(); // ... and so on for each new // type of coffee int[] updateCounts = pstmt.executeBatch(); con.commit(); con.setAutoCommit(true);
You will get a 如果(1)添加到批处理中的某个SQL语句生成结果集(通常为查询)或(2)批处理中的某个SQL语句由于某些其他原因未成功执行,则在调用方法BatchUpdateException
when you call the method executeBatch
if (1) one of the SQL statements you added to the batch produces a result set (usually a query) or (2) one of the SQL statements in the batch does not execute successfully for some other reason.executeBatch
时,您将获得BatchUpdateException
。
You should not add a query (a 您不应该将查询(SELECT
statement) to a batch of SQL commands because the method executeBatch
, which returns an array of update counts, expects an update count from each SQL statement that executes successfully. SELECT
语句)添加到一批SQL命令中,因为返回更新计数数组的方法executeBatch
希望成功执行的每个SQL语句都有一个更新计数。This means that only commands that return an update count (commands such as 这意味着只有返回更新计数的命令(如INSERT INTO
, UPDATE
, DELETE
) or that return 0 (such as CREATE TABLE
, DROP TABLE
, ALTER TABLE
) can be successfully executed as a batch with the executeBatch
method.INSERT INTO
、UPDATE
、DELETE
等命令)或返回0的命令(如CREATE TABLE
、DROP TABLE
、ALTER TABLE
)才能使用executeBatch
方法作为批处理成功执行。
A BatchUpdateException
contains an array of update counts that is similar to the array returned by the method executeBatch
. BatchUpdateException
包含更新计数数组,该数组类似于方法executeBatch
返回的数组。In both cases, the update counts are in the same order as the commands that produced them. 在这两种情况下,更新计数的顺序与生成它们的命令的顺序相同。This tells you how many commands in the batch executed successfully and which ones they are. 这将告诉您批处理中有多少命令成功执行,以及它们是哪些命令。For example, if five commands executed successfully, the array will contain five numbers: the first one being the update count for the first command, the second one being the update count for the second command, and so on.例如,如果成功执行了五个命令,数组将包含五个数字:第一个是第一个命令的更新计数,第二个是第二个命令的更新计数,依此类推。
BatchUpdateException
is derived from SQLException
. BatchUpdateException
是从SQLException
派生的。This means that you can use all of the methods available to an 这意味着您可以使用SQLException
object with it. SQLException
对象可用的所有方法。The following method, 以下方法JDBCTutorialUtilities.printBatchUpdateException
prints all of the SQLException
information plus the update counts contained in a BatchUpdateException
object. JDBCTutorialUtilities.printBatchUpdateException
打印所有SQLException
信息以及BatchUpdateException
对象中包含的更新计数。Because 由于BatchUpdateException.getUpdateCounts
returns an array of int
, the code uses a for
loop to print each of the update counts:BatchUpdateException.getUpdateCounts
返回int
数组,因此代码使用for
循环打印每个更新计数:
public static void printBatchUpdateException(BatchUpdateException b) { System.err.println("----BatchUpdateException----"); System.err.println("SQLState: " + b.getSQLState()); System.err.println("Message: " + b.getMessage()); System.err.println("Vendor: " + b.getErrorCode()); System.err.print("Update counts: "); int[] updateCounts = b.getUpdateCounts(); for (int i = 0; i < updateCounts.length; i++) { System.err.print(updateCounts[i] + " "); } }
Note: Not all JDBC drivers support inserting new rows with the :并非所有JDBC驱动程序都支持使用ResultSet
interface. ResultSet
接口插入新行。If you attempt to insert a new row and your JDBC driver database does not support this feature, a 如果尝试插入新行,而JDBC驱动程序数据库不支持此功能,则会引发SQLFeatureNotSupportedException
exception is thrown.SQLFeatureNotSupportedException
异常。
The following method, 以下方法CoffeesTable.insertRow
, inserts a row into the COFFEES
through a ResultSet
object:CoffeesTable.insertRow
通过ResultSet
对象将一行插入COFFEES
中:
public void insertRow(String coffeeName, int supplierID, float price, int sales, int total) throws SQLException { try (Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE)) { ResultSet uprs = stmt.executeQuery("SELECT * FROM COFFEES"); uprs.moveToInsertRow(); uprs.updateString("COF_NAME", coffeeName); uprs.updateInt("SUP_ID", supplierID); uprs.updateFloat("PRICE", price); uprs.updateInt("SALES", sales); uprs.updateInt("TOTAL", total); uprs.insertRow(); uprs.beforeFirst(); } catch (SQLException e) { JDBCTutorialUtilities.printSQLException(e); } }
This example calls the 此示例使用两个参数调用Connection.createStatement
method with two arguments, ResultSet.TYPE_SCROLL_SENSITIVE
and ResultSet.CONCUR_UPDATABLE
. Connection.createStatement
方法,即ResultSet.TYPE_SCROLL_SENSITIVE
和ResultSet.CONCUR_UPDATABLE
。The first value enables the cursor of the 第一个值使ResultSet
object to be moved both forward and backward. ResultSet
对象的游标能够前后移动。The second value, 如果要在ResultSet.CONCUR_UPDATABLE
, is required if you want to insert rows into a ResultSet
object; it specifies that it can be updatable.ResultSet
对象中插入行,则需要第二个值ResultSet.CONCUR_UPDATABLE
;它指定它是可更新的。
The same stipulations for using strings in getter methods also apply to updater methods.在getter方法中使用字符串的相同规定也适用于updater方法。
The method 方法ResultSet.moveToInsertRow
moves the cursor to the insert row. ResultSet.moveToInsertRow
将游标移动到插入行。The insert row is a special row associated with an updatable result set. 插入行是与可更新结果集关联的特殊行。It is essentially a buffer where a new row can be constructed by calling the updater methods prior to inserting the row into the result set. 它本质上是一个缓冲区,在将行插入结果集中之前,可以通过调用updater方法来构造新行。For example, this method calls the method 例如,此方法调用方法ResultSet.updateString
to update the insert row's COF_NAME
column to Kona
.ResultSet.updateString
将插入行的COF_NAME
列更新为Kona
。
The method 方法ResultSet.insertRow
inserts the contents of the insert row into the ResultSet
object and into the database.ResultSet.insertRow
将插入行的内容插入ResultSet
对象和数据库。
Note: After inserting a row with the :插入带有ResultSet.insertRow
, you should move the cursor to a row other than the insert row. ResultSet.insertRow
的行后,应将游标移动到插入行以外的行。For example, this example moves it to before the first row in the result set with the method 例如,本例使用ResultSet.beforeFirst
. ResultSet.beforeFirst
方法将其移动到结果集中第一行之前。Unexpected results can occur if another part of your application uses the same result set and the cursor is still pointing to the insert row.如果应用程序的另一部分使用相同的结果集,并且游标仍指向插入行,则可能会出现意外结果。