2013-03-23 81 views
3

我在寫一個使用本地SQL數據庫存儲數據的程序。JDBC SQL數據庫被鎖定?

我使用的驅動程序在這裏找到:https://bitbucket.org/xerial/sqlite-jdbc

我試圖從數據庫中讀取並把表名的內容複製到一個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()方法。

爲什麼數據庫被鎖定,我該如何解鎖才能寫入數據庫?

+0

您不關閉任何您創建的對象,既不是'ResultSet'也不是'Statement',也不''Connection'。我會懷疑那是你的問題。 – 2013-03-23 23:17:14

+0

我對SQL非常陌生,以爲它們是本地資源,它們在方法結束時會關閉。我如何關閉它們? – user1113827 2013-03-23 23:18:55

+0

就像其他任何外部資源是Java一樣,當你完成後你需要調用'close()'。通常使用'try finally'模式。 – 2013-03-23 23:20:38

回答

3

爲什麼數據庫被鎖定,我該如何解鎖才能寫入它?

該數據庫是最有可能鎖定在addRow因爲getTable以前調用沒有關閉的結果集。該代碼也無法關閉會導致資源泄漏的數據庫連接對象。

基本的解決辦法是呼籲rsconnection對象close(),但你需要做的是正確的方法,使你的代碼可靠。

這裏推薦的方式做到這一點在Java 7中使用「嘗試與資源」語法:

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明確地做到這一點,但它是更冗長,如果您有需要關閉的相關資源,代碼可能很難正確對待......就像這裏。