第十章 数据库连接池 与DBUtils

数据库连接池
DBCP数据源

        DBCP是数据库连接池(DataBase Connection Pool)的简称,是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包中的很多方法就没有办法实现。


这两个JAR包可以在Apache官网地址“http://commons.apache.org/proper/”中查询下载到。其中,commons-dbcp.jar中包含两个核心的类,分别是BasicDataSourceFactory和BasicDataSource,它们都包含获取DBCP数据源对象的方法。

通过 BasicDataSource 类直接创建数据源对象
        在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目录下创建包pidan.example,并在该包下创建一个Example01类,该类采用手动方式获取数据库的连接信息和数据源的初始化信息

package pidan.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 {
        //获得DBCP数据源实现类对象
        BasicDataSource bds = new BasicDataSource();
        //设置连接数据库需要的配置信息
        bds.setDriverClassName("com.mysql.jdbc.Driver");
        bds.setUrl("jdbc:mysql://localhost:3306/jdbc");
        bds.setUsername("root");
        bds.setPassword("123456");
        //设置参数池的参数
        bds.setInitialSize(5);
        bds.setMaxActive(5);
        ds = bds;
    }
    public static void main(String[] args) throws SQLException{
        //获取数据库连接对象
        Connection conn = ds.getConnection();
        //获取数据库连接信息
        DatabaseMetaData metaData = conn.getMetaData();
        //打印数据库连接信息
        System.out.println(metaData.getURL()
                +",UserName=" + metaData.getUserName()
                +","+metaData.getDriverName());
    }
}

 运行main()方法后,程序的运行结果如图

 通过读取配置文件创建数据源对象
        除了使用BasicDataSource 直接创建数据源对象外,还可以使用BasicDataSourceFactory工厂类读取配置文件,创建数据源对象,然后获取数据库连接对象。
(1)在chapter10项目的src目录下创建dbcpconfig.properties文件,该文件用于设置数据库的连接信息和数据源的初始化信息

driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc
username=root
password=123456
 
initialSize=5
 
maxActive=10
 
maxIdle=10

(2)在pidan.example包下创建一个Example02类,该类中采用了从配置文件中获取数据库的连接信息和数据源的初始化信息的方式

package pidan.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.commons.dbcp.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()
                +",UserName=" + metaData.getUserName()
                +","+metaData.getDriverName());
    }
}

运行main()方法后,程序的运行结果如图

 通过 ComboPooledDataSource()构造方法创建数据源对象
(1)在项目chapter10中导入JAR包c3p0-0.9.1.2.jar,然后在cn.itcast.chapter10.example
包下创建一个Example03类,该类采用C3PO数据源手动代码的方式获取Connection对象

package pidan.example;
 
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
 
 
public class Example03 {
    public static DataSource ds= null;
    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());
    }
}

 通过读取配置文件创建数据源对象
使用 ComboPooledDataSource(String configName)构造方法读取c3p0-config.xml配
置文件,从而创建数据源对象,然后获取数据库连接对象。
(1)在src根目录下创建一个c3p0-config.xml文件,用于设置数据库的连接信息和数据源的初始化信息


<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">
             jdbc:mysql://localhost:3306/jdbc
         </property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="checkoutTimeout">30000</property>
        <property name="initialPoolSize">10</property>
        <property name="maxIdleTime">30</property>
        <property name="maxPoolSize">100</property>
        <property name="minPoolSize">10</property>
        <property name="maxStatements">200</property>
    </default-config> 
    <named-config name="pidan">
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">
               jdbc:mysql://localhost:3306/jdbc
        </property>
        <property name="user">root</property>
        <property name="password">123456</property>
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">15</property>
    </named-config>
</c3p0-config>

c3p0-config.xml 配置了两套数据源,<default-config>.…</default-config>中的信息是默认配置,在没有指定配置时默认使用该配置创建C3p0数据源对象;<named-config>…</ named-config >中的信息是自定义配置,一个配置文件中可以有零个或多个自定义配置,当用户需要使用自定义配置时,调用ComboPooledDataSource(String configName)方法,传入<named-config>节点中name属性的值即可创建C3PO数据源对象。这种设置的好处是,当程序在后期更换数据源配置时,只需要修改构造方法中对应的name值即可。
(2)在pidan.example包下创建一个Example04类,该类中使用C3P0数据源从配置文件中获取Connection对象

package pidan.example;
 
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
 
public class Example04 {
    public static DataSource ds= null;
    static {
        ComboPooledDataSource cpds = new ComboPooledDataSource("pidan");
        ds = cpds;
    }
    public static void main(String[] args) throws SQLException{
        System.out.println(ds.getConnection());
    }
}

运行main()方法后,程序的运行结果如图

 

DBUtils 工具
ResultSetHandler 实现类

1. BeanHandler 和 BeanListHandler
BeanHandler和BeanListHandler实现类是将结果集中的数据封装到对应的JavaBean实例中,这也是实际开发中最常用的结果集处理方法。

(1)在名为jdbc的数据库中创建数据表user,创建语句如下


USE jdbc;
CREATE TABLE user(
id INT(3) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
password VARCHAR(20) NOT NULL
);

向user表插入3条数据,具体语句如下

INSERT INTO user (name, password) VALUES ('zhangsan','123456');
INSERT INTO user (name, password) VALUES ('lisi','123456');
INSERT INTO user (name, password) VALUES ('wangwu','123456');

为了查看数据是否添加成功,使用SELECT语句查询user表

(2)将下载的DBUtils 工具的JAR包commons-dbutils-1.6.jar添加到项目的 lib目录中,并将第9章中文件JDBCUtils.java复制到pidan.example包下。

(3)在chapter10项目的pidan.example包中创建一个名为BaseDao的类,该类中编写了一个通用的查询方法

package pidan.example;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import org.apache.commons.dbutils.ResultSetHandler;
 
public class BaseDao {
    public static Object query(String sql,ResultSetHandler<?> rsh,Object... params) throws SQLException{
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        
        Object obj = null;
        try {
            conn = JDBCUtils.getConnection();
            pstmt = conn.prepareStatement(sql);
            
            for (int i = 0; params != null && i < params.length; i++) {
                pstmt.setObject(i+1, params[i]);
            }
            rs = pstmt.executeQuery();
            obj = rsh.handle(rs);
        } catch (Exception e) {
            return new Exception(e.getMessage());
        }finally {
            JDBCUtils.release(rs, pstmt,conn);
        }
        return obj;
    }

(4)在pidan.example包下创建实体类User,使用该类来封装User对象(建议自己getset)

package pidan.example;
 
public class User {
    private int id;
    private String name,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;
    }
}

(5)在 pidan.example包下创建类ResultSetTest1,该类用于演示BeanHandler类对结果集的处理

package pidan.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=?";
        Object object = baseDao.query(sql, new BeanHandler(User.class), 1);
        if (object!=null && object instanceof User) {
            User user = (User) object;
            System.out.println("id=1的User对象的name值为:"+ user.getName());
        }else {
            System.out.println("查询结果为空:"+object);
        }
    }
    public static void main(String[] args) throws SQLException{
        testBeanHandler();
    }
}

 

6)执行类ResultSetTest1中的main()方法

 输出结果可以看出,BeanHandler已成功将id为1的数据存入到了实体对象user中。


(7)在pidan.example包下创建类ResultSetTest2,该类用于演示BeanListHandler类对结果集的处理

package pidan.example;
 
import java.sql.SQLException;
import java.util.ArrayList;
 
import org.apache.commons.dbutils.handlers.BeanListHandler;
 
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 BeanListHandler(User.class));
        for (int i =0; i < list.size(); i++) {
            System.out.println("第" + (i + 1) + "条数据的username值为:"
                    + list.get(i).getName());
        }
    }
    public static void main(String[] args) throws SQLException{
        testBeanHandler();
    }
}

(8)执行类ResultSetTest2中的main()方法

 由输出结果可以看出,testBeanListHandler()方法可以将每一行的数据都封装到user实体对象中,并将其存放到list中。


2. ScalarHandler
        在使用DBUtils工具操作数据库时,如果需要输出结果集中一行数据的指定字段值,可以使用ScalarHandler类。
(1)在 pidan.example 包下创建类 ResultSetTest3,该类用于演示 ScalarHandler类的使用方法

package pidan.example;
 
import java.sql.SQLException;
 
import org.apache.commons.dbutils.handlers.ScalarHandler;
 
public class ResultSetTest3 {
    public static void testBeanHandler() throws SQLException{
        BaseDao baseDao = new BaseDao();
        String sql = "select * from user where id=?";
        Object arr = (Object) BaseDao.query(sql, new ScalarHandler("name"), 1);
        System.out.println(arr);
    }
    public static void main(String[] args) throws SQLException{
        testBeanHandler();
    }
}

 (2)执行类ResultSetTest3中的main()方法

【任务】使用DBUtils实现增删改查

1.创建C3p0Utils类

        在项目chapter10的src目录下,创建一个名为pidan.jdbc.utils的包,然后在该包下创建C3p0Utils类,该类用于创建数据源

package pidan.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;
    }
}

 

2.创建DBUtilsDao类

        在项目chapter10的src目录下,创建一个名为pidan.jdbc.demo的包,然后在该包下创建一个DBUtilsDao类,该类实现了对user表增删改查的基本操作。

package pidan.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 pidan.example.User;
import pidan.jdbc.utils.C3p0Utils;
 
public class DBUtilsDao {
    public List findAll() throws SQLException{
        QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
        
        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 runner = new QueryRunner(C3p0Utils.getDataSource());
        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 runner = new QueryRunner(C3p0Utils.getDataSource());
        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 updata(User user) throws SQLException{
        QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
        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 runner = new QueryRunner(C3p0Utils.getDataSource());
        String sql = "delete from user where id=?";
        int num = runner.update(sql,id);
        if (num > 0) {
            return true;
        }
        return false;
    }
}

上述代码中,使用了QueryRunner类中带参的方法,将数据源传给QueryRunner对象,并使用QuervRunner对象创建和关闭了数据库连接。
        这样,就实现了用DBUtils工具对数据库的基本操作。需要注意的是,在查询方法中,用到了 BeanHandler和BeanListHandler实现类来处理结果集,查询一条数据用的是能够处理一行数据的BeanHandler类,查询所有数据时用的是能处理所有行数据的BeanListHandler类,切勿错误使用,否则会造成程序报错。


3.测试DBUtilsDao类中的增删改查操作
(1)增加数据。在 pidan.jdbc.demo包中创建类DBUtilsDaoTest1对增加操作进行测试
 

package pidan.jdbc.demo;
 
import java.sql.SQLException;
 
import pidan.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();
    }
}

执行DBUtilsDaoTest1的控制台执行结果

从图中可以看到,控制台的输出结果为true,这说明执行插入操作成功。此时在数据库中查询user表中的数据,查询结果如图

 从图中可以看出,添加方法执行成功。
(2)修改数据。在pidan.jdbc.demo包下创建测试类DBUtilsDaoTest2。

package pidan.jdbc.demo;
 
import java.sql.SQLException;
 
import pidan.example.User;
 
public class DBUtilsDaoTest2 {
    private static DBUtilsDao dao = new DBUtilsDao();
    public static void testupdate() throws SQLException{
        User user = new User();
        user.setName("zhaoliou");
        user.setPassword("666777");
        user.setId(4);
        boolean b = dao.updata(user);
        System.out.println(b);
    }
    public static void main(String[] args) throws SQLException{
        testupdate();
    }
}

执行DBUtilsDaoTest2的控制台执行结果

 从图中可以看出,程序已经执行成功。此时再次查询数据库中user表的数据,查询结果如图

 从图中可以看出,修改方法执行成功。
(3)删除数据。在pidan.jdbc.demo包下创建测试类DBUtilsDaoTest3

package pidan.jdbc.demo;
 
import java.sql.SQLException;
 
import pidan.example.User;
 
public class DBUtilsDaoTest3 {
    private static DBUtilsDao dao = new DBUtilsDao();
    public static void testupdate() throws SQLException{
        
        boolean b = dao.delete(4);
        System.out.println(b);
    }
    public static void main(String[] args) throws SQLException{
        testupdate();
    }
}

执行DBUtilsDaoTest3的控制台执行结果

从图中可以看到,控制台显示的输出结果为true,此时查询数据库中user表的数据,查询结果如图

 

 从图中可以看出,已成功删除user表中id为4的数据。
(4)查询数据。在pidan.jdbc.demo包下创建测试类DBUtilsDaoTest4

package pidan.jdbc.demo;
 
import java.sql.SQLException;
 
import pidan.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();
    }
}

执行DBUtilsDaoTest4的控制台执行结果

 从图中可以看出,控制台已经成功显示出了id为2的数据信息,这说明查询方法也成功执行了。至此,已经完成了使用DBUtils工具对数据库进行的基本操作。从代码上可以看出,DBUtils工具在减少代码量的同时,还增强了代码的规整性和易读性。

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值