CachedRowSet не удалось вставить строку
Я использую 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();
}
2 ответа
Когда вы звоните 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 (включая первичный ключ). Кажется, есть два способа обойти это:
- Установка (случайного) значения. Это требует, чтобы ваш первичный ключ всегда генерировался (даже если указано значение).
- Явно устанавливая столбец в
null
с помощьюupdateNull
, С помощьюsetNull
не работает: он выдает ту же ошибку и используетsetObject(idx, null)
приводит кNullPointerException
При использовании вашего кода с этими изменениями я получаю SQLException
при звонке acceptChanges
так как реализация не отключает autoCommit
(кажется, было закомментировано), но это явно вызывает commit
(который недействителен, когда в autoCommit
). Это не легко решить, за исключением, может быть, явного подключения к execute
или создание собственной реализации.
Я думаю, что такого рода проблемы на самом деле показывают, как мало RowSet
Реализации на самом деле используются (в противном случае они уже давно бы были удалены).
Тем не менее, обратите внимание, что если бы это был именно тот код, который вам нужен, и вам не нужны отключенные характеристики CachedRowSet
, тогда вы можете просто использовать обновляемый набор результатов.
Пример:
beginAddRow(crs);
crs.updateString("TABLE_TYPE", "TABLE");
continueAddRow();
crs.updateString("TABLE_TYPE", "INDEX");
endAddRow();
static public CachedRowSet beginAddRow(CachedRowSet crs) throws SQLException {
crs.moveToInsertRow(); // onInsertRow = true
return crs;
}
static public CachedRowSet continueAddRow(CachedRowSet crs) throws SQLException {
crs.insertRow();
crs.moveToCurrentRow();
crs.moveToInsertRow();
return crs;
}
static public CachedRowSet endAddRow(CachedRowSet crs) throws SQLException {
crs.insertRow();
crs.moveToCurrentRow(); // onInsertRow = false;
crs.beforeFirst();
return crs;
}