我想循环遍历结果集时,在ResultSet中更新raw.以下是我的代码
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);
}
Run Code Online (Sandbox Code Playgroud)
这应该是什么原因?
我收到了以下错误
com.mysql.jdbc.NotUpdatable:结果集不可更新.此结果集必须来自使用ResultSet.CONCUR_UPDATABLE结果集类型创建的语句,查询必须只选择一个表,不能使用函数,并且必须从该表中选择所有主键.有关更多详细信息,请参阅JDBC 2.1 API规范,第5.6节.此结果集必须来自使用ResultSet.CONCUR_UPDATABLE结果集类型创建的语句,查询必须只选择一个表,不能使用函数并且必须全部选择该表中的主键.有关更多详细信息,请参阅JDBC 2.1 API规范,第5.6节.
正如stacktrace所说,你必须创建一个允许其结果集可更新的语句:
PreparedStatement prepStmt= conn.prepareStatement(query,
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
Run Code Online (Sandbox Code Playgroud)
从ResultSet的API(http://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html):
默认的ResultSet对象不可更新,并且只有一个向前移动的游标.因此,您只能迭代一次,并且只能从第一行到最后一行.可以生成可滚动和/或可更新的ResultSet对象.以下代码片段(其中con是有效的Connection对象)说明了如何使结果集可滚动且对其他人的更新不敏感,并且是可更新的.有关其他选项,请参阅ResultSet字段.
Run Code Online (Sandbox Code Playgroud)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:结果集不可更新.此结果集必须来自使用结果集类型创建的语句,ResultSet.CONCUR_UPDATABLE查询必须只选择一个表,不能使用函数,并且必须从该表中选择所有主键.有关更多详细信息,请参阅JDBC 2.1 API规范,第5.6节.
这意味着结果集不可更新.您无法更新不可更新的结果集.
它还说该结果集必须来自使用结果集类型创建的语句ResultSet.CONCUR_UPDATABLE.这意味着您的语句(在本例中为a PreparedStatement)必须使用该选项创建.
最后,它会引导您进入文档.JDBC 2.1有点过时,您可以在通常的J2SE文档中找到所有相关数据.让我们从文档开始ResultSet.它说:
默认的ResultSet对象不可更新,并且只有一个向前移动的游标.因此,您只能迭代一次,并且只能从第一行到最后一行.可以生成可滚动和/或可更新的ResultSet对象.以下代码片段(其中con是有效的Connection对象)说明了如何使结果集可滚动且对其他人的更新不敏感,并且是可更新的.有关其他选项,请参阅ResultSet字段.
它显示的代码片段是:
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
Run Code Online (Sandbox Code Playgroud)
所以你看,他们正在使用一个语句,你可以在其中添加两个参数,使你可以滚动数据并更新它.但他们使用的是一个Statement而不是一个PreparedStatement.这也适用PreparedStatement吗?
转到PreparedStatement文档对你没有多大帮助,但是等等,你正在使用连接对象来准备语句,也许它对你有帮助吗?
是的,确实有一种方法Connection可以让你传递参数,就像Statement在例子中一样.
PreparedStatement prepareStatement(String sql,
int resultSetType,
int resultSetConcurrency)
throws SQLException
Run Code Online (Sandbox Code Playgroud)
所以现在你必须问自己,resultSetType我需要什么样的,什么样的resultSetConcurrency?
您当前的问题不需要滚动语句,因此您可以使用默认值.如果你查看普通文档,preparedStatement(String)你会看到:
使用返回的
PreparedStatement对象创建的结果集默认为type,TYPE_FORWARD_ONLY并且具有并发级别CONCUR_READ_ONLY.可以通过调用来确定创建的结果集的可保持性getHoldability().
...顺便说一句,这就是为什么你的初始预备声明不可更新的原因.但无论如何,它告诉你滚动类型的默认值是TYPE_FORWARD_ONLY.
如何更新,这是重要的部分?嗯,选项是CONCUR_READ_ONLY和CONCUR_UPDATABLE.所以你需要使用第二个.毕竟,这就是错误消息告诉你的内容.
你需要使用
PreparedStatement prepStmt = conn.prepareStatement(
query,
ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
Run Code Online (Sandbox Code Playgroud)
这将为您提供可更新的结果集.
这是如何从您收到的错误消息中找到答案.
| 归档时间: |
|
| 查看次数: |
5577 次 |
| 最近记录: |