ResultSet更新行无效

Mal*_*tha 3 java mysql jdbc

我想循环遍历结果集时,在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节.

flo*_*flo 8

正如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字段.

   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)


Rea*_*tic 8

那么,您应该首先仔细阅读错误文本:

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_ONLYCONCUR_UPDATABLE.所以你需要使用第二个.毕竟,这就是错误消息告诉你的内容.

结论:

你需要使用

PreparedStatement prepStmt = conn.prepareStatement(
                                  query,
                                  ResultSet.TYPE_FORWARD_ONLY,
                                  ResultSet.CONCUR_UPDATABLE);
Run Code Online (Sandbox Code Playgroud)

这将为您提供可更新的结果集.

这是如何从您收到的错误消息中找到答案.