SQLite 通过 JDBC : SQLITE_BUSY when inserting after selecting

标签 sqlite jdbc

在从表中选择后尝试写入表时,我收到错误代码 SQLITE_BUSY。 select 语句和结果在插入之前已正确关闭。

如果我删除选择部分,则插入工作正常。这就是我没有得到的。根据文档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);
    }

这会在 intaffectedRows = stmtInsert.executeUpdate(); 上崩溃。现在,如果我删除第一个 block (并手动将一个值添加到 variablesToAdd 列表中),该值就会很好地插入到数据库中。

我错过了什么吗?我没有正确关闭ResultSet和PreparedStatement吗?也许是我看得太久而看不到自己的错误。

编辑:在单独的线程中执行选择也可以达到目的。但这并不是解决办法。在关闭之前的语句后,我是否试图太快地插入数据库?

Edit2:我遇到了 busy_timeout,它 promise 让更新/查询在返回 SQLITE_BUSY 之前等待指定的时间。我尝试像这样设置繁忙超时:

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

executeUpdate() 函数仍然立即返回 SQLITE_BUSY。

最佳答案

我傻了。 删除 select 语句有效(仍然不确定为什么有效,可能是时机不好)这一事实让我感到非常困惑,以至于我错过了使用同一文件的不同线程。

使两个线程使用相同的 java.sql.Connection,现在一切正常。

感谢您将我推向正确的方向@GordThompson。不知道导致我发现问题的 jdbc:sqlite::memory: 选项。

关于SQLite 通过 JDBC : SQLITE_BUSY when inserting after selecting,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54513666/

相关文章:

javascript - 将捕获的图像存储到 SQlite 数据库中? ( Cordova )

android - Android 上的 SQLite 如何处理长字符串?

Java PreparedStatement UTF-8字符问题

entity-framework - SQLite + Entity Framework 4.0 + Identity 列/Autoinc 不起作用

sqlite - 有没有办法通过 WSL2 以可视方式 (GUI) 探索 SQLite DB?

ruby-on-rails - Ruby Sqlite3 安装 sqlite3_libversion_number() macOS Sierra

java - Eclipse 和 postgres JDBC 连接

java - JDBC 准备好的语句与 Hibernate session 事务只读操作

java - JDBC 插入不起作用

java - 如何为 Hibernate 动态加载驱动程序?