什么是数据库连接池
在 JDBC 编程中,每次创建和断开Connectin 对象都会消耗一定的时间和IO 资源。这是因为在 Java 程序与数据库之间建立连接时,数据库端要验证用户名和密码,并且要为这个连接分配资源,Java 程序则要把代表连接的java.sqlComection 对象等加载到内存中,所以建立数据库连接的开销很大,尤其是在大量的并发访问时。假如某网站一天的访问量是10万,那么,该网站的服务器就需要创建、断开连接 10 万次,频繁地创建、断开数据库连接势必会影响数据库的访问效率,甚至导致数据库崩溃。
为了避免频繁地创建数据库连接,数据库连接池技术应运而生。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立。
DataSource接口
为了获取数据库连接对象(Connection),JDBC 提供了 javax.sql.DataSource 接口,它负责与数据库建立连接,并定义了返回值为 Connection 对象的方法,具体如下。
1.Connection getConnection()
2.Connection getConnection(String username, String password)
上述两个重载的方法都能用来获取 Conection 对象。不同的是,第 1 个方法是通过无参的方式建立与数据库的连接,第 2 个方法是通过传入登录信息的方式建立与数据库的连接。
接口通常都会有其实现类,javax. sql
.DataSource 接口也不例外,通常习惯性地把实现了javax.sqlDataSource 接口的类称为数据源,顾名思义,数据源即数据的来源。在数据源中存储
了所有建立数据库连接的信息。就像通过指定文件名称可以在文件系统中找到文件一样,通过提供正确的数据源名称,也可以找到相应的数据库连接。
数据源中包含数据库连接池。如果数据是水,数据库就是水库,数据源就是连接到水库的管道,终端用户看到的数据集是管道里流出来的水。一些开源组织提供了数据源的独立实现,常用的有 DBCP 数据源和 C3PO 数据源。
DBCP数据源
DBCP是数据库连接池的简称,是Apache组织下的开源连接池实现,不是tomcat服务器使用的连接池组件。单独使用DBCP数据源时,需要在应用程序中导入两个JAR包,具体如下。
- commons-dbcp.jar包
commons-dbopjar 包是 DBCP 数据源的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了 DataSource 接口的getConnection()方法。 - commons-pool.jar包
commons-pooljar包是 DBCP 数据库连接池实现包的依赖包,为 commons-dbcpjar包中
的方法提供了支持。可以这么说,没有该依赖包,commons-dbcpjar 包中的很多方法就没有办法实现。
这两个 JAR 包可以在 Apache 官网地址“htp//commons apache.org/proper”中查询下
载到。其中,commons-dbcpjar 中包含两个核心的类,分别是BasicDataSourceFacbory 和
BasicDataSource,它们都包含获取DBCP数据源对象的方法。
BasicDataSourceFactory是创建BasicDataSource对象的工厂类,它包含一个返回值为BasicDataSource 对象的方法 createDataSource(),该方法通过读取配置文件的信息生成数据源
BasicDataSourceFactory 是创建 BasicDataSource 对象的工厂类,它包含一个返回值为对象并返回给调用者。这种把数据库的连接信息和数据源的初始化信息提取出来写进配置文件的方式,让代码看起来更加简洁,思路也更加清晰。
当使用 DBCP 数据源时,首先要创建数据源对象,数据源对象的创建方式有两种,具体如下。
1.通过 BasicDataSource 类直接创建数据源对象
在使用 BasicDataSource 类创建一个数据源对象时,需要手动给数据源对象设置属性值,然后获取数据库连接对象。接下来,通过一个案例来演示 BasicDataSource 类的使用,具体步
骤如下。
(1)在 Eclipse 中创建一个名称为 chapter10 的 Web 项目,在项目 chapier10 中导人
mysql-connector-java-5.0.8-bin.jar.commons-dbcp-1.4.jar 以及 commons-pool-1.6jar 3个JAR 包,并发布到类路径下,然后在项目的 src 目录下创建包 cn.itcast.chapter10.example,并在该包下创建一个 Example01 类,该类采用手动方式获取数据库的连接信息和数据源的初始化信息
2.通过读取配置文件创建数据源对象
除了使用 BasicDataSource 直接创建数据源对象外,还可以使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象。接下来,通过一个案例来演
示,具体步骤如下。
(1)在 chapter10 项目的 src 目录下创建 dbcpconfig.properties 文件,该文件用于设置数据库的连接信息和数据源的初始化信息。
(2)在 cn.itcast.chapter10.example 包下创建一个 Example02 类,该类中采用了从配置文件中获取数据库的连接信息和数据源的初始化信息的方式。
(3)运行main()方法后,程序的运行结果
C3PO 数据源
C3PO 是目前最流行的开源数据库连接池之一,它实现了 DataSource 数据源接口,支持JDBC2 和 JDBC3 的标准规范,易于扩展并且性能优越,著名的开源框架 Hibernate 和 Spring都支持该数据源。在使用 C3PO 数据源开发时,需要了解 C3PO 中 DataSource 接口的实现类ComboPooledDataSource,它是 C3PO 的核心类,提供了数据源对象的相关方法。
#DBUtis 工具
DBUtiis 工具介
为了更加简单地使用 JDBC,Apache 组织提供了一个 DBUitils 工具,它是操作数据库的一个实现了对JDBC 的简单封装,可以在不影响性能的情况下极大地简化JDBC的编码工作量。
DBUtils 工具可以在“http://commons.apache.org/proper/commons-dbuilsindex.html”下载到,截止到目前它的最新版本为Apache Commons在Dbutils1.6。
DBUtils 工具的核心是 org.apache.commons.dbutils. QueryRunner 类和 org.apache.commons.dbutlis.ResultSetHandler接口。
QueryRunner类
QueryRunner 类简化了执行 SQL 语句的代码,它与 ResultSetHandler组合在一起就能完成大部分的数据库操作,大大地减少了编码量。
QueryRunner 类提供了带有一个参数的构造方法,该方法以javax.sql.DataSource 作为参数传递到 QueryRunner 的构造方法中来获取 Connection 对象。针对不同的数据库操作,QveryRunner 类提供了几种常见的方法,具体如下。
1.query(String sql, ResultSetHandler rsh, Object… params)方法
该方法用于执行查询操作,它可以从提供给构造方法的数据源DataSource或使用的setdatasource()方法中获得连接。
2.update(String sql,Object… params)方法
该方法用于执行插入、更新或者删除操作,其中,参数 params 表示 SQL 语句中的置换参数。
3.update(String sql)方法
该方法用来执行插入,更新或者删除操作,它不需要置换参数。
代码及成功展示
package cn.itcast.chapter10.example;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import org.apache.commons.dbutils.ResultSetHandler;
public class BaseDao {
public static Object query(String sql,ResultSetHandler<?> rsh, Object... params){
Connection conn=null;
PreparedStatement pstmt= null;
ResultSet rs=null;
try {
conn=JDBCUtils.getCon();
pstmt=conn.prepareStatement(sql);
for(int i=8;params!=null && i<params.length;i++){
pstmt.setObject(i+1, params[i]);
}
rs=pstmt.executeQuery();
Object obj=rsh.handle(rs);
return obj;
}catch(Exception e){
e.printStackTrace();
}finally {
JDBCUtils.release(rs, pstmt, conn);
}
return rs;
}
}
package cn.itcast.chapter10.example;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
public class example01 {
public static DataSource ds=null;
static {
BasicDataSource bds=new BasicDataSource();
bds.setDriverClassName("com.mysql.jdbc.Driver");
System.out.println("2020080605045 袁雪华");
bds.setUrl("jdbc:mysql://localhost:3306/jdbc");
bds.setUsername("root");
bds.setPassword("123456");
bds.setInitialSize(5);
bds.setMaxActive(10);
ds=bds;
}
public static void main(String[] args)throws SQLException {
Connection conn=(Connection) ds.getConnection();
DatabaseMetaData metadata=conn.getMetaData();
System.out.println(metadata.getURL());
System.out.println(metadata.getUserName());
System.out.println(metadata.getDriverName());
}
}
package cn.itcast.chapter10.example;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.tomcat.dbcp.dbcp2.BasicDataSourceFactory;
public class example02 {
public static DataSource ds=null;
static {
Properties prop=new Properties();
try {
InputStream in=new example02().getClass().getClassLoader().getResourceAsStream("dbcpconfig.properties");
prop.load(in);
ds=BasicDataSourceFactory.createDataSource(prop);
}catch(Exception e) {
throw new ExceptionInInitializerError(e);
}
}
public static void main(String[] args)throws SQLException{
Connection conn=ds.getConnection();
DatabaseMetaData metadata=conn.getMetaData();
System.out.println(metadata.getURL());
System.out.println(metadata.getUserName());
System.out.println(metadata.getDriverName());
}
}
package cn.itcast.chapter10.example;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class example03 {
public static DataSource ds=null;
//初始化 C3PO 数据源
static {
ComboPooledDataSource cpds = new ComboPooledDataSource();
//设置连接数据库需要的配置信息
try {
cpds.setDriverClass("com.mysql.jdbc.Driver");
cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc");
cpds.setUser("root");
cpds.setPassword("123456");
// 设置连接池的参数
cpds.setInitialPoolSize(5);
cpds.setMaxPoolSize(15);
ds = cpds;
} catch (Exception e){
throw new ExceptionInInitializerError(e);
}
}
public static void main(String[] args) throws SQLException {
//获取数据库连接对象
System.out.println(ds.getConnection());
}
}
package cn.itcast.chapter10.example;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class example04 {
public static DataSource ds = null;
// 初始化 C3PO 数据源
static {
//使用 c3p0-config.xml 配置文件中的 named-config 节点中 name 属性的值
ComboPooledDataSource cpds = new ComboPooledDataSource("123456");
ds = cpds;
}
public static void main(String[] args) throws SQLException {
System.out.println(ds.getConnection());
}
}
package cn.itcast.chapter10.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils {
public static Connection getCon() throws Exception{
Class.forName("com.mysql.jdbc.Driver");
String url="jdbc:mysql://localhost:3306/jdbc";
String username="root";
String password="123456";
Connection conn = DriverManager.getConnection(url,username,password);
return conn;
}
public static void realse( Statement stmt , Connection conn) {
if(stmt!=null) {
try {
stmt.close();
}catch (SQLException e) {
e. printStackTrace();
}
stmt=null;
}
if(conn !=null) {
try {
conn.close();
}catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(conn!=null) {
try {
conn. close();
}catch (SQLException e) {
e.printStackTrace();
}
conn=null;
}
}
public static void release(ResultSet rs, Statement stmt , Connection con) {
if(rs!=null) {
try {
rs.close();
}catch (SQLException e) {
e. printStackTrace();
}
rs=null;
}
if(stmt!=null) {
try {
stmt.close();
}catch (SQLException e) {
e.printStackTrace();
}
stmt=null;
}
if(con!=null) {
try {
con. close();
}catch (SQLException e) {
e.printStackTrace();
}
con=null;
}
}
}
package cn.itcast.chapter10.example;
import java.sql.SQLException;
import org.apache.commons.dbutils.handlers.BeanHandler;
public class ResultSetTest1 {
public static void testBeanHandler() throws SQLException {
BaseDao basedao = new BaseDao();
String sql ="select * from user where id=?";
//获取查询结果
User user=(User) basedao.query(sql, new BeanHandler(User.class), 3);
System.out.print("name "+user.getName());
}
public static void main(String[] args) throws SQLException{
testBeanHandler();
}
}
package cn.itcast.chapter10.example;
import java.sql.SQLException;
import java.util.ArrayList;
import org.apache.commons.dbutils.handlers.BeanHandler;
public class ResultSetTest2 {
public static void testBeanHandler() throws SQLException {
BaseDao basedao = new BaseDao();
String sql ="select * from user ";
ArrayList<User>list=(ArrayList<User>) basedao.query(sql, new BeanHandler(User.class));
for(User user2:list) {
System.out.print("name "+user2.getName());
}
}
public static void main(String[] args) throws SQLException{
testBeanHandler();
}
}
package cn.itcast.chapter10.example;
public class User {
private int id;
private String name;
private String password;
public int getId(){
return id;
}
public void setId(int id){
this.id = id;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getPassword(){
return password;
}
public void setPassword(String password) {
this.password = password;
}
}