1

I'm using CachedRowSet. But when I call the insertRow() method, there is a SQLException failed to insert row.

Here is my code:

static final String DATABASE_URL = "jdbc:mysql://localhost:3306/javapos";
static final String USERNAME = "root";
static final String PASSWORD = "sbc";

public static void main (String [] agr) throws SQLException
{
    CachedRowSetImpl rs = new CachedRowSetImpl();
    rs.setUrl(DATABASE_URL);
    rs.setUsername(USERNAME);
    rs.setPassword(PASSWORD);

    rs.setCommand("select * from uom order by itemid");
    rs.execute();

    while(rs.next()){
        System.out.println(rs.getString("itemid") + "  -  " + rs.getString("uom"));
    }

    rs.moveToInsertRow();
    rs.updateString(2,"Sample code");
    rs.insertRow();
    rs.moveToCurrentRow();

    rs.acceptChanges();
}
4

1 回答 1

2

当您调用insertRow()时,参考实现CachedRowSet会检查是否已填充了所有必需的列,否则会引发异常(来自GrepcodeCachedRowSet.insertRow()的源代码,行号不完全匹配):

if (onInsertRow == false ||
        insertRow.isCompleteRow(RowSetMD) == false) {
    throw new SQLException(resBundle.handleGetObject("cachedrowsetimpl.failedins").toString());
}

检查在InsertRow.isCompleteRow(RowSetMetaData)

public boolean isCompleteRow(RowSetMetaData RowSetMD) throws SQLException {
    for (int i = 0; i < cols; i++) {
        if (colsInserted.get(i) == false &&
                RowSetMD.isNullable(i + 1) == ResultSetMetaData.columnNoNulls) {
            return false;
        }
    }
    return true;
}

换句话说,在插入一行时,您必须为所有不可为空的列提供一个值(这包括主键)。似乎有两种方法可以解决这个问题:

  • 设置(随机)值。这确实要求始终生成主键(即使提供了值)。
  • 将列显式设置为nullusing updateNull。使用setNull不起作用:它提供了相同的错误,并且使用setObject(idx, null)结果NullPointerException

当使用您的代码进行这些更改时,我SQLException在调用时得到一个,acceptChanges因为实现没有禁用autoCommit(它似乎已被注释掉),但它确实显式调用commit(在 in 时无效autoCommit)。这似乎并不容易解决,除非明确提供连接execute,或者创建您自己的实现。

我认为这类问题实际上表明了RowSet实际使用的实现有多么少(否则它们早就被淘汰了)。

但是请注意,如果这是您需要的实际代码并且不需要 的断开连接的特性CachedRowSet,那么您可以简单地使用可更新的结果集。

于 2014-09-13T11:32:57.140 回答