java - JDBC "database table is locked"错误

标签 java sqlite jdbc locking

我正在开发一个简单的 Java 库,它将提供数据库访问。目前我正在研究访问 SQLite。我有一个名为 SQlite.java 的类,它仅实现实例方法。下面是几个方法的实现:

public ResultSet retrieve(String query) {
    try {
        if (this.connection != null) {
            this.statement = this.connection.createStatement();
            return this.statement.executeQuery(query);
        }
    } catch (Exception e) {
        System.err.println("[ERROR] " + e.getMessage());
    }
    return null;
}

public ResultSet listTables() {
    try {
        return this.retrieve("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name");
    } catch (Exception e) {
        System.err.println("[ERROR] " + e.getMessage());
    }
    return null;
}

public boolean hasTable(String tableName) {
    try {
        ResultSet rs = this.listTables();
        while (rs.next()) {
            if (rs.getString(1).equals(tableName)) {
                return true;
            }
        }
    } catch (Exception e) {
        System.err.println("[ERROR] " + e.getMessage());
    }
    return false;
}

public void update(String query) {
    try {
        if (this.connection != null) {
            this.statement = this.connection.createStatement();
            this.statement.executeUpdate(query);
        }
    } catch (Exception e) {
        System.err.println("[ERROR] " + e.getMessage());
    }
}

public void dropTable(String tableName) {
    try {
        if (this.hasTable(tableName)) {
            this.update("DROP TABLE " + tableName); // TEST!
        } else {
            System.err.println("[ERROR] Table '" + tableName + "' not found!");
        }
    } catch (Exception e) {
        System.err.println("[ERROR] " + e.getMessage());
    }
}

当我测试 dropTable() 方法时,出现异常“数据库表已锁定”。我猜测这是由于可能在 hasTable() 方法中调用的非封闭 SELECT 语句造成的。据我所知,即使运行检索查询,数据库表也会被锁定,以便在其他人尝试选择数据时无法更新表。但如何解决这个问题,我不确定。有什么想法吗?

最佳答案

我不知道您的环境是什么,但您应该使用带有连接池的数据源,并检索和关闭每个事务的连接。

完美的方法可能是使用容器( Spring 或 Java EE 之一)并让他为您管理事务,这样您就不会介意正确管理 JDBC 资源。您还可以指定是否允许更新当前事务并管理其他事务属性,例如隔离。

如果您绝对想直接使用jdbc,最佳实践仍然是在使用后关闭连接。如果您出于不明原因更喜欢保持读取连接处于 Activity 状态,我建议使用 2 个不同的用户,一个被授予只读访问权限,另一个用于更新,其连接应在每次调用后系统地关闭。 在所有情况下,您都必须在使用后正确释放连接和最终准备好的语句,否则您将尝试死锁和/或内存泄漏。

比照。 http://javarevisited.blogspot.fr/2012/08/top-10-jdbc-best-practices-for-java.html

关于java - JDBC "database table is locked"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15205825/

相关文章:

postgresql - 无法在 postgres 的 bytea 字段中插入空值

java - 这个简单的字符串转义可以防止任何 SQL 注入(inject)吗?

java - JDK8调用方法时出现com.sun.jdi.InvocationException

mysql - 从 django 检索 mysql 输出 'manage.py sql appname'

java - Exception 子类中 `Super` 关键字的影响

android sqlite 时间戳列

android - 自定义 InfowindowAdapter 以添加来自 Content provider 的图像

java - Mockito UnfinishedStubbingException 与 when().thenReturn()

java - 如何在不同的 ImageView 中设置不同的裁剪图像

java - 当我请求操作时,是什么导致了此 NPE?