JDBC“数据库表被锁定”错误

时间:2013-03-04 16:07:18

标签: 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语句。据我所知,即使运行检索查询,数据库表也会被锁定,以便在其他人尝试选择数据时无法更新表。但是如何解决这个问题,我无法确定。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

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

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

如果您绝对想直接使用jdbc,最佳做法仍然是在使用后关闭连接。如果您因为不明原因而希望保持读取连接的存在,我建议使用2个不同的用户,一个用户只能进行只读访问,另一个用于更新,每次通话后系统关闭连接。 在任何情况下,您必须在使用后正确释放连接和最终准备好的语句,否则您将尝试死锁和/或内存泄漏。

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