数据库连接池
数据库连接池
在JDBC编程中,每次创建和断开Connection对象都会消耗一定的时间和1O资源。这是因为在Java程序与数据库之间建立连接时,数据库课要验正用户名和密码,并且要为这个连接分服资源,Java程序则要把代表连接的java.sql Conmection对象等加载到内存中,所以建立数据库连接的开销很大,尤其是在大量的并发访问时。假如某网话一天的访问量是10万,那么,该网站的服务器就需要创建、断开连接10万次,频紫地创建、断开数每库连接势必会影响数据库的访问效率,甚至导致数据库崩溃。
为了避免频繁地创建数据库连接,数据库连接池技术应运而生。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立。
数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,当应用程序访问数据库时并不是直接创建Connection,而是向连接池“申请”一个Connection。如果连接池中有空闲的Connection,则将其返回,否则创建新的Connection。使用完毕后,连接池会将该Connection回收,并交付其他的线程使用,以减少创建和断开数据库连接的次数,提高数据库的访问效率。
10.1.2DataSource 接口
为了获取数据库连接对象(Connection),JDBC提供了javaxsail.Datasource接口,它负责与数据库建立连接,并定义了返回值为Connection对象的方法,具体如下。
Connection getConnection()
Connection getConnection(String username, String password)
上述两个重载的方法都能用来获取Connection对象。不同的是,第1个方法是通过无参的方式建立与数据库的连接,第2个方法是通过传入登录信息的方式建立与数据库的连接。
接口通常都会有其实现类,javax.sql.DataSource 接口也不例外,通常习惯性地把实现了javax.sql.DataSource接口的类称为数据源,顾名思义,数据源即数据的来源。在数据源中存位了所有建立数据库连接的信息。就像通过指定文件名称可以在文件系统中找到文件一样,通过提供正确的数据源名称,也可以找到相应的数据库连接。
数据源中包含数据库连接池。如果数据是水,数据库就是水库,数据源就是连接到水库的管道,终端用户看到的数据集是管道里流出来的水。一些开源组织提供了数据源的独立实现,常用的有DBCP数据源和C3PO数据源。接下来的小节中,将会对这两种数据源进行详细的讲解。
代码如下(示例):
数据库连接池的运行机制:
(1) 程序初始化时创建连接池
(2) 使用时向连接池申请可用连接
(3) 使用完毕,将连接返还给连接池
(4) 程序退出时,断开所有连接,并释放资源
10.1.2 DataSource接口
为了获取数拢库连接对象(Connection ).JDBC提供了javax.sql.DataSource 接口,它负责与数梯库建立连接,并定义了返回值为Connection对象的方法,具体如下。
Connection getConnection()
.Connection getConnection(String username,String password)
接口通常都会有其实现类,javax.sql.DataSource接口也不例外,通常习惯性地把实现了javax.sqL.DataSource 接口的类称为数捆源,顾名思义,数据源即数据的来源。在数据源中存储了所有建立数据库连接的信息。就像通过指定文件名称可以在文件系统中找到文件一样,通过提供正确的数据源名称,也可以找到相应的数据库连接。
10.1.3 DBCP数据源
1.commons-dbcp.jar包
commons-dbcp.jar 包是 DBCP数据源的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法。
2.commons-pool.jar 包
commons-pool.jar 包是 DBCP 数据库连接池实现包的依赖包,为 commons-dbcpjar 包中的方法提供了支持。可以这么说,没有该依赖包,commons-dbcp.jar 包中的很多方法就没有办法实现。
这两个JAR包可以在Apache官网地址“http:/lcommons.apache.org/proper/”中查询下载到。其中,commons-dbcp.jar 中包含两个核心的类,分别是 BasicDataSourceFactory 和BasicDataSource,它们都包含获取DBCP数据源对象的方法。接下来,针对这两个类的方法进行详细的讲解。
通过BasicDataSource类直接创建数据源对象
在使用 BasicDataSource类创建一个数据源对象时,需要手动给数据源对象设置属性值,然后获取数据库连接对象。接下来,通过一个案例来演示BasicDataSource类的使用,具体步骤如下。
(1)在Eclipse 中创建一个名称为chapter10的Web 项目,在项目chapter10 中导入mysql-connector-java-5.0.8-bin.jar、commons-dbcp-1.4.jar 以及 commons-pool-1.6.jar 3个JAR包,并发布到类路径下,然后在项目的src目录下创建包cn.itcast.chapter10.example,并在该包下创建一个Example01类,该类采用手动方式获取数据库的连接信息和数据源的初始化信息。
2.通过读取配置文件创建数据源对象
除了使用BasicDataSource直接创建数据源对象外,还可以使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象。接下来,通过一个案例来演示,具体步骤如下。
(1)在chapter10项目的src 目录下创建dbcpconfig.properties文件,该文件用于设置数据库的连接信息和数据源的初始化信息。
(2)在cn.itcast.chapter10.example包下创建一个Example02类,该类中采用了从配置文
件中获取数据库的连接信息和数据源的初始化信息的方式。
C3P0 数据源
C3PO 是目前最流行的开源数据库连接池之一,它实现了DataSource 数培源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和Spring都支持该数据源。在使用C3PO数据源开发时,需要了解C3PO中DataSource接口的实现类ComboPooledDataSource,它是C3PO的核心类,提供了数据源对象的相关方法。
DBUtils 工具
DBUtils工具介绍
为了更加简单地使用JDBC,Apache组织提供了一个DBUtils工具,它是操作数据库的一个组件,实现了对JDBC的简单封装,可以在不影响性能的情况下极大地简化JDBC的编码工作量。
DBUtils 工具可以在“http://commons.apache.org/proper/commons-dbutils/index.html”下载到,截止到目前它的最新版本为Apache Commons DbUtils 1.6,本节也是针对该版本进行讲解的。
DBUtils工具的核心是org.apache.commons.dbutils.QueryRunner类和org.apache.commons.dbutils.ResultSetHandler接口,了解它们对于DBUtils工具的学习和使用非常重要。在接下来的小节中,将对 DBUtils 工具的QueryRunner类、ResultSetHandler 接口以及接口的实现类进行详细的讲解。
10.2.2QueryRunner类
QueryRunner类简化了执行SQL语句的代码,它与ResultSetHandler组合在一起就能完成大部分的数据库操作,大大地减少了编码量。
QueryRunner类提供了带有一个参数的构造方法,该方法以javax.sql.DataSource 作为参数传递到 QueryRunner 的构造方法中来获取 Connection 对象。针对不同的数据库操作,QueryRunner类提供了几种常见的方法,具体如下。
query(String sql, ResultSetHandler rsh, Object… params)方法
该方法用于执行查询操作,它可以从提供给构造方法的数据源 DataSource 或使用的setDataSource()方法中获得连接。
update(String sql, Object…params)方法
该方法用于执行插入、更新或者删除操作,其中,参数params表示SQL语句中的置换参数。update(String sql)方法
该方法用来执行插入、更新或者删除操作,它不需要置换参数。
ResultSetHandler 接口
FResuiseltandier接口用于处理 FResutSet结果集,它可以将结果集中的数据转为不同的。式。根据结果集中数据类型的不同,ResutSetHandler提供了几种常见的实现类,具体如下。
BeanHandler:将结果集中的第1行数据封装到一个对应的JavaBean实例中。BeanLisandier?将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
ScalarHandler:将结果集中某一条记录的其中某一列的数据存储成Object对象。另外,在ResutSeiHandler接口中,提供了一个单独的方法handle (java.sql.Resultsetrg)如果上述实现类没有提供想要的功能,可以通过自定义一个实现ResultSetHandler接口的类,然后通过重写 handle()方法,实现结果集的处理。
代码如下(示例):
C3p0Utils.java
package cn.itcast.jdbc.utils;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3p0Utils {
private static DataSource ds;
static {
ds = new ComboPooledDataSource();
}
public static DataSource getDataSource() {
return ds;
}
}
DBUtilsDao.java
package cn.itcast.jdbc.demo;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import cn.itcast.chapter10.example.User;
import cn.itcast.jdbc.utils.C3p0Utils;
public class DBUtilsDao {
// 查询所有,返回List集合
public List findAll() throws SQLException {
// 创建QueryRunner对象
QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
// 写SQL语句
String sql = "select * from user";
// 调用方法
List list = (List) runner.query(sql,
new BeanListHandler(User.class));
return list;
}
// 查询单个,返回对象
public User find(int id) throws SQLException {
// 创建QueryRunner对象
QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
// 写SQL语句
String sql = "select * from user where id=?";
// 调用方法
User user = (User) runner.query(sql,
new BeanHandler(User.class), new Object[] { id });
return user;
}
// 添加用户的操作
public Boolean insert(User user) throws SQLException {
// 创建QueryRunner对象
QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
// 写SQL语句
String sql = "insert into user (name,password) values (?,?)";
// 调用方法
int num = runner.update(sql,
new Object[] { user.getName(), user.getPassword() });
if (num > 0)
return true;
return false;
}
// 修改用户的操作
public Boolean update(User user) throws SQLException {
// 创建QueryRunner对象
QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
// 写SQL语句
String sql = "update user set name=?,password=? where id=?";
// 调用方法
int num = runner.update(sql, new Object[] { user.getName(),
user.getPassword(),user.getId() });
if (num > 0)
return true;
return false;
}
// 删除用户的操作
public Boolean delete(int id) throws SQLException {
// 创建QueryRunner对象
QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
// 写SQL语句
String sql = "delete from user where id=?";
// 调用方法
int num = runner.update(sql, id);
if (num > 0)
return true;
return false;
}
}
(1)在cn.itcast.jdbc.demo包中创建类DBUtilsDaoTest1对增加操作进行测试:
DBUtilsDaoTest1.java
package cn.itcast.jdbc.demo;
import java.sql.SQLException;
import cn.itcast.chapter10.example.User;
public class DBUtilsDaoTest1 {
private static DBUtilsDao dao = new DBUtilsDao();
public static void testInsert() throws SQLException {
User user = new User();
user.setName("zhaoliu");
user.setPassword("666666");
boolean b = dao.insert(user);
System.out.println(b);
}
public static void main(String[] args) throws SQLException {
testInsert();
}
}
DBUtilsDaoTest2.java
package cn.itcast.jdbc.demo;
import java.sql.SQLException;
import cn.itcast.chapter10.example.User;
public class DBUtilsDaoTest2 {
private static DBUtilsDao dao = new DBUtilsDao();
public static void testupdate() throws SQLException {
User user = new User();
user.setName("zhaoliu");
user.setPassword("666777");
user.setId(4);
boolean b = dao.update(user);
System.out.println(b);
}
public static void main(String[] args) throws SQLException {
testupdate();
}
}
DBUtilsDaoTest3.java
package cn.itcast.jdbc.demo;
import java.sql.SQLException;
public class DBUtilsDaoTest3 {
private static DBUtilsDao dao = new DBUtilsDao();
public static void testdelete() throws SQLException {
boolean b = dao.delete(4);
System.out.println(b);
}
public static void main(String[] args) throws SQLException {
testdelete();
}
}
DBUtilsDaoTest4.java
package cn.itcast.jdbc.demo;
import java.sql.SQLException;
import cn.itcast.chapter10.example.User;
public class DBUtilsDaoTest4 {
private static DBUtilsDao dao = new DBUtilsDao();
public static void testfind() throws SQLException {
User user = dao.find(2);
System.out.println(user.getId() + "," + user.getName() + ","
+ user.getPassword());
}
public static void main(String[] args) throws SQLException {
testfind();
}
}