2012-12-15 25 views
2

我的恐懼是,我在理解Java中的連接池時遇到了一個根本性問題。Java連接池 - 垃圾回收或調用close()?

我使用IDBCDataSource作爲連接池。 在我的應用程序的入口點,我實例化一個BasicDataSource,例如setMaxActive = 50。該數據源的實例被傳遞到某些業務邏輯所使用的各種DAO中。

每個DAO調用getConnection(),但沒有調用一個close()。我的假設是,在不使用DAO後,垃圾收集器關閉連接。

我的問題是,我不斷用完連接(即等待可用連接的代碼)。

現在讓我們說我會在每個數據庫操作結束時添加一個close()調用。拋出異常會發生什麼。我必須捕獲DAO中的每個異常,確保關閉連接,然後重新拋出發生的異常!

- 當前的方法:

public class MyDAO { 
    private Connection con; 

    public MyDAO (DataSource ds) { 
      con = ds.getConnection();  
    }  

    public MyReturnClass execSomeQuery() throws SQLException { 
      String sql = String.format("SELECT * FROM foo"); 
      PreparedStatement ps = con.prepareStatement(sql); 
      ResultSet rs = ps.executeQuery(); 

      while (rs.next()) { 
       …  
       ... 
      }   

      return result; 
    } 
} 


public class MyAppLogic() { 
    DataSource ds; 

    public MyAppLogic(DataSource ds) { 
      this.ds = ds; 
    } 

    public void doSomeStuff() { 
      MyDAO myDAO = MyDAO(ds); 
      myDAO.execSomeQuery(); 
    } 
} 

回答

2

你需要讓他們在連接池返回close的連接。 GC不會在您的連接上致電關閉!

+0

這也意味着我需要捕捉每個異常,關閉連接,然後重新拋出異常? 這也意味着每個DAO方法都需要單獨獲取連接,而不是整個DAO類獲取一個連接。 getConnection()是否會導致開銷? –

+0

1)是抓住每一個連接2)那麼什麼?你沒有得到任何東西你的方式。池會重用連接 – Cratylus

2

您可以創建一個管理連接的包裝器或父類,以便您不必在每種方法中複製邏輯。這裏有一個例子(請注意,我沒有真正編譯或測試過)。

public interface DAOClass { 
    public void execSomeQuery() throws SQLException; 
} 

public class MyDAOWrapper { 
    private DAOClass dao; 
    private DataSource ds; 

    public MyDAOWrapper(DataSource ds, DAOClass dao) { 
     this.dao = dao; 
     this.ds = ds; 
    } 

    public void exec() throws SQLException { 
     Connection con = ds.getConnection(); 
     try { 
      dao.execSomeQuery(); 
     } 
     finally { 
      con.close(); 
     } 
    } 

} 

// usage 
    public void doSomeStuff() throws SQLException { 
     MyDAOWrapper dao = new MyDAOWrapper(ds, new MyDAO()); 
     dao.exec(); 
    } 

關於錯誤處理,您不需要重新拋出異常,除非您捕獲它。您的finally子句應該關閉連接(如果存在)並且退出時,異常將繼續傳播。

try { 
    do_something(); 
} 
finally { 
    cleanup(); 
    // throw is not necessary 
}