手写数据库连接池

最近复习JDBC的一些知识,看到C3P0连接池,虽然用过很多次,但是如果说具体原理和实现方法。一时半会竟然无法回答,于是把C3P0的内容看了一下,同时自己简单的按照这个思路去手写了一个数据库连接池。


先来整理一下思路,对数据库连接池进行一个总结。

在我们对数据库进行操作时,一般分为以下几个步骤.

  1. 加载数据库驱动
  2. 获得数据库资源
  3. 获得数据库连接
  4. 编写SQL语句
  5. 关闭数据库连接

在这种情况下,我们每当进行一次操作,都需要开启并关闭一次连接。这种对资源的申请操作是非常消耗时间的行为。通过简单的测试,每次消耗时间大约为0.3秒左右,但从数字上看来这个值并不是不可接受,但在高访问量的环境下,必会给服务器造成巨大的竞争。我们希望在高访问下,每个连接都能够发挥其最大价值,在该连接存在的情况下处理更多的问题,把每次开启关闭操作代价降到最低。

之前有过线程池操作,同理,连接池也是将其放入一个容器中,其中保存了多个连接,当我们需要使用时调出,在使用完毕后归还。虽然其长久存在占据了一部分内存空间,但减少了多次开启的时间消耗。


线程池的思路简单。我们需要找到一个存储connection的容器,这个容器应该具有这样几个特点。

  1. 存取方便,消耗小
  2. 能够动态扩容
  3. 能保持内存消耗更小

这样看来,LinkedList是一个非常适合的选项,存取快捷,并能从头部删除从尾部添加。当我们要实现getConnection功能时,只需要通过linkedList中removeFirst方法,即可获取头部并将链表中头部删除。使用完成后通过将其归还,重新储存进LinkedList中。

这里值得注意的一点是,我们在使用时应该对close方法进行重写,这点在很多博客中都有提到,重写后的close并不进行连接的断开,而是将其归还给线程池。而在C3P0中,由于对connection进行了二次封装,所有调用本类的close方法可以实现归还,而调用父类close方法则能够彻底断开连接。这是值得注意的一个地方。


package DataUtils;

import java.sql.Connection;
import java.util.LinkedList;


/*
 * 该类为JDBC连接池,通过配置文件加载完成后,直接从池中获取连接即可
 * 按照C3P0的设计想法,模仿其设计方式,重点为close方法的重写已经对于
 * 多余连接的关闭和自动创建新链接的使用.我们使用LinkedList来作为连接池的容器
 */
public class JDBCConnectionPool {
	private LinkedList<Connection> can = new LinkedList<>();
	/*
	 *首先获得数据库连接池的数据库资源,通过静态代码块进行配置 
	 *在该类进行初始化时即可完成加载,提高执行效率
	 */
	private static Source dataSource;
	static {
		/*
		 * 通过静态代码块加载数据库资源,为连接池
		 * 之后的获取提供帮助
		 */
		dataSource = new Source();
		dataSource.setDriver("com.mysql.jdbc.Driver");
		dataSource.setPassword("jdbc:mysql://127.0.0.1/userinformation");
		dataSource.setUserName("root");
		dataSource.setPassword("root");
		
	}
	/*
	 * 连接池数量计数器
	 */
	private int connectionCounter = 0;//初始状态为0
	/*
	 * 初始连接数量,创建开始时池内链接数量
	 * 默认连接池内连接数量为5个,可以通过初始化构造器以及Set方法设定该容量
	 */
	private int initialConnectionNum = 5 ;
	/*
	 * 连接池连接最小闲置数量,当到达改数量时连接池将自动扩容
	 */
	private int MinConnectionNum = 2;
	/*
	 * 连接池汇总最大连接数量,当到达该值后,将不再创建新的连接,
	 * 同时通过返回值提交信息。
	 */
	private int MaxConnectionNum = 10;
	/*
	 * 数据库配置文件读取地址
	 * 数据库连接驱动
	 * 数据库账号密码
	 */
	//private String configFileUrl;
	private String DataDriver;
	private String userName;
	private String passWord;
	private String DataSourceUrl;
	
	public JDBCConnectionPool() {
		//空参数构造器,可以通过直接创建后进行set的设置方法进行设置
		/*
		 * 初始化连接池内连接
		 * 在创建完成时内部含有五个连接
		 */
		for(int i = 0; i< initialConnectionNum; i++) {
			Connection con = dataSource.getConnection();
			can.add(con);
		}
	}
	
	public JDBCConnectionPool(String DataDriver,String userName,String passWord,String DataSourceUrl) {
		this.DataDriver = DataDriver;
		this.userName = userName;
		this.passWord = passWord;
		this.DataSourceUrl = DataSourceUrl;
	}
	
	/*
	 * 获取连接
	 */
	public Connection getConnection() {
		/*
		 * 在每次获取资源时,
		 */
		if(can.size() < MinConnectionNum) {
			for(int i = 0;i<MinConnectionNum;i++) {
				Connection con = dataSource.getConnection();
				can.add(con);
			}
		}
		/*
		 * 该操作即为从链表中获取链接
		 */
		Connection con = null;
		if(con == null) {
			//当连接为空时,我们从链表头部取出一个连接并将链表头部删除
			con = can.removeFirst();
			return con;}
		else {
			//当链表不为空时,直接返回连接
			return con;
		}
	}
	/*
	 * close方法能够返还资源并存入LinkedList中
	 * 
	 */
	public void close() {
		//对于二次封装的connection类中的close方法进行重新
		/*
		 * 执行该方法的类应为connection,对其方法进行重写即可完成要求
		 * 将连接重新放入链表中,此时出现在链表尾部,这样相当于将连接返回
		 * 下次再获得时,将得到头部连接
		 */
	}
	
	/*
	 * 对于连接池初始化的各种方法
	 */
	public void setDataDriver(String DataDriver) {
		this.DataDriver = DataDriver;
	}
	
	public void setUserName(String userName) {
		this.userName = userName;
	}
	
	public void setPassword(String password) {
		passWord = password;
	}
	
	/*
	 * 设置最大连接数等属性的各种方法
	 */
	
	public void setInitialConnectionNum(int InitialConnectionNum) {
		initialConnectionNum = InitialConnectionNum;
	}
	
	public void setMinConnectionNum(int MinConnectionNum) {
		this.MinConnectionNum = MinConnectionNum;
	}
	
	public void setMaxConnectionNum(int MaxConnectionNum) {
		this.MaxConnectionNum = MaxConnectionNum;
	}
	
	
	
}

以上是代码实现,通过static代码块的形式,在类加载时便对数据库资源完成初始化,实际上这一步也可以在申请connection时完成。其中并没有太难的操作,更多的是把思路理解清楚即可。

close操作

public void close(){
    //调用该方法的应为connection,所有使用this关键字
    //直接将调用者存储进linkedList即可完成归还
    can.add(this);
}

猜你喜欢

转载自blog.csdn.net/weixin_41582192/article/details/82427465
今日推荐