【问题标题】:JDBC SQL Database is locked?JDBC SQL 数据库被锁定?
【发布时间】:2013-03-23 23:11:14
【问题描述】:

我正在编写一个使用本地 SQL 数据库存储数据的程序。

我正在使用此处找到的驱动程序:https://bitbucket.org/xerial/sqlite-jdbc

我正在尝试从数据库中读取并将 tableName 的内容放入 JTable 中,如下所示:

public Object[][] getTable(String tableName){
    int columns = getColumnNumber(tableName);
    int rows = getRowNumber(tableName);
    String[] columnNames = getColumnNames(tableName);
    Object[][] table = new Object[rows][columns];
    try{
        Connection connection = DriverManager.getConnection("jdbc:sqlite:" + dbName + ".db");
        Statement stmt = connection.createStatement();
        ResultSet rs = stmt.executeQuery("select * from " + tableName);
        for(int r = 0; r < rows; r++){
            rs.next();
            for (int c = 0; c < columns; c++){
                table[r][c] = rs.getString(columnNames[c]);
            }
        }
        return table;           
    }catch(Exception e){
        System.out.println("ERROR CREATING TABLE ARRAY");
        e.printStackTrace();
        return null;
    }
}

稍后我尝试返回并在表格中添加一行:

public boolean addRow(String tableName, Object[] values){
    if(!isDataAcceptable(tableName, values))
        return false;
    try{
        String stmt = "insert into " + tableName + " values (";
        for(int c = 0; c < values.length; c++){
            if(values[c] instanceof String)
                stmt += "'" + values[c] + "'";
            else
                stmt += values[c];
            if(c == (values.length - 1))
                    stmt += ");";
            else
                stmt += ", ";
        }
        System.out.println(stmt);
        Connection connection = DriverManager.getConnection("jdbc:sqlite:" + dbName + ".db");
        Statement statement = connection.createStatement();
        statement.executeUpdate(stmt);
        return true;
    }catch(Exception e){
        System.out.println("ERROR INSERTING ROW");
        e.printStackTrace();
        return false;
    }
}

然后我想用新行更新我之前创建的 JTable。

当我尝试添加该行时,它会导致异常:

java.sql.SQLException: database is locked

指向线:

statement.executeUpdate(stmt);

...在 addRow() 方法中。

为什么数据库被锁定,我如何解锁它以写入它?

【问题讨论】:

  • 您不会关闭您创建的任何对象,ResultSetStatementConnection 都不会。我怀疑那是你的问题。
  • 我对 SQL 非常陌生,并假设因为它们是本地资源,所以当方法结束时它们会关闭。如何关闭它们?
  • 就像任何其他外部资源是 Java 一样,您需要在完成后调用 close()。通常使用try finally 模式。
  • 我将 .close() 添加到所有打开 Connection 或 ResultSet 并修复它的方法中。谢谢。

标签: java sql database sqlite


【解决方案1】:

为什么数据库被锁定,我如何解锁它以写入它?

数据库很可能被锁定在addRow,因为之前对getTable 的调用没有关闭结果集。该代码也无法关闭数据库连接对象,这将导致资源泄漏。

基本解决方法是在 rsconnection 对象上调用 close(),但您需要以正确的方式执行此操作以使您的代码可靠。

这是在 Java 7 中使用“try with resources”语法的推荐方法:

try (Connection connection = 
         DriverManager.getConnection("jdbc:sqlite:" + dbName + ".db"),
     Statement stmt = connection.createStatement(),
     ResultSet rs = stmt.executeQuery("select * from " + tableName)) {
  for (int r = 0; r < rows; r++) {
    rs.next();
    for (int c = 0; c < columns; c++) {
      table[r][c] = rs.getString(columnNames[c]);
    }
  }
  return table;           
} catch (Exception e) {
    System.out.println("ERROR CREATING TABLE ARRAY");
    e.printStackTrace();
    return null;
}

您也可以通过在 finally 块中显式调用 close 来执行此操作,但它更冗长,如果您有需要关闭的相关资源,则代码可能难以正确......比如在这里。

【讨论】:

    【解决方案2】:

    关闭数据库并重新打开它并尝试, 有时数据库查询在后台运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-28
      • 1970-01-01
      • 2015-11-22
      相关资源
      最近更新 更多