1

我目前有一個數據庫類,PreparedStatement成員變量在構造函數中初始化。事情是這樣的:Java多線程和連接池與PreparedStatement

public class Database 
{ 
    private Connection connection; 
    private PreparedStatement statement1, statement2, ...; 

    public Database(String url, String user, String pass) 
    { 
     Class.forName("com.mysql.jdbc.Driver").newInstance(); 
     connection = DriverManager.getConnection(url, user, pass); 

     statement1 = connection.prepareStatement("sql stuff"); 
     statement2 = connection.prepareStatement("sql stuff"); 
     // etc 
    } 

    public User getUser(int userId) 
    { 
     // execute getUser statement 
    } 
    // and other similar methods 
} 

該應用程序將是多線程的,我想用C3P0連接池。但我不知道如何去做。

比方說,我創建了一個數據庫對象的每一個線程,並且構造現在得到從池中的連接。每個線程應該只調用其中一個方法(最多5個查詢),然後結束。我是否每次都必須初始化所有準備好的語句?如果是的話,不會花太長時間嗎?

有沒有更好的方法可以做到這一點?

+0

我不知道c3p0是否支持語句緩存,但有一些池可以。例如,[Tomcat JDBC池](https://tomcat.apache.org/tomcat-9.0-doc/jdbc-pool.html#org.apache.tomcat.jdbc.pool.interceptor.StatementCache)。有了這樣的池,您可以重新使用準備語句的代碼。如果像這樣的語句已被緩存,則緩存的副本將被返回而不會產生實際準備語句的成本。 – Ralf

+0

我剛剛檢查並且c3p0確實有語句緩存。這是否意味着如果我在一個連接中準備語句,並且另一個線程稍後從池中獲取另一個連接,那麼這些語句將已經準備好了嗎?或者他們是否必須爲泳池中的每個連接做好準備? – dluga

回答

0

一個連接池的優點是,它重新使用現有的連接,這東西你目前的實現並不做。所以問題「每次初始化所有準備好的陳述不需要太長時間?」並非真正相關,因爲每次創建新的數據庫連接最有可能比每次初始化準備好的語句花費更多的時間。即使準備好的語句每次都被初始化並且從不重複使用,我懷疑你會注意到任何性能差異,因爲執行數據庫語句花費的時間比初始化準備好的語句要長得多。

話雖這麼說,大多數JDBC驅動程序將有一個選項緩存預處理語句(即這並不完全取決於連接池)。請參閱MySQL配置選項herecachePrepStmts,prepStmtCacheSizeprepStmtCacheSqlLimit)。但請記住,這些優化「很好」,首先確保您的程序在多線程場景中正常工作(例如,確保始終將從池借用的連接返回到池,即使(運行時)例外發生)並且是maintainable

1

您需要使用它提供了連接池的方式,數據源,然後你應用程序從池中的連接。

您可以在應用程序啓動創建數據源綱領性像in this example也可以從網絡服務器控制檯配置(取決於Web服務器),然後通過JNDI

得到的數據源在您的應用程序

預編譯和DB-端緩存Prepared Statement導致整體執行速度更快,並且可以重用相同的SQL語句。

+0

我認爲這個問題是關於重複編寫陳述以及如何避免陳述的費用。不是如何使用連接池。 – Ralf

+0

他問'我想用c3p0來連接池。但我不知道如何去做。「但我也會澄清第二部分 –

+0

是的,我知道如何使用數據源。問題是如何組織它,以便它可以被多個線程使用,並且不會花太長時間處理這些語句。 – dluga