2011-09-02 82 views
12

可能重複:
when to close Connection, Statement, PreparedStatement and ResultSet in JDBC良好做法:JDBC連接

我寫了一個簡單的包裝了JDBC連接和它的作品,但我想用最好的實踐,以提高它儘可能。它基本上具有如下方法:open(),close(),isOpened(),select(), insert(), update(), delete()batch()。爲了簡單起見,我只會在這裏發佈前4種方法。

public class Query{ 
    private Connection con; 
    private PreparedStatement ps; 
    private ResultSet rs; 

    //Database.open() returns a Connection ready to use 
    public void open (Database database) throws DatabaseException, SQLException{ 
     if (!isOpened()){ 
      con = database.open(); 
     } 
    } 

    public void close() throws SQLException{ 
     if (isOpened()){ 
      if (ps != null) ps.close(); 
      con.close(); 
      con = null; 
     } 
    } 

    public boolean isOpened(){ 
     return con != null; 
    } 

    //The query string is the query without the word "select" and can use placeholders (?) 
    //The args param it's just an array owith the values of this placeholders 
    public ResultSet select (String query, Object[] args) throws SQLException{ 
     if (ps != null) ps.close(); 

     if (isOpened()){ 
      ps = con.prepareStatement ("select " + query); 
      if (args != null){ 
       for (int i=0; i<args.length; i++){ 
        ps.setObject (i+1, args[i]); 
       } 
      } 
      rs = ps.executeQuery(); 
     } 

     return rs; 
    } 
} 

注:

  • 相同的查詢對象可重複使用,例如打開和關閉 它,並且再次打開之後。
  • 我不關閉,每次查詢的連接,我只是關閉 準備好的語句(這是正確的或我可以離開制 語句打開,因爲Connection對象將關閉它?)
  • 當我關閉Connection,所有的PreparedStatement s和 他們的ResultSet s也都關了吧?

用法:

Database database; 

//Database initialization 

Query query = new Query(); 


query.open (database); 

ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" }); 
doSomethingWithResult1 (rs); 

//Connection is not closed here 

ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 }); 
doSomethingWithResult2 (rs); 

query.close(); 


query.open (database); 

ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" }); 
doSomethingWithResult1 (rs); 

//Connection is not closed here 

ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 }); 
doSomethingWithResult2 (rs); 

query.close(); 

你覺得呢?我應該在每次查詢後關閉並打開連接嗎?在同一連接上的每個查詢之後,我可以保留打開PreparedStatement嗎?這是一個很好的設計?

+7

關閉並重新打開每個查詢的連接是一個壞主意。建立連接真的非常昂貴。 – bdares

+1

然後,我可以離開打開PreparedStatement或者我應該關閉它的每個查詢? –

+0

您可以將所有內容保持打開狀態,直到您實際使用數據庫。關閉連接將追蹤並關閉它產生的所有東西(語句,結果集)。 – bdares

回答

12

您必須先關閉PreparedStatement,然後再在同一連接上創建新的PreparedStatement。我有嚴重的問題,因爲我沒有關閉PreparedStatements。事實證明,在數據庫服務器上有分配的資源,只有在顯式調用PreparedStatement.close()後才能分配資源。

由於bdares評論,連接應儘可能不頻繁地打開和關閉。

1

最佳選擇是:如果這些隊列是同一方法的一部分,並且每個查詢在使用後關閉PreparedStatement,則對所有查詢使用單個Connection對象。

1

使用連接池。所以你不要繼續創造。

+0

連接池是在初始化數據庫時創建的。我的database.open()方法返回的連接是來自池的連接,因爲我正在使用數據源。 –

5

連接池

使用連接池。應用程序中的每個事務都將從此池中獲取連接,執行所需的所有操作,回滾或提交併關閉連接(它會將連接返回到池)。

你可以給你一個查詢對象池的引用,打開將獲得連接,關閉將關閉它(實際上返回它)。

預處理語句

嘗試重用你準備好的聲明中類似的查詢。這樣數據庫將重用先前的查詢計劃,並且速度會更快。如果您正在執行大量相同表單的查詢,那麼它有很大的意義。

怎麼樣?

  • 保持最後PS開放
  • 如果您關閉連接或什麼的,關閉它
  • 如果查詢相同的查詢字符串比以前重用的PS保存
  • ,如果它是不一樣的查詢字符串...關閉它並創建一個新的