2013-03-04 93 views
0

我正在开发一个简单的Java库,它将提供数据库访问。目前我正在访问SQLite。我有一个名为SQlite.java的类,它只实现实例方法。下面是几个方法的实现:JDBC“数据库表被锁定”错误

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

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

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

如果您绝对想直接使用jdbc,最佳实践仍然是在使用后关闭连接。如果您偏好使用晦涩的理由让您的读取连接保持活跃状态​​,我会建议使用2个不同的用户,一个授予只读访问权限,另一个授权用于更新,每次调用后系统应关闭连接。 在任何情况下,您必须在使用后妥善释放连接和最终准备好的语句,否则您将尝试死锁和/或内存泄漏。

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

+0

我正在研究Hibernate。 – temelm 2013-03-04 17:32:38

+0

但是,如果我直接使用JDBC,我是否必须使用静态方法(这将打开与数据库的连接,运行给定查询并关闭连接)?目前,我正在使用一个java.sql.Connection实例变量的对象类,它并不真正关闭。 – temelm 2013-03-04 17:34:55

+0

Imho确实是最好的做法。您可以打开连接并将其用于所有对话,但在对话结束时必须将其关闭。无论如何,在每次使用之后通过关闭资源来确保资源的释放更容易,否则使用像Spring这样的容器来委派工作。 – Gab 2013-03-05 08:19:56