JDBC既制定统一标准兼容了多种数据库,又利用预报告堵上了SQL注入漏洞,照理说已经很完善了,可是人算不如天算,它在性能方面不尽如人意。问题出在数据库连接的管理上,按照正常流程,每次操作完数据库,都要关闭连接,无论是代码里手工关闭,还是由try语句自动关闭。如果没有及时关闭数据库连接,就会长时间占用有限的数据库内存,致使无谓的系统资源浪费。然而频繁开关数据库连接也有毛病,因为每次获取操作都要CPU处理,经常连接数据库会加重CPU的负担。看来内存与CPU像是一对难兄难弟,不管怎么做都会影响其中一个,正所谓鱼与熊掌不可兼得。
其实连接跟线程的情况相似,线程也很头疼频繁创建导致的资源开销,为此Java早早就设计了线程池机制,事先在一个池子中容纳若干线程,需要使用线程时便从中挑一根线程执行任务,任务做完再归还线程,如此实现了线程资源的循环利用,有效提高了系统的整体运行效率。既然线程们组建了线程池这个大家庭,那么连接们能否也组成连接池的大家庭呢?Java固然自带了线程池工具,却未能推出类似的连接池工具,于是各种第三方的连接池蜂拥而起,例如DBCP、C3P0、Proxool等等,其中应用广泛的当数C3P0。
C3P0是一个开源的数据库连接池,它支持JDBC3规范和JDBC2的标准扩展。若要在Java工程中运用C3P0,得先导入它的jar包,比如c3p0-0.9.5.4.jar,同时还要导入该jar包依赖的mchange-commons-java-0.2.16.jar,也就是一共导入两个jar文件。使用C3P0很简单,掌握ComboPooledDataSource类的用法就够了,该类的常见方法说明如下:
setDriverClass:设置连接池的数据库驱动。
setJdbcUrl:设置数据库的连接地址。
setUser:设置数据库的用户名。
setPassword:设置数据库的密码。
setMaxPoolSize:设置连接池大小的上限。
setMinPoolSize:设置连接池大小的下限。
setInitialPoolSize:设置连接池的初始大小。
setMaxStatements:设置报告的最大个数。
setCheckoutTimeout:设置获取连接的等待时间,单位毫秒。当连接池中的所有连接都被占用的时候,新请求想获取连接就必须等待,等待现有连接被释放后才能获取空闲连接。默认为0表示一直等待下去。
setMaxIdleTime:设置最大空闲时间,单位秒。如果某个连接超过该时间仍未使用,则会被自动回收。默认为0表示不判断是否超时,也就是永不回收。
getConnection:从连接池中获取一个连接。
close:关闭连接池。
引入连接池之后,完整的数据库操作流程分解成了两大步骤:初始化连接池、从连接池中取出一个连接处理,下面分别予以介绍。
1、初始化连接池
该步骤首先创建C3P0连接池的对象,再依次调用相关方法设置详细的参数信息,包括数据库驱动、连接地址、用户名、密码,以及与连接池有关的规格参数。下面是初始化C3P0连接池的代码例子:

	private static ComboPooledDataSource dataSource; // 声明C3P0连接池的对象
// 初始化连接池
private static void initDataSource() {
dataSource = new ComboPooledDataSource(); // 创建C3P0连接池
try {
dataSource.setDriverClass(driver_class); // 设置连接池的数据库驱动
} catch (PropertyVetoException e) {
e.printStackTrace();
}
dataSource.setJdbcUrl(dbUrl); // 设置数据库的连接地址
dataSource.setUser(dbUserName); // 设置数据库的用户名
dataSource.setPassword(dbPassword); // 设置数据库的密码
dataSource.setMaxPoolSize(10); // 设置连接池大小的上限
dataSource.setMinPoolSize(1); // 设置连接池大小的下限
dataSource.setInitialPoolSize(3); // 设置连接池的初始大小
}

  

2、从连接池中取出一个连接处理
除了一开始调用连接池的getConnection获取连接之外,该步骤剩余的操作过程与JDBC原有流程保持一致,即获得数据库连接之后,同样要创建连接的报告,然后命令报告执行SQL语句。下面是通过连接池操作数据库的代码例子:

	// 显示性别分组
private static void showRecordGroupBySex() {
String sql = "select sex,count(1) count from teacher group by sex order by sex asc";
// 从连接池中获取连接、创建连接的报告、命令报告执行指定的SQL语句
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) { // 循环遍历结果集里面的所有记录
int sex = rs.getInt("sex"); // 获取指定字段的整型值
int count = rs.getInt("count"); // 获取指定字段的整型值
String desc = String.format("%s老师有%d位;", sex==0 ? "男" : "女", count);
System.out.print(desc);
}
} catch (SQLException e) {
e.printStackTrace();
}
}

整合连接池的初始化和具体操作的代码,运行包含整合代码之内的测试程序,观察如下日志可知C3P0连接池正常工作。

男老师有2位;女老师有3位;  


更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(一百五十)C3P0连接池的用法的更多相关文章

  1. Java开发笔记(五十)几种开放性修饰符

    前面介绍子类继承父类的时候,提到了public(公共)和private(私有)两个修饰符,其中public表示它所修饰的实体是允许外部访问的:而private表示它所修饰的实体不允许外部访问,只能在当 ...

  2. Java开发笔记(五十二)对象的类型检查

    前面介绍了类的多态性,来自于鸡类的实例chicken,既能用来表达公鸡实例,也能用来表达母鸡实例.可是这导致了一个问题,假如在call方法内部需要手工判断输入参数属于公鸡实例还是母鸡实例,那该如何是好 ...

  3. Java开发笔记(五十四)内部类和嵌套类

    通常情况下,一个Java代码文件只定义一个类,即使两个类是父类与子类的关系,也要把它们拆成两个代码文件分别定义.可是有些事物相互之间密切联系,又不同于父子类的继承关系,比如一棵树会开很多花朵,这些花儿 ...

  4. Java开发笔记(五十五)关键字static的用法

    前面介绍嵌套类的时候讲到了关键字static,用static修饰类,该类就变成了嵌套类.从嵌套类的用法可知,其它地方访问嵌套类之时,无需动态创建外层类的实例,直接创建嵌套类的实例就行.其实static ...

  5. Java开发笔记(五十六)利用枚举类型实现高级常量

    前面介绍了联合利用final和static可实现常量的定义,该方式用于简单的常量倒还凑合,要是用于复杂的.安全性高的常量,那就力不从心了.例如以下几种情况,final结合static的方式便缺乏应对之 ...

  6. Java开发笔记(五十八)简单接口及其实现

    前面介绍了抽象方法及抽象类的用法,看似解决了不确定行为的方法定义,既然叫唤动作允许声明为抽象方法,那么飞翔.游泳也能声明为抽象方法,并且鸡类涵盖的物种不够多,最好把这些行为动作扩展到鸟类这个群体,于是 ...

  7. Java开发笔记(五十九)Java8之后的扩展接口

    前面介绍了接口的基本用法,有心的朋友可能注意到这么一句话“在Java8以前,接口内部的所有方法都必须是抽象方法”,如此说来,在Java8之后,接口的内部方法也可能不是抽象方法了吗?之所以Java8对接 ...

  8. Java开发笔记(五十三)关键字final的用法

    前面介绍了多态的相关用法,可以看到一个子类从父类继承之后,便能假借父类的名义到处晃悠.这种机制在正常情况之下没啥问题,但有时为了预防意外发生,往往只接受当事人来处理,不希望它的儿子乃至孙子来瞎掺和.可 ...

  9. Java开发笔记(二十)一维数组的用法

    之前介绍的各类变量都是单独声明的,倘若要求定义相同类型的一组变量,则需定义许多同类型的变量,显然耗时耗力且不宜维护.为此,编程语言引入了数组的概念,每个数组都由一组相同类型的数据构成,对外有统一的数组 ...

  10. OpenCV开发笔记(五十六):红胖子8分钟带你深入了解多种图形拟合逼近轮廓(图文并茂+浅显易懂+程序源码)

    若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...

随机推荐

  1. (尚031)Vue_案例_自定义事件(组件间通信第2种方式:vue自定义事件)

    自定义事件: 我们知道,父组件使用prop传递数据的子组件,但子组件怎么跟父组件通信呢? 这个时候Vue的自定义事件系统就派得上用场了. 自定义事件知道两件事: (1).绑定 (2).触发 注意:$o ...

  2. ABP 00 常用知识

    1.更改本地预览的端口: 文件路径:\src\ContractMS.Web.Mvc\Properties\launchSettings.json 改这里:"applicationUrl&qu ...

  3. Noip2018/Csp2019 ------退役记

    退役记 上记 不知道为啥,自从今下午某大佬的人生第一次政治运动(虽然最后被镇压,现在小命难保)后,仿佛有一种看破感. 以下有点在自作多情,不喜者可以不看. 学信竞快一年了.可以说有收获也有失去吧. 收 ...

  4. 原创:Kmeans算法实战+改进(java实现)

    kmeans算法的流程:   EM思想很伟大,在处理含有隐式变量的机器学习算法中很有用.聚类算法包括kmeans,高斯混合聚类,快速迭代聚类等等,都离不开EM思想.在了解kmeans算法之前,有必要详 ...

  5. python 类的倒入

    test.pyclass sss: def ddd(self): print("hello") test2.pyfrom testone import sss

  6. KD-Tree总结

    KD-Tree总结 问题引入 平面上有\(n\)个点,\(q\)组询问,每一次查询距离\((x,y)\)最近的点对,强制在线. 问题解决 暴力 显然我们可以直接枚举点然后算距离取\(min\),这样子 ...

  7. Mongoose 索引

    Mongoose 索引介绍 索引是对数据库表中一列或多列的值进行排序的一种结构,可以让我们查询数据库变得更 快(如果有些字段是用不着的就不要设置索引).MongoDB 的索引几乎与传统的关系型数据库一 ...

  8. Windows 文件过滤驱动经验总结

    Windows 文件过滤驱动经验总结作者:sinister 本文转载自驱动开发网 看了 ChuKuangRen 的第二版<文件过滤驱动开发教程>后,颇有感触.我想,交流都是建立在平等的基础 ...

  9. Gamma阶段第三次scrum meeting

    每日任务内容 队员 昨日完成任务 明日要完成的任务 张圆宁 #91 用户体验与优化https://github.com/rRetr0Git/rateMyCourse/issues/91(持续完成) # ...

  10. The Snowflake Elastic Data Warehouse

    开篇说的是,Shared-nothing当前已经是主流的架构,需要用自身的local disks来存储数据,Tables被水平划分到各个partitions上 这种架构,比较适合star-schema ...