SQLite через JDBC: SQLITE_BUSY при вставке после выбора - PullRequest
0 голосов
/ 04 февраля 2019

Я получаю код ошибки SQLITE_BUSY при попытке записи в таблицу после выбора из нее.Оператор выбора и результат правильно закрываются перед моей вставкой.

Если я удаляю выбранную часть, вставка работает нормально.И это то, что я не получаю.В соответствии с документацией SQLITE_BUSY должно означать, что другой процесс или соединение (что здесь определенно не так) блокирует базу данных.

Нет запущенного менеджера SQLite.Также jdbcConn является единственным подключением к базе данных, которое у меня есть.Также нет параллельных потоков.

Вот мой код:

    try {
        if(!jdbcConn.isClosed()) {
            ArrayList<String> variablesToAdd = new ArrayList<String>();

            String sql = "SELECT * FROM VARIABLES WHERE Name = ?";

            try (PreparedStatement stmt = jdbcConn.prepareStatement(sql)) {
                for(InVariable variable : this.variables.values()) {
                    stmt.setString(1, variable.getName());
                    try(ResultSet rs = stmt.executeQuery()) {
                        if(!rs.next()) {
                            variablesToAdd.add(variable.getName());                 
                        }
                    }
                }
            }

            if(variablesToAdd.size() > 0) {
                String sqlInsert = "INSERT INTO VARIABLES(Name, Var_Value) VALUES(?, '')";
                try(PreparedStatement stmtInsert = jdbcConn.prepareStatement(sqlInsert)) {
                    for(String name : variablesToAdd) {
                        stmtInsert.setString(1, name);
                        int affectedRows = stmtInsert.executeUpdate();

                        if(affectedRows == 0) {
                            LogManager.getLogger().error("Error while trying to add missing database variable '" + name + "'.");
                        }
                    }
                }

                jdbcConn.commit();
            }
        }
    }
    catch(Exception e) {
        LogManager.getLogger().error("Error creating potentially missing database variables.", e);
    }

Это происходит при int affectedRows = stmtInsert.executeUpdate();.Теперь, если я удалю первый блок (и вручную добавлю значение в список variablesToAdd), это значение будет вставлено в базу данных.

Я что-то упустил?Правильно ли я закрываю ResultSet и PreparedStatement?Может быть, я не замечаю своей ошибки, потому что смотрю на нее слишком долго.

Редактировать: Выполнение выбора в отдельном потоке делает свое дело.Но это не может быть решением.Пытаюсь ли я вставить в базу данных слишком быстро после закрытия предыдущих операторов?

Edit2: я столкнулся с busy_timeout, который обещал заставить обновления / запросы ждать определенное количество времени, прежде чем вернуться с SQLITE_BUSY.Я попытался установить тайм-аут занятости следующим образом:

if(jdbcConn.prepareStatement("PRAGMA busy_timeout = 30000").execute()) {
    jdbcConn.commit();
}

Функция executeUpdate() по-прежнему возвращается с SQLITE_BUSY.

1 Ответ

0 голосов
/ 05 февраля 2019

Я тупой.Я был настолько сбит с толку тем фактом, что удаление оператора select сработало (все еще не уверен, почему это сработало, возможно, неправильное время), что я пропустил другой поток, используя один и тот же файл.

Сделал так, чтобы оба потока использовали одну и ту же Java.sql.Connection и теперь все работает нормально.

Спасибо, что подтолкнули меня в правильном направлении @GordThompson.Не знал о параметре jdbc:sqlite::memory:, который привел меня к поиску проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...