为什么使用连接池
应用程序与底层DB进行通信连接时间过长,可能大于执行sql的时间。
为了减少性能开销,使用连接池管理连接。
数据源有三种方式
转载地址:https://blog.youkuaiyun.com/yue_cui_wu/article/details/82627770
https://www.cnblogs.com/yixiu868/p/8142986.html
三种方式都是通过不同数据源工厂进行数据源创建。
1、pooledDataSource 使用连接池的数据源
public Connection getConnection() throws SQLException {
return popConnection(dataSource.getUsername(), dataSource.getPassword()).getProxyConnection();
}
public Connection getConnection(String username, String password) throws SQLException {
return popConnection(username, password).getProxyConnection();
}
执行popConnection()获取连接:
a) 先检查空闲的连接池(被封装后存储在idle列表中)是否有空闲的连接,如果有,直接返回conn,并将conn移除idle列表;否则执行b操作
b) 检查活跃的连接池(被封装后存储在active列表中)是否小于设置值,如果小于,则创建一个新的连接返回,并放到active列表中。如果大于设置值,则进行步骤c
c) 检查活跃的列表中最早连接是否过期。
如果有,最大检出时间大于当前时间,逾期连接数+1,使用连接列表移除此连接;随后如果连接不是自动提交,则进行回滚操作,使用旧的连接数据重新创建新的连接,同时将过期的连接设置为invalid;
如果没有则根据设置的等待时间进行等待。
d) 活动连接后,需要对连接进行pingConnection处理。
如果不是坏连接,设置连接代码,是由url+username+password,进行hashcode获得的int类型的值。并将设置被检查时间以及最后使用时间。最后添加到活跃列表中去;
否则坏连接数量+1。
e) 如果获取的一直是坏连接,且坏连接数> 空闲连接+3,则抛出异常。
获取PoolConnection或执行getProxyConnection方法返回connection。
2、unpooledDataSource
每次获取连接都需要进行创建。
3、jndiDataSource
连接池数据源管理连接
1、创建连接
先创建PoolConnection,然后调用getProxyConnection方法进行connection创建。
2、conn回收
通过代理模式,进行回收;
由于数据库连接池需要循环使用数据库连接,所以不会真正关闭连接,而是将连接放回连接池中。
也是使用PoolConnection类中的代理对象proxyConnection,调用closed方法,实际是将连接放回连接池中。
public PooledConnection(Connection connection, PooledDataSource dataSource) {
this.hashCode = connection.hashCode();
this.realConnection = connection;
this.dataSource = dataSource;
this.createdTimestamp = System.currentTimeMillis();
this.lastUsedTimestamp = System.currentTimeMillis();
this.valid = true;
this.proxyConnection = (Connection) Proxy.newProxyInstance(Connection.class.getClassLoader(), IFACES, this);
}
实际上,我们调用PooledDataSource的getConnection()方法返回的就是这个proxyConnection对象。
当我们调用此proxyConnection对象上的任何方法时,都会调用PooledConnection对象内invoke()方法。
创建连接时间
在执行sql的时候才会去获取连接。