2013-03-04 125 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