第11章 数据库连接池与DBUtils工具
参考博文:详解Java数据库连接池类加载器与 Class.getResourceAsStream 问题解决1 数据库连接池1.1数据看看连接池那点事由于每操作一次数据库,都会执行一次创建和断开Connection对象的操作,频繁的操作Connection对象十分影响数据库的访问效率,并且增加了代码量,所以在实际开发中,开发人员通常会使用数据库连接池来解决这些问题。数据库连接池负责分配、管理和释放数
参考博文:
类加载器与 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.jar和commons-pool2.jar两个JAR包:
commons-dbcp2.jar包是DBCP数据库连接池的实现包,包含所有操作数据库连接信息和数据库连接池初始化信息的方法,并实现了DataSource接口的getConnection()方法。
commons-pool2.jar包是commons-dbcp2.jar包的依赖包,为commons-dbcp2.jar包中的方法提供了支持。
commons-dbcp2.jar包含两个核心类,分别是BasicDataSourceFactory和BasicDataSource,它们都包含获取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.jar、commons-dbcp2-2.7.0.jar、commons-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数据源接口,支持JDBC2和JDBC3的标准规范,易于扩展并且性能优越,著名的开源框架Hibernate和 Spring都支持该数据库连接池。在使用C3P0数据库连接池开发时,需要了解C3P0中DataSource接口的实现类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()构造方法创建数据源对象,需要手动给数据源对象设置属性值,然后获取数据库连接对象。
导入JAR包c3p0-0.9.2.1.jar和mchange-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工具
为了更加简单地使用JDBC,Apache组织提供了一个DBUtils工具,它是操作数据库的一个组件,实现了对JDBC的简单封装,可以在不影响数据库访问性能的情况下简化JDBC的编码工作量。DBUtils工具要有三个作用。
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提供了几种常见的实现类。
ResultSetHandler接口还提供了一个单独的方法handle (java.sql.ResultSet rs),如果上述实现类没有提供想要的功能,可以自定义一个实现ResultSetHandler接口的类,然后通过重写handle()方法,实现结果集的处理。
BeanHandler和BeanListHandler
类名称 | 相同点 | 不同点 |
BeanHandler | 都要先将结果集封装进JavaBean | 封装单条数据,把结果集的第一条数据的字段放入一个JavaBean中 |
BeanListHandler | 封装多条数据,把每条数据的字段值各放入一个JavaBean中,再把所有JavaBean都放入List集合中 |
ColumnListHandler和ScalarHandler
ColumnListHandler和ScalarHandler类可以对指定的列数据进行封装,在封装时,查询指定列数据,然后将获得的列数据封装到容器中。ColumnListHandler和ScalarHandler的对比如下表所示。
类名称 | 相同点 | 不同点 |
ColumnListHandler | 都是对指定列的查询结果集进行封装 | 封装指定列的所有数据,将他们放入一个List集合中 |
ScalarHandler | 封装单条列数据,也可以封装类似count、avg、max、min、sum等聚合函数的执行结果 |
: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)