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

参考博文:

详解Java数据库连接池

类加载器与 Class.getResourceAsStream 问题解决

JDBC----学习(16)----DBUtils工具类 ResultSetHandler

JDBC工具类-DButils(QueryRunner-ResultSetHandler)

1 数据库连接池

1.1数据看看连接池那点事

由于每操作一次数据库,都会执行一次创建和断开Connection对象的操作,频繁的操作Connection对象十分影响数据库的访问效率,并且增加了代码量,所以在实际开发中,开发人员通常会使用数据库连接池来解决这些问题。数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用现有的数据库连接,而不是重新建立。

1.1.1优点:

1.节省资源,如果每次访问数据库都创建新的连接,创建和销毁都浪费系统资源
2.响应性更好,省去了创建的时间,响应性更好。
3.统一管理数据库连接,避免因为业务的膨胀导致数据库连接的无限增多。
4.便于监控。

1.1.2常用连接池方案:

数据库连接池的方案有不少,接触过的连接池方案有:

1.C3p0

这个连接池我很久之前看到过,但是当时自己还很弱小,并没有很好的理解,现在用的也很少了,爷爷级的连接池,可以忽略

2.DBCP (Database Connection Pool)

这个名字很直白,数据库连接池,从Tomcat 5.5开始,Tomcat 内置了DBCP的数据源实现,所以可以非常方便地配置DBCP数据源。

3.Druid

阿里开源的数据源,这个也是前公司使用的数据源,Druid能够提供强大的监控和扩展功能,强项在于监控。

4.HiKariCP

号称最快的数据库连接池,springboot2.0 也已经把默认的数据源改为了HikariCP,强于性能。

1.2 Druid 的数据库连接池的配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${db.driverClassName}"/>
<property name="url" value="${db.url}"/>
<property name="username" value="${db.username}"/>
<property name="password" value="${db.password}"/>
<property name="initialSize" value="5"/>
<property name="maxIdle" value="10"/>
<property name="minIdle" value="5"/>
<property name="maxActive" value="15"/>
<property name="removeAbandoned" value="true"/>
<property name="removeAbandonedTimeout" value="180"/>
<property name="maxWait" value="3000"/>
<property name="validationQuery">
<value>SELECT 1</value>
</property>
<property name="testOnBorrow">
<value>true</value>
</property>
</bean>

 1.driverClassName 使用的JDBC驱动的完整有效的Java类名,如连接 mysql  com.mysql.cj.jdbc.Driver

2.jdbcUrl 数据库的连接。如 jdbc:mysql://127.0.0.1:3306/mydatabase

3.username 你懂的,数据库的用户名,如 root

4.password 太直白了 ,数据库的用户密码,如 p123456

5.initialSize 连接池创建的时候,自动创建的数据库连接数量,建议 10-50足够

6.maxIdle 最大空闲连接:连接池中允许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制,建议设置和 与initialSize相同,减少释放和创建的性能损耗。

7.minIdle  最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建

8.maxActive 最大同时激活的连接数量。

9.maxWait 如果连接池中没有可用的连接,最大的等待时间,超时则没有可用连接,单位毫秒,设置-1时表示无限等待,建议设置为100毫秒

10.testxxx  在对连接进行操作时,是否检测连接的有效性,如 testOnBorrow 在申请连接的时候会先检测连接的有效性,执行validationQuery ,建议线上的把此配置设置为false,因为会影响性能。

11.validationQuery 检查池中的连接是否仍可用的 SQL 语句,drui会连接到数据库执行该SQL, 如果正常返回,则表示连接可用,否则表示连接不可用,建议 select 1 from dual

pom.xml 加入依赖

<dependency>
     <groupId>com.alibaba</groupId>
     <artifactId>druid</artifactId>
     <version>1.2.6</version>
   </dependency>

配置文件

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <!-- 基本属性 url、user、password -->
    <property name="driverClassName" value="${jdbc.driver}" />
    <property name="url" value="${jdbc_url}" />
    <property name="username" value="${jdbc_user}" />
    <property name="password" value="${jdbc_password}" />
  
    <!-- 配置监控统计拦截的filters -->
    <property name="filters" value="stat" />
  
    <!-- 配置初始化大小、最小、最大 -->
    <property name="maxActive" value="20" />
    <property name="initialSize" value="1" />
    <property name="minIdle" value="1" />
  
    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000" />    
  
    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
  
    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000" />
  
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="false" />
    <property name="testOnReturn" value="false" />
  
    <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
    <property name="poolPreparedStatements" value="true" />
    <property name="maxOpenPreparedStatements" value="20" />
</bean>
  
<!--配置jdbcTemplate,如果userDao没有extends JdbcDaoSupport-->
<<bean id="jdbcTemplate" class="com.springframework.jdbc.core.JdbcTemplate">
       <property name="dataSource" ref="dataSource"/>
   </bean>
    <bean id="userDao" class="com.caraway.dao.UserDao">
       <property name="dataSource" ref="jdbcTemplate"/>
   </bean>

调用

public static void main(String[] args) {
       ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
       UserDao userDao = (UserDao) context.getBean("userDao");
       User user = new User();
       user.setUsername("香菜");
       user.setPassowrd("root");
       userDao.saveUser(user);
  }

1.3 DBCP (Database Connection Pool)

先导入commons-dbcp2.jarcommons-pool2.jar两个JAR包:

commons-dbcp2.jar包是DBCP数据库连接池的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法

commons-pool2.jar包是commons-dbcp2.jar包的依赖包,commons-dbcp2.jar包中的方法提供了支持

commons-dbcp2.jar包含两个核心类,分别是BasicDataSourceFactoryBasicDataSource,它们都包含获取DBCP数据库连接池对象的方法。

BasicDataSource类的常用方法:

方法名称

功能描述

void setDriverClassName(String driverClassName)

设置连接数据库的驱动名称

void setUrl(String url)

设置连接数据库的路径

void setUsername(String username)

设置数据库的登录账号

void setPassword(String password)

设置数据库的登录密码

void setInitialSize(int initialSize)

设置数据库连接池初始化的连接数目

void setMinIdle(int minIdle)

设置数据库连接池最小闲置连接数目

Connection getConnection()

从连接池中获取一个数据库连接

BasicDataSourceFactory工厂类

创建BasicDataSource对象的工厂类,它包含一个返回值为BasicDataSource类型的方法createDataSource(),该方法通过读取配置文件的信息生成数据源对象并返回给调用者。把数据库的连接信息和数据源的初始化信息提取出来写进配置文件,这样让代码看起来更加简洁,思路也更加清晰。

1.3.1 案例1:通过BasicDataSource类直接创建数据源对象

项目中导入mysql-connector-java-8.0.15.jarcommons-dbcp2-2.7.0.jarcommons-logging-1.2.jar以及commons-pool2-2.8.0.jar四个JAR包,并发布到类路径下:

package chapter11;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.commons.dbcp2.BasicDataSource;
public class Example01 {
    public static DataSource ds = null;
    static {
        // 获取DBCP数据库连接池实现类对象
        BasicDataSource bds = new BasicDataSource();
        // 设置连接数据库需要的配置信息
        bds.setDriverClassName("com.mysql.cj.jdbc.Driver");
        bds.setUrl("jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8");
        bds.setUsername("root");
        bds.setPassword("123456");
        // 设置连接池的初始化连接参数
        bds.setInitialSize(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());
    }
}

1.3.2 案例2:通过读取配置文件创建数据源对象

注意:在src目录下新建 Source Folder,然后进入Source Folder 新建 general->file :dbcpconfig.properties,否则提示  找不到 resource  文件。

#连接设置
driverClassName=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8
username=root
password=root
#初始化连接
initialSize=5
#最大空闲连接
maxIdle=10

 Example02

package chapter11;
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 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());
    }
}

1.4 C3P0数据库连接池

C3P0是流行的开源数据库连接池之一,它实现了DataSource数据源接口,支持JDBC2JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架HibernateSpring都支持该数据库连接池。在使用C3P0数据库连接池开发时,需要了解C3P0DataSource接口的实现类ComboPooledDataSource,它是C3P0的核心类,提供了数据源对象的相关方法

ComboPooledDataSource类的常用方法:

方法名称

功能描述

void setDriverClass()

设置连接数据库的驱动名称

void setJdbcUrl()

设置连接数据库的路径

void setUser()

设置数据库的登录账号

void setPassword()

设置数据库的登录密码

void setMaxPoolSize()

设置数据库连接池最大连接数目

void setMinPoolSize()

设置数据库连接池最小连接数目

void setInitialPoolSize()

设置数据库连接池初始化的连接数目

Connection getConnection()

从数据库连接池中获取一个连接

C3P0数据库连接池时,首先需要创建数据源对象,创建数据源对象可以通过调用ComboPooledDataSource的构造方法实现。ComboPooledDataSource类有两个构造方法,分别是ComboPooledDataSource()ComboPooledDataSource(String configName)

1.4.1 通过ComboPooledDataSource()构造方法创建数据源对象

调用ComboPooledDataSource()构造方法创建数据源对象,需要手动给数据源对象设置属性值,然后获取数据库连接对象。

导入JARc3p0-0.9.2.1.jarmchange-commons-java-0.2.3.4.jar

package chapter11;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class Example03 {
    public static DataSource ds = null;
    // 初始化C3P0数据库连接池
    static {
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        // 设置连接数据库需要的配置信息
        try {
            cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
            cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8");
            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());
    }
}

1.4.2 通过ComboPooledDataSource(String configName)构造方法创建数据源对象

调用ComboPooledDataSource(String configName)构造方法可以读取c3p0-config.xml配置文件,根据配置文件中的配置信息创建数据源对象,然后获取数据库连接对象。

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://localhost:3306/jdbc?serverTimezone=GMT%2B8
        </property>
        <property name="user">root</property>
        <property name="password">root</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="itcast">
        <property name="driverClass">com.mysql.cj.jdbc.Driver</property>
        <property name="jdbcUrl">
            jdbc:mysql://localhost:3306/jdbc?serverTimezone=GMT%2B8
        </property>
        <property name="user">root</property>
        <property name="password">root</property>
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">15</property>
    </named-config>
</c3p0-config>

Example04

package chapter11;

import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class xample04 {
    public static DataSource ds = null;
    // 初始化C3P0数据库连接池
    static {
        // 使用c3p0-config.xml配置文件中的named-config节点中name属性的值
        ComboPooledDataSource cpds = new ComboPooledDataSource("itcast");
        ds = cpds;
    }
    public static void main(String[] args) throws SQLException {
        System.out.println(ds.getConnection());
    }
}

2 DBUtils工具

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

写数据 DBUtils 可以通过编写 SQL 语句对数据表进行增、删、改操作。
读数据 DBUtils 工具可以将从数据表中读取的数据结果集转换成 Java 常用类集合,以方便对结果进行处理。
优化性能 ,在使用 DBUtils 工具的基础上,程序可以使用数据源、 JNDI 、数据库连接池等技术减少代码冗余。

 2.1核心类库介绍

2.1.1 DBUtils

DBUtils类主要提供了加载JDBC驱动、关闭资源等方法DBUtils类中的方法一般为静态方法,可以直接使用类名进行调用。

DBUtils类的常用方法:

方法名称

功能描述

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.1.2 QueryRunner类

QueryRunner类简化了执行SQL语句的代码,它与ResultSetHandler配合就能完成大部分的数据库操作,大大减少了编码量。QueryRunner类提供了带有一个参数的构造方法,该方法以javax.sql.DataSource的实例对象作为参数传递到QueryRunner的构造方法中来获取Connection对象。针对不同的数据库操作,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.1.2 ResultSetHandler接口

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

BeanHandler :将结果集中的第一行数据封装到一个对应的 JavaBean 实例中。
BeanListHandler :将结果集中的每一行数据都封装到一个对应的 JavaBean 实例中,并存放到 List 里。
ColumnListHandler :将某列属性的值封装到 List 集合中。
ScalarHandler :将结果集中某一条记录的某一列数据存储成 Object 对象。

ResultSetHandler接口还提供了一个单独的方法handle (java.sql.ResultSet rs),如果上述实现类没有提供想要的功能,可以自定义一个实现ResultSetHandler接口的类,然后通过重写handle()方法,实现结果集的处理。

BeanHandlerBeanListHandler

BeanHandler BeanListHandler 实现类是将结果集中的数据封装到对应的 JavaBean 中。在封装时,表中数据的字段和 JavaBean 的属性是相互对应的,一条数据记录被封装进一个对应的 JavaBean对象中。

类名称

相同点

不同点

BeanHandler

都要先将结果集封装进JavaBean

封装单条数据,把结果集的第一条数据的字段放入一个JavaBean

BeanListHandler

封装多条数据,把每条数据的字段值各放入一个JavaBean中,再把所有JavaBean都放入List集合中

ColumnListHandlerScalarHandler

ColumnListHandlerScalarHandler类可以对指定的列数据进行封装,在封装时,查询指定列数据,然后将获得的列数据封装到容器中。ColumnListHandlerScalarHandler的对比如下表所示。

类名称

相同点

不同点

ColumnListHandler

都是对指定列的查询结果集进行封装

封装指定列的所有数据,将他们放入一个List集合中

ScalarHandler

封装单条列数据,也可以封装类似countavgmaxminsum等聚合函数的执行结果

关于可变参数:

:Object…  params于是百度查了查。

这是JDK1.5新增语法,新特性,动态参数或者是可变参数的意思。
(1)使用…将参数声明成可变长参数。
(2)可变长参数必须是最后一个参数。
(3)可变参数同时可以跟固定的参数混合使用,但是一个方法的参数中不能同时拥有2种类型的可变参数。

案例代码
user类:

package chapter11;
import java.util.Date;
public class user {

    private int id;
    private String name;
    private String password;
    private String email;
    private Date birthday;
    
    public user() {
    	
    }
    public user(int id,String name,String password,String email,Date birthday) {
    	this.id = id;
    	this.name = name;
    	this.password = password;
    	this.email = email;
    	this.birthday = birthday;
    }

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String username) {
        this.name = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public String getEmail() {
        return email;
    }
    public void setEmail(String email) {
        this.email = email;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
}

BaseDao的类,在该类中编写一个通用的查询方法。

package chapter11;


import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.commons.dbutils.ResultSetHandler;

import chapter10.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();
            
         // 处理结果集 验证
            while (rs.next()) {

                System.out.println("id: " + rs.getInt("id") + " ,name: " + rs.getString("name"));
            }
            
            // 让调用者去实现对结果集的处理
            //Object obj = rsh.handle(rs);
            Object obj = rsh.handle(rs);
            return obj;
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            // 释放资源
            JDBCUtils.release(rs, pstmt, conn);
        }
        return rs;
    }
    
    
    /* 目前重新的有点问题 稍后修改
    public static Object query(Connection connection,String sql, ResultSetHandler<?> rsh,
            Object... params) throws SQLException 
    {
		Connection conn = connection;
		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();
			
			// 处理结果集 验证
			while (rs.next()) {
			
				System.out.println("id: " + rs.getInt("id") + "name: " + rs.getString("name"));
		}
	
		// 让调用者去实现对结果集的处理
		Object obj = rsh.handle(rs);
		@Override
		public List<Blog> handle(ResultSet rs) throws SQLException {
			List<Blog> lists = new ArrayList<Blog>();
			while(rs.next()){
				Blog blog = new Blog();
				blog.setId(rs.getInt("id"));
				blog.setContent(rs.getString("content")+"huangbaokang");
				blog.setTitle(rs.getString("title")+"黄宝康");
				lists.add(blog);
			}
			return lists;
		}
		return obj;
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
		// 释放资源
			JDBCUtils.release(rs, pstmt, conn);
		}
			return rs;
	}
    */
    
}

验证代码类:

package chapter11;

import java.sql.Connection;

import java.sql.SQLException;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import chapter10.JDBCUtils;

import java.util.ArrayList;

public class ResultSetTest {
	

	public static void main(String[] args) throws SQLException {
		testBeanHandler();
		//testBeanListHandler();
		//testColumnListHandler();
		
		//testScalarHandler();
	
	}
	
	/*
	//BeanHandler类处理结果集
    public static void myBeanHandler() throws SQLException {
    	Connection connection = null;
    	try {
    		connection = JDBCUtils.getConnection();
    		String sql = "select id,name,password,email,birthday from users where id = ?";
    		users customers=(users) BaseDao.query(connection, sql, new BeanHandler(users.class), 1);
    		System.out.println(customers);
    	} catch (Exception e) {
    		e.printStackTrace();
    	} finally {
    		JDBCUtils.release(null, connection);
    	}

	} */
	
	//BeanHandler类处理结果集
	public static void testBeanHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from users where id=?;";
        //String sql = "select id,name,password,email,birthday from users where id=?;";
        @SuppressWarnings({ "static-access", "rawtypes", "unchecked" })
		user myuser = (user) basedao.query(sql, new BeanHandler(user.class), 1);
        if (myuser == null)
        {
        	System.out.print("返回记录个数为:null" );
        }
        else {
        	System.out.print("id为1的users对象的name值为:" + myuser.getName());
		}
        
        
    }
	
	//BeanListHandler类处理结果
	public static void testBeanListHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from users;";
        @SuppressWarnings({ "static-access", "unchecked", "rawtypes" })
		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());
        }
	}
	
	//ColumnListHandler
	public static void testColumnListHandler() throws SQLException {
        BaseDao basedao = new BaseDao();
        String sql = "select * from users;";
        Object arr = (Object) basedao.query(sql,
                new ColumnListHandler("name"));
        System.out.println(arr);
    }
	
	//ScalarHandler类的使用
	public static void testScalarHandler() throws SQLException {
		BaseDao basedao = new BaseDao();
		String sql = "select * from users where id=?";
		Object arr = (Object) basedao.query(sql, 
                               new ScalarHandler("name"), 1);
		System.out.println(arr);
	}


}

通过验证代码发现,测试过程中,发现调用(user) basedao.query(sql, new BeanHandler(user.class), 1);语句时,能查询到结果。但是:

 // 让调用者去实现对结果集的处理
Object obj = rsh.handle(rs);

会报错,无法正确转换。重新query类还未完成,稍后再做。

针对以上问题采用c3p0.ComboPooledDataSource 解决问题,对应教程上的11.2.6案例:

package chapter11;

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

import javax.sql.DataSource;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import com.mchange.v2.c3p0.ComboPooledDataSource;


public class myResultSetHandler {
	public static void main(String[] args) throws SQLException {
		//获取数据源
		DataSource ds = new ComboPooledDataSource();
		QueryRunner queryRunner = new QueryRunner(ds);
				
		//testBeanHandler();
		
		//------------------------------查询语句------------------------------------
	
		
         /*
        //ArrayListHandler:将查询的结果的每一行放到一个数组中,然后再将数组放到集合中;
        String sql = "SELECT * FROM users;";
        List<Object[]> query = queryRunner.query(sql, new ArrayListHandler());
        for (Object[] obj : query) {
            for (Object o : obj) {
                System.out.print(o + " ");
            }
            System.out.println();
        } */

		/*
        //BeanHandler:将查询的结果的第一行封装到一份javabean对象中;
        String sql = "SELECT * FROM users;";
        user query = queryRunner.query(sql, new BeanHandler<user>(user.class));
        System.out.println(query);

        //BeanListHandler:将查询的结果的每一行封装到一个javabean对象中,然后再将这些对象存入list中;
        System.out.println("///");
        sql = "SELECT * FROM users";
        List<user> list = queryRunner.query(sql, new BeanListHandler<user>(user.class));
        for(user users:list) {
            System.out.println(users.getName());
        } */

        
        //ColumnListHandler:查询指定的列,将查询结果放到一个List中
		System.out.println("//ColumnListHandler:查询指定的列,将查询结果放到一个List中//");
        String sql = "SELECT * FROM users;";
        List<Object> list = queryRunner.query(sql, new ColumnListHandler<Object>("name"));
        for(Object o:list) {
            System.out.println(o);
        }

        //ScalarHandler:将查询的结果的第一行的某一列放到一个对象中;精确定位到某个值;
        System.out.println("//ScalarHandler:将查询的结果的第一行的某一列放到一个对象中;精确定位到某个值//");
        sql = "SELECT COUNT(*) FROM users;";
        Long query = queryRunner.query(sql, new ScalarHandler<Long>());
        System.out.println(query);

        //MapHandler:将查询的结果的第一行存入到一个map中,键为列名,值为各列值;
        System.out.println("//MapHandler 将查询的结果的第一行存入到一个map中,键为列名,值为各列值//");
        sql = "SELECT * FROM users;";
        Map<String, Object> queryMapHandler = queryRunner.query(sql, new MapHandler());
        for (String key : queryMapHandler.keySet()) {
            System.out.println(key + ":" + queryMapHandler.get(key));
        }

        //MapListHandler:将查询的结果的每一行存入到一个map中,键为列名,值为各列值;然后再将map存入list中;
        System.out.println("//MapListHandler:将查询的结果的每一行存入到一个map中,键为列名,值为各列值;然后再将map存入list中//");
        sql = "SELECT * FROM users;";
        List<Map<String, Object>> queryMapListHandler = queryRunner.query(sql, new MapListHandler());
        for (Map<String, Object> map : queryMapListHandler) {
            for(String key:map.keySet()) {
                System.out.print(key+":"+map.get(key)+" ");
            }
            System.out.println();
        }
    
		//ArrayHandler:将查询的结果的第一行放到一个数组中
	    System.out.println("//ArrayHandler:将查询的结果的第一行放到一个数组中//");
		sql = "SELECT * FROM users;";
		Object[] queryArrayHandler = queryRunner.query(sql, new ArrayHandler());
		 for (Object o : queryArrayHandler) {
			 System.out.println(o);
		 }
		 
		 
		//------------------------------更新语句------------------------------------
	       /* sql = "SELECT * FROM users WHERE id = ?";
	        Map<String, Object> query = queryRunner.query(sql, new MapHandler(),1);
	        for(String key:query.keySet()) {
	            System.out.println(key+":"+query.get(key));
	        }

	        String sql = "DELETE FROM type WHERE id in(?,?)";
	        int update = queryRunner.update(sql,6,7);
	        System.out.println(update);

	        String sql = "UPDATE type SET name = '生日系列' WHERE id = ?";
	        int update = queryRunner.update(sql,8);
	        System.out.println(update);

	        String sql = "INSERT INTO type (name) values(?)";
	        int update = queryRunner.update(sql,"111");
	        System.out.println(update);
	        
	        */
		
	}  
      
  }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值