我正在使用CachedRowSet
。但是当我调用insertRow()
方法时,有一个SQLException
无法插入行。
这是我的代码:
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();
}
最佳答案
调用insertRow()
时,CachedRowSet
的参考实现将检查是否已填充所有必需的列,否则将引发异常(Grepcode CachedRowSet.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;
}
换句话说,当插入一行时,必须为所有不可为空的列提供一个值(包括主键)。似乎有两种方法可以解决此问题:
设置(随机)值。这确实要求始终生成主键(即使提供了值)。
使用
null
将列明确设置为updateNull
。使用setNull
不起作用:它会提供相同的错误,而使用setObject(idx, null)
会导致NullPointerException
当使用您的代码进行这些更改时,我在调用
SQLException
时得到一个acceptChanges
,因为该实现未禁用autoCommit
(它似乎是commented out),但是它确实显式调用了commit
(这是在autoCommit
中时无效)。这似乎并不容易解决,除非可以在execute
上显式提供连接或创建自己的实现。我认为这类问题实际上表明了
RowSet
实现实际上很少使用(否则它们早就已经被冲洗掉了)。但是请注意,如果这是您需要的实际代码,并且不需要
CachedRowSet
的断开连接的特性,那么您可以简单地使用可更新的结果集。