结果集更新行不起作用
ResultSet update row is not working
我想在遍历结果集时更新结果集中的原始数据。以下是我的代码
try {
String query="SELECT * FROM smsmessage WHERE recipient = ? and sent_status = 'pending' LIMIT ? ";
PreparedStatement prepStmt = conn.prepareStatement(query);
prepStmt.setString(1,shortCode);
prepStmt.setInt(2, Integer.parseInt(batchSize));
ResultSet rs=prepStmt.executeQuery();
while (rs.next()) {
//update the selected message sent status to "sent" from "pending"
rs.updateString("sent_status","sent");
rs.updateRow();
}
} catch (SQLException e) {
log.error("MySQL exception",e);
}
这可能是什么原因?
我收到以下错误
com.mysql.jdbc.NotUpdatable: Result Set not updatable. This result set
must come from a statement that was created with a result set type of
ResultSet.CONCUR_UPDATABLE, the query must select only one table, can
not use functions and must select all primary keys from that table.
See the JDBC 2.1 API Specification, section 5.6 for more details.This
result set must come from a statement that was created with a result
set type of ResultSet.CONCUR_UPDATABLE, the query must select only one
table, can not use functions and must select all primary keys from
that table. See the JDBC 2.1 API Specification, section 5.6 for more
details.
如堆栈跟踪所示,您必须创建一个允许其结果集可更新的语句:
PreparedStatement prepStmt= conn.prepareStatement(query,
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
来自 ResultSet (http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html) 的 API:
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable. See ResultSet fields for other options.
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
嗯,你应该从仔细阅读错误文本开始:
com.mysql.jdbc.NotUpdatable
: Result Set not updatable. This result
set must come from a statement that was created with a result set
type of ResultSet.CONCUR_UPDATABLE
, the query must select only one
table, can not use functions and must select all primary keys from
that table. See the JDBC 2.1 API Specification, section 5.6 for more
details.
这意味着结果集不可更新。您无法更新不可更新的结果集。
它还表示此结果集必须来自使用结果集类型 ResultSet.CONCUR_UPDATABLE
创建的语句。这意味着您的声明 - 在本例中为 PreparedStatement
,必须使用该选项创建。
最后,它会将您定向到文档。 JDBC 2.1 有点过时了,你可以在通常的 J2SE 文档中找到所有相关数据。让我们从 ResultSet
的文档开始。它说:
A default ResultSet object is not updatable and has a cursor that
moves forward only. Thus, you can iterate through it only once and
only from the first row to the last row. It is possible to produce
ResultSet objects that are scrollable and/or updatable. The following
code fragment, in which con is a valid Connection object, illustrates
how to make a result set that is scrollable and insensitive to updates
by others, and that is updatable. See ResultSet fields for other
options.
它显示的代码片段是:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
所以你看,他们正在使用一个语句,你可以在其中添加两个参数,使你能够滚动浏览数据并更新它。但他们使用的是 Statement
而不是 PreparedStatement
。这也适用于 PreparedStatement
吗?
查看 PreparedStatement
文档对您没有多大帮助,但是等等,您正在使用连接对象来准备语句,也许它会对您有所帮助?
是的,确实有一个method in Connection
可以让你传递参数,就像例子中的Statement
。
PreparedStatement prepareStatement(String sql,
int resultSetType,
int resultSetConcurrency)
throws SQLException
所以现在你必须问问自己,我需要什么样的resultSetType
,什么样的resultSetConcurrency
?
您当前的问题不需要滚动您的陈述,因此您可以使用默认值。如果您查看 the documentation of the plain preparedStatement(String)
,您会看到:
Result sets created using the returned PreparedStatement
object will
by default be type TYPE_FORWARD_ONLY
and have a concurrency level of
CONCUR_READ_ONLY
. The holdability of the created result sets can be
determined by calling getHoldability()
.
...顺便说一下,这就是为什么您的初始准备语句不可更新的原因。但无论如何,它告诉你滚动类型的默认值是 TYPE_FORWARD_ONLY
.
更新呢,哪个是重要的部分?嗯,选项是 CONCUR_READ_ONLY
和 CONCUR_UPDATABLE
。所以你需要使用第二个。毕竟,这就是错误消息告诉您的内容。
结论:
你需要使用
PreparedStatement prepStmt = conn.prepareStatement(
query,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
这将为您提供一个可更新的结果集。
这是从您收到的错误消息中找到答案的方法。
我想在遍历结果集时更新结果集中的原始数据。以下是我的代码
try {
String query="SELECT * FROM smsmessage WHERE recipient = ? and sent_status = 'pending' LIMIT ? ";
PreparedStatement prepStmt = conn.prepareStatement(query);
prepStmt.setString(1,shortCode);
prepStmt.setInt(2, Integer.parseInt(batchSize));
ResultSet rs=prepStmt.executeQuery();
while (rs.next()) {
//update the selected message sent status to "sent" from "pending"
rs.updateString("sent_status","sent");
rs.updateRow();
}
} catch (SQLException e) {
log.error("MySQL exception",e);
}
这可能是什么原因?
我收到以下错误
com.mysql.jdbc.NotUpdatable: Result Set not updatable. This result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE, the query must select only one table, can not use functions and must select all primary keys from that table. See the JDBC 2.1 API Specification, section 5.6 for more details.This result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE, the query must select only one table, can not use functions and must select all primary keys from that table. See the JDBC 2.1 API Specification, section 5.6 for more details.
如堆栈跟踪所示,您必须创建一个允许其结果集可更新的语句:
PreparedStatement prepStmt= conn.prepareStatement(query,
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
来自 ResultSet (http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html) 的 API:
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable. See ResultSet fields for other options.
Statement stmt = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2"); // rs will be scrollable, will not show changes made by others, // and will be updatable
嗯,你应该从仔细阅读错误文本开始:
com.mysql.jdbc.NotUpdatable
: Result Set not updatable. This result set must come from a statement that was created with a result set type ofResultSet.CONCUR_UPDATABLE
, the query must select only one table, can not use functions and must select all primary keys from that table. See the JDBC 2.1 API Specification, section 5.6 for more details.
这意味着结果集不可更新。您无法更新不可更新的结果集。
它还表示此结果集必须来自使用结果集类型 ResultSet.CONCUR_UPDATABLE
创建的语句。这意味着您的声明 - 在本例中为 PreparedStatement
,必须使用该选项创建。
最后,它会将您定向到文档。 JDBC 2.1 有点过时了,你可以在通常的 J2SE 文档中找到所有相关数据。让我们从 ResultSet
的文档开始。它说:
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable. See ResultSet fields for other options.
它显示的代码片段是:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");
// rs will be scrollable, will not show changes made by others,
// and will be updatable
所以你看,他们正在使用一个语句,你可以在其中添加两个参数,使你能够滚动浏览数据并更新它。但他们使用的是 Statement
而不是 PreparedStatement
。这也适用于 PreparedStatement
吗?
查看 PreparedStatement
文档对您没有多大帮助,但是等等,您正在使用连接对象来准备语句,也许它会对您有所帮助?
是的,确实有一个method in Connection
可以让你传递参数,就像例子中的Statement
。
PreparedStatement prepareStatement(String sql,
int resultSetType,
int resultSetConcurrency)
throws SQLException
所以现在你必须问问自己,我需要什么样的resultSetType
,什么样的resultSetConcurrency
?
您当前的问题不需要滚动您的陈述,因此您可以使用默认值。如果您查看 the documentation of the plain preparedStatement(String)
,您会看到:
Result sets created using the returned
PreparedStatement
object will by default be typeTYPE_FORWARD_ONLY
and have a concurrency level ofCONCUR_READ_ONLY
. The holdability of the created result sets can be determined by callinggetHoldability()
.
...顺便说一下,这就是为什么您的初始准备语句不可更新的原因。但无论如何,它告诉你滚动类型的默认值是 TYPE_FORWARD_ONLY
.
更新呢,哪个是重要的部分?嗯,选项是 CONCUR_READ_ONLY
和 CONCUR_UPDATABLE
。所以你需要使用第二个。毕竟,这就是错误消息告诉您的内容。
结论:
你需要使用
PreparedStatement prepStmt = conn.prepareStatement(
query,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
这将为您提供一个可更新的结果集。
这是从您收到的错误消息中找到答案的方法。