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;
    }
Другие вопросы по тегам