第10章 数据库连接池与DBUtils工具
- 10.1 数据库连接池
- 10.1.2 DataSource接口
- 10.1.3 DBCP数据源
- 10.1.4 C3P0数据源
- 10.2 DBUtils工具
- 10.2.1 DBUtils工具介绍
- 10.2.2 QueryRunner类
- 10.2.3 ResultSetHandler接口
由于每操作一次数据库,都会执行一次创建和断开Connection对象的操作,这种频繁的操作Connection对象十分影响数据库的访问效率,并且增加了代码量,所以在实际开发中,开发人员通常会使用数据库连接池来解决这些问题,Apache组织还提供一个DBUtils工具类,该类实现了对JDBC的简单封装,能在不影响性能的情况下极大地简化JDBC的编码工作
10.1 数据库连接池
在JDBC编程中,每次创建和断开Connection对象都会消耗一定的时间和IO资源。这是因为Java程序与数据库之间建立连接时,数据库端要验证用户名和密码,并且要为这个连接分配资源,JAVA程序则要把代表连接的 java.sql.Connection对象加载到内存中,所以建立数据连接的开销很大,尤其是在大量的并发访问时。假如某网站一天的访问量是10万,那么该网站的服务器就需要创建,断开连接10万次,频繁地创建,断开数据库连接势必会影响数据库的访问效率,甚至导致数据库的崩溃
为了避免频繁地创建数据库连接,数据库连接池技术应运而生。数据库连接池负责分配,管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,当应用程序访问数据库时并不是直接创建Connection,而是向连接池申请一个Connection。如果连接池中有空闲的Connection,则将其返回,否则创建新的Connection。使用完毕后,连接池会将该Connection回收,并交付其他的线程使用,以减少创建和断开数据库连接的次数,提高数据库的访问效率
10.1.2 DataSource接口
为了获取数据库连接对象,JDBC提供了javax.sql.DataSource接口,它负责与数据库建立连接,并定义了返回值为Connection对象的方法,具体如下:
1.Connection getConnection()
2.Connection getConnection(String username,String password)
上述两个重载的方法都能用来获取Connection对象。不同的是,第1个方法是通过无参的方式建立与数据库的连接,第2个方法是通过传入登录信息的方式建立于数据库的连接
接口通常都会有其实现类,javax.sql.DataSource接口也不例外,通常习惯性地把实现了javax.sql.DataSource接口的类称为数据源,顾名思义,数据源即数据的来源。在数据源中存储了所有建立数据库的连接信息。就像通过指定文件名称可以在文件系统中找到文件一样,也可以找到相应的数据库连接
数据源包含数据库连接池。如果数据是水,数据库就是水库,数据源就是连接到水库的管道,终端用户看到的数据集是管道里流出来的水。一些开源组织提供了数据源的独立实现,常用的有DBCP数据源和C3P0数据源
10.1.3 DBCP数据源
DBCP:是数据库连接池的简称,是Apache组织下的开源连接池的实现,也是Tomcat服务器使用的连接池组件。单独使用DBCP数据源时,需要在应用程序中导入两个JAR包,具体如下:
1.commons-dbcp.jar包
commons-dbcp.jar包:是DBCP数据源的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法
2.commons-pool.jar包
commons-pool.jar包:是DBCP数据库连接池实现包的依赖包,为commons-dbcp.jar包中的方法提供了支持。可以这么说,没有该依赖包,commons-dbcp.jar包中的很多方法就没有办法实现
commons-dbcp.jar中包含两个核心的类,分别是BasicDataSourceFactory和BasicDataSource,它们都包含获取DBCP数据源对象的方法
BasicDataSourceFactory:是DataSource接口的实现类,主要包括设置数据源对象的方法,具体方法如下:
方法名称 | 功能描述 |
void setDriverClassName(String driverClassName) | 设置数据库的驱动名称 |
void setUrl(String url) | 设置连接数据库的路径 |
void setUsername(String username) | 设置数据库登录账户 |
void setPassword(String password) | 设置数据库的登录密码 |
void setInitialSize(int initialSixe) | 设置数据库连接池初始化的连接数目 |
void setMaxActive(int maxldle) | 设置数据库连接池最大活跃的连接数目 |
void setMinldle(int minldle) | 设置数据库连接池最小闲置的连接数目 |
connection getConnection() | 从连接池中获取一个数据库连接 |
BasicDataSourceFactory是创建BasicDataSource对象的工厂类,它包含一个返回值为BasicDataSource对象的方法createDataSource(),该方法通过读取配置文件的信息生成数据源对象并返回调用者。这种把数据库的连接信息和数据源的初始化信息提取出来写进配置文件的方式,让代码看起来更加简洁,思路也更加清晰当使用DBCP数据源时,首先要创建数据源对象,数据源对象的创建方式有两种具体如下:
1.通过BasicDataSource类直接创建数据源对象
在使用BasicDataSource类创建对象时,需要手动给数据源对象设置属性值,然后获取数据库连接对象
2.通过读取配置文件创建数据源对象
除了使用BasicDataSource直接创建数据源对象外,还可以使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象
10.1.4 C3P0数据源
C3P0是目前最流行的开源数据库连接池之一,它实现了DataSource数据源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和Spring都支持该数据源。在使用C3P0数据源开发时,需要了解C3P0中DataSource接口的实现类ComboPooledDataSource,它是C3P0的核心类,提供了数据源对象的相关方法,该类的常用方法介绍如下:
方法名称 | 功能描述 |
void setDriverClass() | 设置连接数据库的驱动名称 |
void setJdbUrl() | 设置连接数据库的路径 |
void setUser() | 设置数据库的登录账号 |
void setPassword() | 设置数据库的登录密码 |
void setMaxPoolSize() | 设置数据库连接池最大的连接数目 |
void setMinPoolSize() | 设置数据库连接池最小的连接数目 |
void setlnitialPoolSize() | 设置数据库连接池初始化的连接数目 |
Connection getConnection() | 从数据库连接池中获取一个连接 |
当使用C3P0数据源时,首先需要创建数据源对象,创建数据源对象可以使用Combo-PooledDataSource类,该类有两个构造方法,f分别是ComboPooledDataSource()和ComboPooledDataSource(String configName)
1.通过ComboPooledDataSource()构造方法创建数据源对象
2.通过读取配置文件创建数据源对象
10.2 DBUtils工具
10.2.1 DBUtils工具介绍
为了更加简单地使用JDBC,Apache组织提供了一个DBUtils工具,它是操作数据库的一个组件,实现了对JDBC的简单封装,可以在不影响性能的情况下极大地简化JDBC的编码工作量
DBUtils工具核心是org.apache.commons.dbutils.QueryRunner类和org.apache.commons.dbutils.ResultSetHandler接口,了解它们对于DBUtils工具的学习和使用非常重要
10.2.2 QueryRunner类
QueryRunner类简化了执行SQL语句的代码,它与ResultSetHandler组合在一起就能完成大部分的数据库操作,大大地减少了编码量
QueryRunner类提供了带有一个参数的构造方法,该方法以javax.sql.DataSource作为参数传递到QueryRunner的构造方法中来获取Connection对象。针对不同的数据库操作,QueryRunner类提供了几种常见的方法,具体如下:
(1)query(String sql,ResultSetHandler rsh,Object…params)方法
该方法用于执行查询操作,它可以从提供给构造方法的数据源DataSource或使用的setDataSource()方法中获得连接
(2)update(String sql,object…params)方法
该方法用于执行插入,更新或者删除操作,其中,参数params表示SQL语句中的置换参数
(3)update(String sql)方法
该方法用来执行插入,更新或者删除操作,它不需要置换参数
10.2.3 ResultSetHandler接口
ResultSetHandler接口用于处理ResultSet结果集,它可以将结果集中的数据转为不同的形式。根据结果集中数据类型的不同,ResultSetHandler提供了几种常见的实现类型,具体如下:
(1)BeanHandler:将结果集中的第1行数据封装到一个对应的JavaBean实例中
(2)BeanListHandler:将结果集中的每一行数据都封装到一个对象的JavaBean实例中,并放到List里
(3)ScalarHandler:将结果集中某一条记录的其中某一列的数据存储成Object对象
(4)handle(java.sql.ResultSet rs):如果实现类没有提供想要的功能,可以通过自定义实现ResultSetHandler接口的类,然后通过重写handle()方法,实现结果集的处理