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