一般我们这样写一个数据库数据池的应用代码。
public class ConnectionPool {
private static ComboPooledDataSource dataSource;
public ConnectionPool() {
try {
dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("gao");
dataSource
.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=GB2312");
dataSource.setDriverClass("com.mysql.jdbc.Driver ");
dataSource.setInitialPoolSize(2);
dataSource.setMinPoolSize(1);
dataSource.setMaxPoolSize(10);
dataSource.setMaxStatements(50);
dataSource.setMaxIdleTime(60);
} catch (PropertyVetoException e) {
throw new RuntimeException(e);
}
}
public final static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException("无法从数据源获取连接 ", e);
}
}
}
进入getConnection()方法后,可以看到如下的代码。
public Connection getConnection() throws SQLException
{
PooledConnection pc = getPoolManager().getPool().checkoutPooledConnection();
return pc.getConnection();
}
这里有三个重要的类,也是三个重要函数的调用。C3P0PooledConnectionPoolManager是连接池的管理类,C3P0PooledConnectionPool是连接池类,BasicResourcePool是真正管理数据库连接池的类。分别对应getPoolManager()、getPool()、checkoutPooledConnection()这三个方法。
在初始化时,调用getPool()时,往下调用,会调用recheckResizePool()这个方法。 在BasicResourcePool中,会调用expandPool(initCount)这个方法,其中的参数是配置文件中设置的初始化连接数,然后在AcquireTask这个线程中执行doAcquire()方法,doAcquire()方法会acquireResource()方法,acquireResource()方法会拿到一个连接,并且这个连接会通过assimilateResource()方法放到unused(LinkedList)集合中。
接着调用checkoutPooledConnection()这个方法,从 unused集合中获取一个连接。这个方法里面有大量的判断逻辑,连接数是否到达最大,如何扩容等等。
上面只是简单分析初始化和连接的过程,其实c3p0整个逻辑还是比较复杂的,考虑的情况比较多,还有大量的线程检测等等。