Prism代码语法高亮

第11章 数据库连接池与DBUtils工具


学习目标

上一章讲解了JDBC的基本用法和操作,由于每操作一次数据库,都会执行一次创建和断开数据库Connection对象的操作,频繁的操作Connection对象十分影响数据库的访问效率,并且增加了代码量,所以在实际开发中,开发人员通常会使用数据库连接池来解决这些问题。

Apache组织提供了一个DBUtils工具类库,该类库实现了对JDBC的简单封装,能在不影响数据库访问性能的情况下,极大地简化JDBC的编码工作。

1 数据库连接池

1.1 什么是数据库连接池

(1) JDBC连接数据库的缺陷

在JDBC编程中,每次创建和断开Connection对象都会消耗一定的时间和IO资源。在Java程序与数据库之间建立连接时,数据库端要验证访问数据库用户名和密码,并且要为这个连接分配资源,Java程序则要把代表连接的java.sql.Connection对象等加载到内存中,所以建立数据库连接的开销很大,尤其是在大量的并发访问时。频繁地创建、断开数据库连接会影响数据库的访问效率,甚至导致数据库崩溃

(2) 数据库连接池技术

为了避免频繁的创建数据库连接,工程师们提出了数据库连接池技术: 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立

图1 连接池连接数据库的原理图

减少创建和断开数据库连接的次数,提高数据库的访问效率。 DBCP、C3P0、Druid--阿里

1.2 DataSource接口

为了获取数据库连接对象(Connection),JDBC提供了javax.sql.DataSource接口,它负责与数据库建立连接(数据源中存储了所有建立数据库连接的信息----数据库连接池),并定义了返回值为Connection对象的方法:

常用的开源组织提供数据源实现有:JNDI、DBCP、C3P0和阿里Druid

数据源用于管理数据库连接池。

1.3 DBCP数据源

DBCP是数据库连接池(DataBase Connection Pool)的简称,是Apache组织下的开源连接池实现,也是Tomcat服务器使用的连接池组件。单独使用DBCP数据源时,需要在应用程序中导入两个jar包:commons-dbcp2.jar、commons-poo2.jar(本例使用commons-dbcp2-2.9.0.jar、commons-pool2-2.11.1.jar。 )。

官网下载地址:

https://commons.apache.org/proper/commons-dbcp/download_dbcp.cgi

https://commons.apache.org/proper/commons-pool/download_pool.cgi

https://commons.apache.org/proper/commons-logging/download_logging.cgi

(1) DBCP常见配置项

分类 属性 描述
必须项 driverClassName 数据库驱动名称
url 数据库的地址
username 用户名
password 密码
基本项(扩展) maxActive 最大连接数量
minIdle 最小空闲连接数
maxIdle 最大空闲连接数
initialSize 初始化连接数

(2) BasicDataSource类的常用方法(7个set、1个getConnection())

方法名称 功能描述
void setDriverClassName(String driverClassName) 设置连接数据库的驱动名称
void setUrl(String url) 设置连接数据库的路径
void setUsername(String username) 设置数据库的登陆账号
void setPassword(String password) 设置数据库的登录密码
void setInitialSize(int initialSize) 设置数据库连接池初始化的连接数目
void setMaxActive (int maxIdle) 设置数据库连接池最大活跃的连接数目
void setMinIdle(int minIdle) 设置数据库连接池最小闲置的连接数目
Connection getConnection() 从连接池中获取一个数据库连接

(3) 通过BasicDataSource类直接创建数据源对象

参照ch04创建ch11_zxx项目(添加Web框架支持、设置模块的Tomcat库和Web\WEB-INF\lib目录库支持、设置工件、配置运行配置),

将Java 8:mysql-connector-java-8.0.30.jar、commons-dbcp2-2.9.0.jar、commons-pool2-2.11.1.jar、commons-logging-1.2.jar 粘贴到 Web\WEB-INF\lib。

cn.zxx.Eg01_zxx.java。

package cn.zxx;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;

public class Eg01_zxx {
    public static DataSource ds = null;
    static {
        // 获取DBCP数据库连接池实现类对象
        BasicDataSource bds = new BasicDataSource();
        // 设置连接数据库需要的配置信息
        bds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        bds.setUrl("jdbc:mysql://公网ip:3306/jdbc_zxx?serverTimezone=GMT%2B8&characterEncoding=UTF-8&useSSL=false");
        bds.setUsername("root");
        bds.setPassword("******");
        // 设置连接池的初始化连接参数
        bds.setInitialSize(5);
        bds.setMaxTotal(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("通过BasicDataSource类直接创建数据源对象【张晓轩】\nURL="+metaData.getURL()
                +",\nUserName="+metaData.getUserName()
                +",\nDriverName="+metaData.getDriverName());
    }
}

运行main方法截图如下:

图2 通过BasicDataSource类直接创建数据源对象

(4) 通过BasicDataSourceFactory类读取配置文件创建数据源对象

src\dbcpconfig.properties。

#\u8FDE\u63A5\u8BBE\u7F6E
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://101.42.158.247:3306/jdbc_zxx?serverTimezone=GMT%2B8&characterEncoding=UTF-8&useSSL=false
username=root
password=****密码****.
#\u521D\u59CB\u5316\u8FDE\u63A5
initialSize=5
#\u6700\u5927\u8FDE\u63A5\u6570\u91CF
# maxActive=10
maxTotal=10
#\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
maxIdle=10

https://www.bejson.com/convert/unicode_chinese/ 请使用该网站转换上面的注释

cn.zxx.Eg02_zxx.java。

package cn.zxx;

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.dbcp2.BasicDataSourceFactory;

public class Eg02_zxx {
    public static DataSource ds = null;
    static {
        // 新建一个配置文件对象
        Properties prop = new Properties();
        try {
            // 通过类加载器找到文件路径,读配置文件
            InputStream in = new Eg02_zxx().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("通过BasicDataSourceFactory类读取配置文件创建数据源对象【张晓轩】\nURL="+metaData.getURL()
                + "\nUserName=" + metaData.getUserName() + ",\nDriverName=" + metaData.getDriverName());
    }
}

运行main方法截图如下:

图3 通过BasicDataSourceFactory类读取配置文件创建数据源对象

1.4 C3P0数据源

C3P0是目前最流行的开源数据库连接池之一,它实现了DataSource数据源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和 Spring使用的都是该数据源。(据可靠信息:C3P0连接池的作者其实是一个《星球大战》迷,C3P0就是其中的一个机器人名字,而且这个名称中包涵了Connection和Pool的单词字母。因此就叫了这个名字。)

官网下载地址:https://sourceforge.net/projects/c3p0/

c3p0-0.9.5.5.jar mchange-commons-java-0.2.19.jar

(1) C3P0类的常用方法(7个set、1个getConnection())

方法名称 功能描述
void setDriverClass() 设置连接数据库的驱动名称
void setJdbcUrl() 设置连接数据库的路径
void setUser() 设置数据库的登陆账号
void setPassword() 设置数据库的登录密码
void setMaxPoolSize() 设置数据库连接池最大的连接数目
void setMinPoolSize() 设置数据库连接池最小的连接数目
void setInitialPoolSize() 设置数据库连接池初始化的连接数目
Connection getConnection() 从数据库连接池中获取一个连接

当使用C3P0数据源时,首先得创建数据源对象,创建数据源对象可以使用ComboPooledDataSource类,该类有两个构造方法,分别是ComboPooledDataSource()和ComboPooledDataSource(String configName)。

需要注意的是,在使用ComboPooledDataSource(String configName)方法创建数据源对象时必须遵循以下两点:

(2) 通过ComboPooledDataSource类直接创建数据源对象

将c3p0-0.9.5.5.jar、mchange-commons-java-0.2.19.jar 粘贴到 Web\WEB-INF\lib。

cn.zxx.Eg03_zxx.java。

package cn.zxx;

import java.sql.SQLException;
import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Eg03_zxx {
    public static DataSource ds = null;
    // 初始化C3P0数据源
    static {
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        // 设置连接数据库需要的配置信息
        try {
            cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
            cpds.setJdbcUrl("jdbc:mysql://101.42.158.247:3306/jdbc_zxx?serverTimezone=GMT%2B8&characterEncoding=UTF-8&useSSL=false");
            cpds.setUser("root");
            cpds.setPassword("***密码***");
            // 设置连接池的参数
            cpds.setInitialPoolSize(10);
            cpds.setMaxPoolSize(15);
            ds = cpds;
        } catch (Exception e) {
            throw new ExceptionInInitializerError(e);
        }
    }

    public static void main(String[] args) throws SQLException {
        // 获取数据库连接对象
        System.out.println("通过ComboPooledDataSource类直接创建数据源对象【张晓轩】\n"+ds.getConnection());
    }
}

运行main方法截图如下:

图4 通过ComboPooledDataSource类直接创建数据源

(3) 通过读取配置文件创建数据源对象

src/c3p0-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
    <default-config>
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">
            jdbc:mysql://101.42.158.247:3306/jdbc_zxx?serverTimezone=GMT%2B8&amp;characterEncoding=UTF-8&amp;useSSL=false
        </property>
        <property name="user">root</property>
        <property name="password">***密码***</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="dzjiang">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">
            jdbc:mysql://101.42.158.247:3306/jdbc_zxx?serverTimezone=GMT%2B8&amp;characterEncoding=UTF-8&amp;useSSL=false
        </property>
        <property name="user">root</property>
        <property name="password">***密码***</property>
        <property name="initialPoolSize">10</property>
        <property name="maxPoolSize">15</property>
    </named-config>
</c3p0-config>

cn.zxx.Eg04_zxx.java。

package cn.zxx;

import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Eg04_zxx {
    public static DataSource ds = null;
    // 初始化C3P0数据源
    static {
        // 使用src\c3p0-config.xml配置文件中的default-config节点中name属性的值
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        ds = cpds;
        System.out.println(cpds.getJdbcUrl().toString());
    }
    public static void main(String[] args) throws SQLException {
        System.out.println("使用src\\c3p0-config.xml配置文件的<default-config>节点信息【张晓轩】\n"+ds.getConnection());
    }
}

运行main方法截图如下:

图5 使用c3p0-config.xml默认配置信息

cn.zxx.Eg05_zxx.java

第12行 dzjiang 对应src/c3p0-config.xml第17行定义

package cn.zxx;

import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Eg05_zxx {
    public static DataSource ds = null;
    // 初始化C3P0数据源
    static {
        // 使用src\c3p0-config.xml配置文件中的 named-config 节点中name属性的值
        ComboPooledDataSource cpds = new ComboPooledDataSource("dzjiang");
        ds = cpds;
        System.out.println(cpds.getJdbcUrl().toString());
    }
    public static void main(String[] args) throws SQLException {
        System.out.println("使用src\\c3p0-config.xml配置文件的<named-config>节点信息【张晓轩】\n"+ds.getConnection());
    }
}

运行main方法截图如下:

图6 使用c3p0-config.xml中【named-config】节点配置信息

2 DBUtils工具

commons-dbutils的核心是两个类和一个接口: DBUtils类、 QueryRunner类、 ResultSetHandler接口

https://commons.apache.org/proper/commons-dbutils/download_dbutils.cgi

2.1 DBUtils工具介绍

DBUtils工具的作用

为了更加简单地使用JDBC,Apache组织提供了一个DBUtils工具,它是操作数据库的一个组件,实现了对JDBC的简单封装,可以在不影响数据库访问性能的情况下简化JDBC的编码工作量。DBUtils工具要有三个作用。

DBUtils的核心类库的三个核心API

图7 DBUtils的核心类库的三个核心API

2.2 DBUtils类

DBUtils类主要为如关闭连接、装载JDBC驱动程序之类的常规工作提供方法,它提供的方法都是静态方法

方法名称 功能描述
void close(Connection conn) 当连接不为NULL时,关闭连接
void close(Statement stat) 当声明不为NULL时,关闭声明
void close(ResultSet rs) 当结果集不为NULL时,关闭结果集
void closeQuietly(Connection conn) 当连接不为NULL时,关闭连接,并隐藏一些在程序中抛出的SQL异常
void closeQuietly(Statement stat) 当声明不为NULL时,关闭声明,并隐藏一些在程序中抛出的SQL异常
void closeQuietly(ResultSet rs) 当结果集不为NULL时,关闭结果集,并隐藏一些在程序中抛出的SQL异常
void commitAndCloseQuietly(Connection conn) 提交连接后关闭连接,并隐藏一些在程序中抛出的SQL异常
Boolean loadDriver(String driveClassName) 装载并注册JDBC驱动程序,如果成功就返回true

2.3 QueryRunner类

QueryRunner类简化了执行SQL语句的代码它与ResultSetHandler组合在一起就能完成大部分的数据库操作,大大减少编码量。针对不同的数据库操作,QueryRunner类提供的不同的方法。

QueryRunner类的常用方法

方法名称 功能描述
Object query(Connection conn,String sql,ResultSetHandler rsh,Object[] params) 执行查询操作,传入的Connection对象不能为空
Object query (String sql, ResultSetHandler rsh,Object[] params) 执行查询操作
Object query (Connection conn,String sql, ResultSetHandler rsh) 执行一个不需要置换参数的查询操作
int update(Connection conn, String sql, ResultSetHandler rsh) 执行一个更新(插入、删除、更新)操作
int update(Connection conn, String sql) 执行一个不需要置换参数的更新操作
int batch(Connection conn,String sql, Object[] []params) 批量添加、修改、删除
int batch(String sql, Object[][] params) 批量添加、修改、删除

2.4 ResultSetHandler接口

ResultSetHandler接口用于处理ResultSet结果集,它可以将结果集中的数据转换为不同的形式。根据结果集中不同的数据类型,ResultSetHandler提供了几种常见的实现类

类名称 功能描述
AbstractKeyedHandler 该类为抽象类,能够把结果集里面的数据转换为用Map存储
AbstractListHandler 该类为抽象类,能够把结果集里面的数据转换为用List存储
ArrayHandler 把结果集中的第一行数据转成对象数组
ArrayListHandler 把结果集中的每一行数据都转成一个对象数组,再将数组存放到List中。
BaseResultSetHandler 把结果集转换成其他对象的扩展。
BeanHandler 将结果集中的第一行数据封装到一个对应的JavaBean实例中。
BeanListHandler 将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
BeanMapHandler 将结果集中的每一行数据都封装到一个对应的JavaBean实例中,然后再根据指定的key把每个JavaBean再存放到一个Map里。
ColumnListHandler 将结果集中某一列的数据存放到List中。
KeyedHandler 将结果集中的每一行数据都封装到一个Map里,然后再根据指定的key把每个Map再存放到一个Map里。
MapHandler 将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
MapListHandler 将结果集中的每一行数据都封装到一个Map里,然后再存放到List中。
ScalarHandler 将结果集中某一条记录的其中某一列的标量数据存储成Object对象

2.5 ResultSetHandler实现类

(1) BeanHandler和BeanListHandler

类名称 相同点 不同点
BeanHandler 都要先将结果集封装进JavaBean 封装单条数据,把结果集的第一条数据的字段放入一个JavaBean中
BeanListHandler 封装多条数据,把每条数据的字段值各放入一个JavaBean中,再把所有JavaBean都放入List集合中

(a) MySQL 数据表

# 下面表已经在上一章创建
create database jdbc_zxx DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_chinese_ci;
use jdbc_zxx;

CREATE TABLE 用户表(
        id INT PRIMARY KEY AUTO_INCREMENT,
        用户名 VARCHAR(40),
        密码 VARCHAR(40),
        电邮 VARCHAR(60),
        生日 DATE 
)CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO 用户表(用户名,密码,电邮,生日) VALUES
('张晓轩','1234560','zxx@sina.com','1963-12-01'),
('张三','1234561','zs@sina.com','1980-12-02'),
('李四','1234562','lisi@sina.com','1981-12-03'),
('王五','1234563','wangwu@sina.com','1979-12-04');

/*为了查看数据是否添加成功,使用SELECT语句查询users表,SQL语句如下所示*/
SELECT * FROM 用户表;

commons-dbutils-1.7.jar粘贴到 Web - WEB-INF - lib。

(b) cn.zxx.c3p0.javabean.User

package cn.zxx.c3p0.javabean;
public class User {
    private int id;
    private String 用户名;
    private String 密码;
    private String 电邮;
    private Date 生日;

    // setter | getter
    //toString
}

(c) src创建包cn.zxx.jdbc.utils,创建JDBCUtils.java

package cn.zxx.jdbc.utils;
import java.sql.*;

public class JDBCUtils {
    // 加载驱动,并建立数据库连接
    public static Connection getConnection() throws SQLException,
            ClassNotFoundException {
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://101.42.158.247:3306/jdbc_zxx?serverTimezone=GMT%2B8&characterEncoding=UTF-8&useSSL=false";
        String username = "root";
        String password = "*********";
        Connection conn = DriverManager.getConnection(url, username,
                password);
        return conn;
    }
    // 关闭数据库连接,释放资源
    public static void release(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();
            }
            conn = null;
        }
    }
    public static void release(ResultSet rs, Statement stmt,
                               Connection conn){
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;
        }
        release(stmt, conn);
    }
}

(d) 在cn.zxx.jdbc.dao 创建BaseDao.java

package cn.zxx.jdbc.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.dbutils.ResultSetHandler;
import cn.zxx.utils.JDBCUtils;

public class BaseDao {
    // 优化查询
    public static Object query(String sql, ResultSetHandler<?> rsh, 
             Object... params) throws SQLException {
            Connection conn = null;
            PreparedStatement pstmt = null;
            ResultSet rs = null;
            try {
                // 获得连接
                conn = JDBCUtils.getConnection();
                // 预编译sql
                pstmt = conn.prepareStatement(sql);
                // 将参数设置进去
                for (int i = 0; params != null && i < params.length; i++)  {
                    pstmt.setObject(i + 1, params[i]);
                }
                // 发送sql
                rs = pstmt.executeQuery();
                // 让调用者去实现对结果集的处理
                Object obj = rsh.handle(rs);
                return obj;
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                // 释放资源
                JDBCUtils.release(rs, pstmt, conn);
             }
            return rs;
        }
}

(e) cn.zxx.jdbc创建ResultSetTest1_zxx.java。演示BeanHandler类处理结果集。

package cn.zxx.jdbc;
import java.sql.SQLException;

import cn.zxx.jdbc.dao.BaseDao;
import cn.zxx.c3p0.javabean.User;
import org.apache.commons.dbutils.handlers.BeanHandler;
public class ResultSetTest1_zxx {
    public static void testBeanHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from 用户表 where id=?";
        User user = (User) basedao.query(sql,
                new BeanHandler(User.class), 1);
        System.out.println("演示BeanHandler类处理结果集【张晓轩】");
        System.out.println("id为1的User对象的【用户名】值为:" + user.get用户名());
        System.out.println("id为1的User对象为:" + user.toString());
    }
    public static void main(String[] args) throws SQLException {
        testBeanHandler();
    }
}

运行main方法截图如下:

图8 结果集中的第一行数据转成对象

(f) cn.zxx.Test_zxx.java 添加下列测试程序段

package cn.zxx.jdbc;
import java.sql.SQLException;
import java.util.ArrayList;
import cn.zxx.c3p0.javabean.User;
import cn.zxx.jdbc.dao.BaseDao;
import org.apache.commons.dbutils.handlers.BeanListHandler;

public class ResultSetTest2_zxx {
    public static void testBeanListHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from 用户表 ";
        ArrayList<User> list = (ArrayList<User>) basedao.query(sql,
                new BeanListHandler(User.class));
        System.out.println("演示BeanListHandler类处理结果集【张晓轩】");
        for (int i = 0; i < list.size(); i++) {
            System.out.println("第" + (i + 1) + "条数据的username值为:"
                    + list.get(i).get用户名());
        }
        System.out.println("---------------------------------------------");

        for (int i = 0; i < list.size(); i++) {
            System.out.println("第" + (i + 1) + "条数据:"
                    + list.get(i).toString());
        }
    }
    public static void main(String[] args) throws SQLException {
        testBeanListHandler();
    }
}

运行main方法截图如下:

图9 演示BeanListHandler类处理结果集

(2) ColumnListHandler和ScalarHandler

(a) cn.zxx.jdbc.ResultSetTest3_zxx.java

package cn.zxx.jdbc;
import java.sql.SQLException;
import cn.zxx.jdbc.dao.BaseDao;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
public class ResultSetTest3_zxx {
    public static void testColumnListHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from 用户表";
        Object arr = (Object) basedao.query(sql,
                new ColumnListHandler("用户名"));
        System.out.println("演示ColumnListHandler类的使用方法【张晓轩】");
        System.out.println("用户名:" +arr);
    }
    public static void main(String[] args) throws SQLException {
        testColumnListHandler();
    }
}

运行main方法截图如下:

图10 演示ColumnListHandler类的使用方法

(b) cn.zxx.jdbc.ResultSetTest4_zxx.java

package cn.zxx.jdbc;
import java.sql.SQLException;
import cn.zxx.jdbc.dao.BaseDao;
import org.apache.commons.dbutils.handlers.ScalarHandler;

public class ResultSetTest4_zxx {
    public static void testScalarHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from 用户表 where id=?";
        Object obj = (Object) basedao.query(sql,
                new ScalarHandler("用户名"), 1);
        System.out.println("演示ScalarHandler类的使用方法【张晓轩】");
        System.out.println(obj);
    }
    public static void main(String[] args) throws SQLException {
        testScalarHandler();
    }
}

运行main方法截图如下:

图11 演示ColumnListHandler类的使用方法

2.6 动手实践:使用DBUtils实现增删改查

(1) cn.zxx.c3p0.utils C3p0Utils.java

package cn.zxx.c3p0.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) cn.zxx.c3p0.dao.QueryDao_zxx.java

package cn.zxx.c3p0.dao;
import cn.zxx.c3p0.javabean.User;
import cn.zxx.c3p0.utils.C3p0Utils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;

import java.sql.SQLException;
import java.util.List;

public class QueryDao_zxx {
    public static void main(String[] args)throws SQLException {
        // 创建QueryRunner对象
        QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
        // 写SQL语句
        String sql = "select * from 用户表 where id=2";
        // 调用方法
        User user1 = (User) runner.query(sql,new BeanHandler(User.class));
        System.out.println("id=2  "+user1.toString());
        System.out.println("---------------------------------");

        // 写SQL语句
        sql = "select * from 用户表";
        // 调用方法
        List<User> list = (List) runner.query(sql,new BeanListHandler(User.class));
        for(User user : list){
            System.out.println(user.toString());
        }
    }
}

运行main方法截图如下:

图12 QueryDao

(3) cn.zxx.c3p0.dao.InsertDao_zxx.java

package cn.zxx.c3p0.dao;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import cn.zxx.c3p0.utils.C3p0Utils;
public class InsertDao_zxx {
    public static void main(String[] args)throws SQLException{
        // 创建QueryRunner对象
        QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
        String sql = "insert into 用户表 (id,用户名,密码,电邮,生日) values (7,'孙七','1234567','孙七@139.com','2001-01-07')";
        int num = runner.update(sql);
        if (num > 0){
            System.out.println("添加【孙七】成功!----【张晓轩】");
        }else{
            System.out.println("添加【孙七】失败!----【张晓轩】");
        }
    }
}

运行main方法截图如下:

图13 QueryDao

(4) cn.zxx.c3p0.dao.UpdateDao_zxx.java

package cn.zxx.c3p0.dao;
import cn.zxx.c3p0.utils.C3p0Utils;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.SQLException;
public class UpdateDao_zxx {
    public static void main(String[] args)throws SQLException {
        // 创建QueryRunner对象
        QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
        // 写SQL语句
        String sql = "update 用户表 set 用户名='孙小七',密码='7777777' where 用户名='孙七'";
        // 调用方法
        int num = runner.update(sql);
        if (num > 0){
            System.out.println("修改[孙七]成功!---- 【张晓轩】");
        }else{
            System.out.println("修改[孙七]失败!---- 【张晓轩】");
        }
    }
}

运行main方法截图如下:

图14 QueryDao

(5) cn.zxx.c3p0.dao.DeleteDao_zxx.java

package cn.zxx.c3p0.dao;
import cn.zxx.c3p0.utils.C3p0Utils;
import org.apache.commons.dbutils.QueryRunner;
import java.sql.SQLException;
public class DeleteDao_zxx {
    public static void main(String[] args)throws SQLException {
        // 创建QueryRunner对象
        QueryRunner runner = new QueryRunner(C3p0Utils.getDataSource());
        // 写SQL语句
        String sql = "delete from 用户表 where 用户名='赵六'";
        // 调用方法
        int num = runner.update(sql);
        if (num > 0){
            System.out.println("删除[赵六]成功!----【张晓轩】");
        }else{
            System.out.println("删除[赵六]失败!----【张晓轩】");
        }
    }
}

运行main方法截图如下:

图15 QueryDao
图16 本章程序截图

愿者可参阅《JavaWeb程序开发进阶》:


返回