前言

今天来讲一下数据库连接池技术.其实这个名词也就是听起来高大上一点,实际上并不是很复杂的内容,相信在我的讲解下,并且自己实际的将代码写一遍之后,能够对这项技术有较为深刻的理解.废话不多说,开始讲解.

数据库连接池技术概述

所谓的数据库连接池技术,就是用来分配,管理,释放数据库连接的.你也许会问,好像我直接用JDBC也能够实现这些功能吧.
嗯,你说的没错,JDBC确实也可以,但是,你记不记得,我们使用JDBC技术的时候,每次用完了,是不是都会将连接关闭;等到下一次再用的时候,是不是都得将数据库连接再打开?
实际上,数据库链接资源是十分宝贵的,我们在小型的项目中还看不出来,在高并发的项目中,你会发现,这样频繁的打开和关闭数据库链接是对服务器的一种摧残,十分影响效率.
那么,数据库连接池是如何做的呢?
实现思路是这样的:在每次有访问的时候,数据库连接池会给用户分配一个数据库连接,当用户用完了连接之后,连接池再将连接回收,放回一个连接集合中.
原理就是这样的,我们来看一下这张图加深印象

这样你可能还是不太清楚,而且,数据库连接池要考虑的东西要比上面说的更复杂,不过不要害怕,我通过实际的代码来帮你理解一下.
备注:下面的代码是自己实现一个简单的数据库连接池,着重了解数据库连接池的原理.

自己实现一个数据库连接池

注意:下面的代码我是分块讲解的,你一个个粘贴下来,最后肯定也是能运行的,为了方便,我会在讲完之后,给出完整的实现代码.

  • 定义初始化连接数目,最大连接数以及当前已经连接的数目
    一开始,当数据库连接池启动的时候,为了实现上面的需求,我们肯定是要先给出几个已经完成的连接的,这样用户访问的时候就能直接拿到了;此外,当某一段时间的访问用户超过我定义的连接池中的连接个数,肯定是要额外新建连接给用户使用;当然,这个新建的连接肯定是不能无限制的,否则还是会很影响效率的,所以,我们还要定义最大的连接数.
private final int init_count = 3; //初始化链接数目
private final int max_count = 6; //最大连接数
private int current_count = 0; //到当前连接数
  • 那么,我们一开始新建的连接池要放在哪里供用户使用呢?肯定是要创建一个连接集合的,这样的操作比较方便.至于为什么要使用LinkedList这样一个集合,一会就会介绍的.
private LinkedList<Connection> pool = new LinkedList<Connection>();
  • 刚才说了,一开始我们肯定是要初始化连接给用户使用的,那么,就需要在连接池启动的时候就新建一定数量的链接.分析后发现,放在构造函数中初始化链接是最好不过的了,最后再将连接放在链接集合中.
 //构造函数,初始化链接放入连接池public MyPool() {for (int i=0;i<init_count;i++){//记录当前连接数current_count++;//createConnection是自定义的创建链接函数.Connection connection = createConnection();pool.addLast(connection);}}
  • 创建一个新的连接,这个就没啥好说的了,毕竟你要的链接都是从这来的.
public Connection createConnection() {Class.forName("com.mysql.jdbc.Driver");Connection connection =DriverManager.getConnection("jdbc:mysql://localhost:3306/keyan","root","root");return connection;
}
  • 获取链接
    当用户来访问的时候,我们肯定是要给用户一个连接的,如果池中没有连接了(所有连接均被占用),那么就要创建新的连接,使用createConnection()函数,当然,这个连接的个数肯定是不能超过最大连接数的.如果不满足这两个条件,那么直接抛出异常.
public Connection getConnection() {if (pool.size() > 0){//removeFirst删除第一个并且返回//现在你一定看懂了我说的为什要用LinkedList了吧,因为下面的这个//removeFirst()方法会将集合中的第一个元素删除,但是还会返回第一个元素//这样就省去了我们很多不必要的麻烦return pool.removeFirst();}if (current_count < max_count){//记录当前使用的连接数current_count++;//创建链接return createConnection();}throw new RuntimeException("当前链接已经达到最大连接数");
}
  • 释放资源
    当用户使用完了连接之后,我们要做的并不是关闭连接,而是将连接重新放入资源池LinkedList之中,这样就省去了一遍又一遍的连接关闭.这个就是连接池的核心内容.是不是很简单?
 public void releaseConnection(Connection connection){if (pool.size() < init_count){pool.addLast(connection);current_count--;}else {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}
}

整个的实现过程就是这样的,下面我把全部的代码贴出来,方便大家学习.

//单元测试
@Test
public class MyPool {private final int init_count = 3; //初始化链接数目private final int max_count = 6; //最大private int current_count = 0; //到当前连接数//连接池,用来存放初始化链接private LinkedList<Connection> pool = new LinkedList<Connection>();//构造函数,初始化链接放入连接池public MyPool() {for (int i=0;i<init_count;i++){//记录当前连接数current_count++;Connection connection = createConnection();pool.addLast(connection);}}//创建新的连接public Connection createConnection() {try {Class.forName("com.mysql.jdbc.Driver");Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/keyan","root","root");return connection;}catch (Exception e){System.out.println("数据库链接异常");throw new RuntimeException();}}//获取链接public Connection getConnection() {if (pool.size() > 0){//removeFirst删除第一个并且返回return pool.removeFirst();}if (current_count < max_count){//记录当前使用的连接数current_count++;//创建链接return createConnection();}throw new RuntimeException("当前链接已经达到最大连接数");}//释放链接public void releaseConnection(Connection connection){if (pool.size() < init_count){pool.addLast(connection);current_count--;}else {try {connection.close();} catch (SQLException e) {e.printStackTrace();}}}
}

自己跑了一遍代码之后,你是不是发现原来看起来很复杂的技术,并不像我们想得那样?
好了,介绍完了基本的数据库连接池技术原理之后,我们就要介绍两个开源的优秀的数据连接池技术.
其实,真正的数据库连接池要考虑的东西比我们刚才写的这玩意复杂,现阶段不需要我们写这样复杂的东西,不过如果你感兴趣的话,可以看看数据库连接池的源代码--没错,这两个连接池都是开源的.OK,接下来就开始吧!

优秀的数据库连接池

首先,sun公司规定,连接池技术需实现javax.sql.DataSource接口,也就是说,如果你要自己实现数据库连接池,那么就必须实现这个接口.是不是很牛比的样子,实际上,作为标准制定方,sun公司还是有很多要求的,这是作为标准制定者的权利,所以,企业或者国家往往会对一些关键技术标准的制定打得头破血流.额,扯远了...

DBPC

其实,你可能不知道,如果你的tomcat经过特殊的配置,也是可以作为数据库连接池使用的,因为tomcat内置的就是DBPC…
想要使用DBPC,你必须导入三个jar文件:commons-dbcp2-2.2.0.jar,commons-pool2-2.5.0.jar,commons-logging-1.2.jar.我想,以你的聪明才智,想要获取这三个jar文件,一定是小菜一叠,这是一个软件开发者的必备技能--学会如何搜索.
使用起来就非常简单了.使用的方式主要有两种,一种是硬编码的方式,就是自己手动设置各种参数,另外一种就是配置相应的配置文件,然后载入就行了.

硬编码实现DBPC

BasicDataSource dataSource = new BasicDataSource();
//参数配置:初始化连接数,最大连接数,连接字符串,驱动,用户,密码
dataSource.setInitialSize(3);   //最大初始化链接
dataSource.setMaxTotal(6);      //最大链接
dataSource.setMaxIdle(3000);    //最大空闲时间
dataSource.setUrl("jdbc:mysql:///keyan");   //url
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword("root");//获取链接
Connection connection = dataSource.getConnection();
connection.prepareStatement("SELECT * FROM e_person").execute();
connection.close();

使用查询的时候,只需要按照原来JDBC的操作方式就行了,这个没啥好说的,按照我上面的配置方式实现就行了,一定不要忘记导入包.

配置文件方式实现

//创建properties配置文件
Properties properties = new Properties();
//获取文件流
InputStream in = DBCPTest.class.getResourceAsStream("db.properties");
//加载配置文件
properties.load(in);
//创建数据源对象
BasicDataSource dataSource = BasicDataSourceFactory.createDataSource(properties);//获取链接
Connection connection = dataSource.getConnection();
ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_person").executeQuery();
while (resultSet.next()){System.out.println(resultSet.getString("work_name"));
}
connection.close();

上面是基本的操作流程,下面我们看一下这个xml文件的配置
文件db.properties

url=jdbc:mysql:///keyan
driverClassName=com.mysql.jdbc.Driver
username=root
password=root
initialSize=3
maxActive=6
maxIdle=3000

特别要注意的一点是,这个配置文件一定要放在和你的这DBPC类放在同一个包下.
都完成了之后,直接用就可以了.

C3P0

c3p0同样是非常优秀的连接池技术,这个需要导入的文件比较少,只有一个c3p0-0.9.1.2.jar.自己去网站上找一下就好了.
使用c3p0同样是有两种方式,分别也是硬编码方式和配置文件方式.

硬编码方式

//配置相关的参数
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setJdbcUrl("jdbc:mysql:///keyan");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setUser("root");
dataSource.setPassword("root");
dataSource.setInitialPoolSize(3);
dataSource.setMaxPoolSize(6);
dataSource.setMaxIdleTime(1000);Connection connection = dataSource.getConnection();
//sql语句
ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_project").executeQuery();
while (resultSet.next()){System.out.println(resultSet.getString("project_name"));
}
connection.close();

和上面一样,简单的使用一下就行了,知道如何使用就行.至于更加深层次的东西,有兴趣的话慢慢研究吧.

配置文件方式

ComboPooledDataSource dataSource = new ComboPooledDataSource();
Connection connection = dataSource.getConnection();
ResultSet resultSet = connection.prepareStatement("SELECT * FROM e_project").executeQuery();
while (resultSet.next()){System.out.println(resultSet.getString("project_name"));
}
connection.close();

乍一看,你可能会问,不是配置文件方式实现吗?没错,只是这个是隐式的调用,不需要你实现,只需要新建一个ComboPooledDataSource对象就行了,默认调用xml文件,文件路径是src根目录.也就是说,你只需要将配置文件写在src目录下就行了.重点是如何写这个xml文件.
注意,文件名c3p0-config.xml,这个文件名不能改,必须是这个,文件路径必须是src根目录,否则读取不到.

<c3p0-config><default-config><property name="jdbcUrl">jdbc:mysql://localhost:3306/test</property><property name="driverClass">com.mysql.jdbc.Driver</property><property name="user">root</property><property name="password">root</property><property name="initialPoolSize">3</property><property name="maxPoolSize">6</property><property name="maxIdleTime">1000</property></default-config>
</c3p0-config>

配置文件的参数大体上用到的就这么多,当然,你也可以去找一下相关的资料,了解一下更加详细的参数意义,这些参数,我么日常使用足够了.

补充内容:数据库连接池的优点

资源重用

由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。

更快的系统反应速度

数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间

新的资源分配手段

对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源

统一的连接管理,避免数据库连接泄露:

在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露。

数据库连接池技术详解【吐血整理,疯狂推荐】相关推荐

  1. 线程池ThreadPoolExecutor详解(整理详细)

    ThreadPoolExecutor 1.什么是线程池? (首先要理解什么是线程) 线程池,thread pool,是一种线程使用模式,线程池维护着多个线程,等待着监督管理者分配可并发执行的任务. 通 ...

  2. C3P0(数据库连接池)详解

    一.定义 C3P0是一个开源的JDBC连接池,它实现了数据源与JNDI绑定,支持JDBC3规范和实现了JDBC2的标准扩展说明的Connection和Statement池的DataSources对象. ...

  3. 数据库连接池原理详解与自定义连接池实现

    实现原理 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约.无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量.连接池的 ...

  4. Linux Shell 编程基础详解——吐血整理,墙裂推荐!

    第一部分:Linux Shell 简介 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应用程序, ...

  5. mysql explain table_MySQL explain 应用详解(吐血整理)

    什么是explain 使用优化器可以模拟优化器执行SQL查询语句,从而知道MySQL怎么处理你的SQL语句的,分析你的查询语句和表结构的性能瓶颈.explain能够干什么读取表的顺序 哪些索引能够被使 ...

  6. zookeeper 分布式过程协同技术详解.pdf_阿里大牛耗时18个月整理这份ZooKeeper分布式详解文档...

    前言 摩尔定律揭示了集成电路每18个月计算性能就会增加一倍.随着信息的飞速膨胀,很多应用都无法依赖单个服务器的性能升级来处理如此庞大的数据量,分布式系统和应用越来越受到人们的青睐.分布式系统和应用不仅 ...

  7. jdbc 连接池 java_JDBC自定义连接池过程详解

    这篇文章主要介绍了JDBC自定义连接池过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 开发中,"获得连接"和" ...

  8. P2P技术详解(一):NAT详解——详细原理、P2P简介(转)

    这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层开发人员而言有很高的参考价值. <P2P技术详解>系列文章 ➊ 本 ...

  9. 015. P2P技术详解(一):NAT详解——详细原理、P2P简介

    http://www.52im.net/thread-50-1-1.html 这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层 ...

最新文章

  1. 解决MyEclipse2015启动时:Java was started but returned exit code=1问题
  2. 当DRM出错时的解决办法
  3. JVM内存结构分析:为什么需要S0和S1?
  4. 《Java技术》第二次作业计科1501赵健宇
  5. windows搭建python开发环境方法_04 Windows下搭建 Python 开发环境 - Python 入门教程
  6. 解决undefined reference to symbol ‘sem_close@@GLIBC_2.2.5‘问题
  7. 初步使用计算机说课,初步认识计算机说课稿
  8. c++ maps使用
  9. 计算机的常见故障处理实验报告,微机系统故障与处理-实验报告.doc
  10. 计算机毛利润的函数,毛利率计算公式
  11. win10系统mysql重新配置密码
  12. 上上下下左右左右BA
  13. python eml解析_使用 python eml-parser 对 eml文件进行格式化
  14. Java Reference Objects or How I Learned to Stop Worrying and Love OutOfMemoryError
  15. QT虚拟键盘中英文切换
  16. Nessus之——Nessus的整理
  17. PCB及电路抗干扰措施
  18. CMD 常用命令总结
  19. SLIC与目前最优超像素算法的比较 SLIC Superpixels Compared to State-of-the-art Superpixel Methods
  20. 【考研英语语法】冠词练习题

热门文章

  1. 一个内核网络漏洞详解|容器逃逸
  2. ETCD 问题、调优、监控
  3. 【大会】声音叫醒耳朵,语音连接网络
  4. OCP大会 | 腾讯云Open DCN Networking(附PDF)
  5. 自动化运维之 部署Saltstack 并批量部署 Nginx
  6. 判断目录是否存在并创建mkdir
  7. 人脸识别的过程和算法
  8. 第一个Arduino程序
  9. float double 的存储方式
  10. 大剑无锋之mysql中的行转列如何写?【面试推荐】