【DBUtils工具概述】
为了简化JDBC开发,使用apache commons 组件一个成员:DBUtils。
DBUtils 是java编程中的数据库操作实用工具,小巧简单实用。
Dbutils三个核心功能介绍:
(1) QueryRunner 中提供对sql语句操作的API
a. 方法update() 实现对数据库的 insert 、delete、update
b. 方法query() 实现对数据库的查询 select 返回值是T泛型
(2) ResultSetHandler接口 用于定义select操作后,怎样封装结果集
a. 接口实现类 ArrayHandler -- 将结果集的第一行存储到对象数组中 Object[]
b. 接口实现类 ArrayListHandler -- 结果集的每一行都存储在对象数组中,再将这些数组存储在List集合中
c. 接口实现类 BeanHandler -- 将结果集的第一行数据,封装成javaBean对象
d. 接口实现类 BeanListHandler -- 结果集每一行数据,都装成javaBean对象,将这些对象存储List集合中
e. 接口实现类 ColumnListHandler -- 将结果集指定列存储到List<Object>集合中
f. 接口实现类 ScalarHandler -- 查询后结果集中只有1个结果 类型为long
g. 接口实现类 MapHandler -- 将结果集的第1行数据封装到Map集合中去 Map<列名, 列数据>
(3) DbUtils类 是一个工具类,定义了关闭资源与事务处理的方法
【连接池】
用池来管理Connection ,这样就可以重复使用Connection了。可以通过池来获取Connection对象,使用完后再归还给池。java为数据库连接池提供的公共接口:javax.sql.DataSource 。常见的连接池DBCP C3P0。
【DBCP连接池】
作用:自身维护了多个Connection对象
DataSource 接口 它是java与每种数据库连接池 连接的标准规范
BasicDataSource类 它是DataSource接口的实现类
【DBCP连接池常见配置】
必须项 |
driverClassName |
数据库驱动名称 |
url |
数据库的地址 |
|
username |
用户名 |
|
password |
密码 |
|
基本项 |
maxActive |
最大连接数量 |
initialSize |
连接池中初始化多少个Connection连接对象 |
|
扩展项 |
maxWait |
超时等待时间以毫秒为单位 1000等于1秒 |
【1. QueryRunner 方法update】
import java.sql.Connection;
import java.sql.SQLException;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import usst.javacode.JDBCutils.JDBCutils;
/*
* 使用QueryRunner类,实现对数据表的 增insert 删 delete 改 update
* 1.方法 update(Connection con, String sql, Object...params)
* Object...params Object类型 可变参数,SQL语句出现?占位符
* 使用自己定义的工具类 创建数据库连接对象 JDBCutils.getConnection()
*/
public class QueryRunnerDemo1 {
private static Connection con = JDBCutils.getConnection();
public static void main(String[] args) throws SQLException {
//insert();
//update();
delete();
}
// 1. 使用QueryRunner类 向数据库中添加数据
public static void insert() throws SQLException{
// 创建QueryRunner类对象
QueryRunner qr = new QueryRunner();
String sql = "INSERT INTO sort1 (sname,sprice,sdesc) VALUES (?,?,?)";
// 调用qr对象的方法 update 执行SQL语句
Object[] params = {"鼠标",99,"雷蛇"}; // 将三个实际占位符的参数写在数组中
int row = qr.update(con, sql, params);
System.out.println(row);
DbUtils.closeQuietly(con);
}
// 2. 使用QueryRunner类 修改数据库中的数据
public static void update() throws SQLException{
// 创建QueryRunner类对象
QueryRunner qr = new QueryRunner();
String sql = "UPDATE sort1 SET sname = ?,sprice = ?, sdesc = ? WHERE sid = ?";
// 定义Object数组,存储?中的参数
Object[] params = {"记录本",49,"精装",13};
int row = qr.update(con, sql, params);
System.out.println(row);
DbUtils.closeQuietly(con);
}
// 3. 使用QueryRunner类 删除数据库中的数据
public static void delete() throws SQLException{
// 创建QueryRunner类对象
QueryRunner qr = new QueryRunner();
String sql = "DELETE FROM sort1 WHERE sid = ?";
int row = qr.update(con, sql, 12);
System.out.println(row);
DbUtils.closeQuietly(con);
}
}
【javaBean】
javaBean就是一个类,在开发中常用封装数据。具有以下特性:
(1) 需要实现接口:java.io.Serializable,通常实现接口这个步骤省略,不会影响程序
(2) 提供私有字段:private 类型 字段名
(3) 提供getter/setter方法
(4) 提供无参构造方法
【2. QueryRunner方法query()】
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
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 usst.javacode.JDBCutils.JDBCutils;
import usst.javacode.JDBCutils.Sort;
/*
* QueryRunner类数据查询操作:
方法 query(Connection con,String sql,ResultSetHandler r,Object...params)
* ResultSetHandler r 结果集的处理方式 传递ResultSetHandler接口的实现类
* Object...params SQL语句中?号占位符的参数
* 注意:query方法返回的是 T 泛型,具体返回值类型,跟随结果集处理方式变化
*
*/
public class QueryRunnerDemo2 {
private static Connection con = JDBCutils.getConnection();
public static void main(String[] args) throws SQLException {
//arrayHandler();
//arrayListHandler();
//beanHandler();
//beanListHandler();
//columnListHandler();
//scalarHandler();
//mapHandler();
mapListHandler();
}
// 1. 结果集第一种处理方法 ArrayHandler 将结果集的第一行存储到对象数组中 Object[]
public static void arrayHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用query方法执行查询,(传递连接对象,SQL语句,结果集处理方式的实现类)
// 返回对象数组
Object[] result = qr.query(con,sql,new ArrayHandler());
for(Object res:result){
System.out.print(res+"\t"); // 打印sort1数据表中第一行
// 1 家电 3000.0 厂家促销
}
}
// 2. 结果集第二种处理方法 ArrayListHandler 将结果集的每一行,封装到对象数组中Object[] 对象数组存储到List集合
public static void arrayListHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用query方法 , 结果集处理的参数上,传递实现类ArrayListHandler
// 返回值 每一行是一个对象数组,存储到List中
List<Object[]> result = qr.query(con, sql,new ArrayListHandler());
// 集合遍历
for(Object[] objs:result){
// 遍历对象数组
for(Object obj:objs){
System.out.print(obj+"\t"); // 打印sort1表中的所有内容
// 1 家电 3000.0 厂家促销 ......
}
System.out.println();
}
}
// 3. 结果集第三种处理方法,BeanHandler 将结果集的第一行数据 封装成javaBean对象
// 注意: 被封装成数据 到javaBean对象Sort类,必须有空参数的构造方法
public static void beanHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用方法query 传递结果集实现类BeanHandler
// BeanHandler(Class<T> type)
Sort s = qr.query(con, sql, new BeanHandler<Sort>(Sort.class));
System.out.println(s); // 打印sort1数据表中第一行
// Sort [sid=1, sname=家电, sprice=3000.0, sdesc=厂家促销]
}
// 4. 结果集第四种处理方法BeanListHandler 将数据结果集的每一行,封装成javaBean对象 多个javaBean对象封装到List集合中
public static void beanListHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用方法query 传递结果集实现类beanListHandler
// BeanListHandler(Class<T> type)
List<Sort> result = qr.query(con,sql, new BeanListHandler<Sort>(Sort.class));
// 遍历
for(Sort res:result){
System.out.println(res); // 打印sort1表中的所有内容
// Sort [sid=1, sname=家电, sprice=3000.0, sdesc=厂家促销] ......
}
}
// 5. 结果集第五种处理方法 ,ColumnListHandler 将结果集中指定列的数据,存储到List集合 List<Object> 每个类数据类型不同
public static void columnListHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用方法query, 传递结果集实现ColumnListHandler 实现类构造方法中使用字符串的列名
List<Object> result = qr.query(con, sql, new ColumnListHandler<Object>("sname"));
System.out.println(result);
// [家电, 家具, 儿童玩具, 生鲜, 服装, 洗发水, 新能源汽车, 羽绒服, 新能源汽车, 新能源汽车, 鼠标1, 记录本]
for(Object res:result){
System.out.println(res);
// 家电 家具 ......
}
}
// 6. 结果集第六种处理方法,ScalarHandler 用於单数据 查询后只有一个结果
public static void scalarHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT COUNT(*) FROM sort1";
// 调用query方法,传递结果集实现类ScalarHandler
long count = qr.query(con,sql,new ScalarHandler<Long>());
System.out.println(count); // 12
}
// 7. 结果集第七种处理方法,MapHandler,将结果集中的第一行封装到Map集合中 Map<键,值> 键:列名 值:这列的数据
public static void mapHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用query方法,传递结果集实现类MapHandler
// 返回值:Map集合,Map接口实现类,泛型
Map<String,Object> map = qr.query(con, sql,new MapHandler());
// 遍历Map集合
for(String key:map.keySet()){
System.out.println(key+"="+map.get(key));
}
/*
* 打印结果
sid=1
sname=家电
sprice=3000.0
sdesc=厂家促销
*/
}
// 8. 结果集第八种处理方法,MapListHandler 奖结果集的每一行存储到Map集合中,键:列名 值:这列的数据
// Map集合过多,存储到List集合中去
public static void mapListHandler() throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM sort1";
// 调用query方法,传递结果集实现类MapListHandler
// 返回值是List集合,里面存储的是Map集合
List<Map<String,Object>> list = qr.query(con,sql,new MapListHandler());
// 遍历集合List
for(Map<String,Object> map:list){
for(String key:map.keySet()){
System.out.print(key+"="+map.get(key)+"\t");
}
System.out.println();
}
/*
* sid=1 sname=家电 sprice=3000.0 sdesc=厂家促销
sid=2 sname=家具 sprice=8900.0 sdesc=家具价格上调
sid=3 sname=儿童玩具 sprice=300.0 sdesc=销量火爆
... .... ... ...
*/
}
}
【连接池工具类】 -- BasicDataSource
实际开发中“获得连接”和“释放连接”是非常消耗系统资源的两个过程,为了解决此类问题我们采用连接池技术,来共享连接Connection。
import javax.sql.DataSource;
import org.apache.commons.dbcp.BasicDataSource;
/*
* 使用DBCP实现数据库的连接池
* 连接池配置:
* 最基本四项配置 1. 数据库驱动名称:setDriverClassName 2. 数据库地址:setUrl
* 3. 用户名:setUsername 4. 密码:setPassword
* 基本项(扩展) 1. 初始化的连接数量:setInitialSize 2. 最大连接数量:setMaxActive
* 3. 最大空闲数:setMaxIdle 4. 最小空闲数:setMinIdle
*/
public class JDBCutils {
// 创建出BasicDataSource类对象
private static BasicDataSource dataSource = new BasicDataSource();
// 静态代码块,进行配置
static{
// 连接数据库的4个基本信息,通过对象方法setXXX进行设置 (必须进行配置)
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybase1");
dataSource.setUsername("root");
dataSource.setPassword("123");
// 对 dataSource连接池对象 的连接数量进行配置 (可选配置,有默认配置)
dataSource.setInitialSize(10); // 初始化的连接数量
dataSource.setMaxActive(8); // 最大连接数量
dataSource.setMaxIdle(5); // 最大空闲数
dataSource.setMinIdle(1); // 最小空闲数
}
// 定义静态方法,返回BasicDataSource类对象
public static DataSource getDataSource(){
return dataSource;
}
// 定义静态方法,返回Connection对象
public static Connection getConnection(){
return dataSource.getConnection;
}
}
【测试连接池工具类】
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
/*
* 测试写好的工具类:JDBCutils 静态方法getDataSource() 返回值类型是DataSource
QueryRunner 类构造方法,接受DataSource接口的实现类
*/
public class QueryRunnerDemo {
// 定义2个方法,实现数据表的添加 、数据表的查询
// QueryRunner类对象写在成员变量位置
private static QueryRunner qr =new QueryRunner(JDBCutils.getDataSource());
public static void main(String[] args) {
//insert();
select();
}
// 数据表添加数据
public static void insert(){
String sql = "INSERT INTO sort1 (sname,sprice,sdesc) VALUES(?,?,?)";
Object[] params = {"核桃",29.9,"新疆干果"};
try{
int row = qr.update(sql,params); // 无须传递Connection对象
System.out.println(row);
}catch(SQLException ex){
throw new RuntimeException(ex+"数据库添加失败");
}
}
// 数据表查询函数
public static void select(){
String sql = "SELECT * FROM sort1";
try{
List<Object[]> lists = qr.query(sql, new ArrayListHandler());
for(Object[] list:lists){
for(Object l:list){
System.out.print(l+"\t");
}
System.out.println();
}
}catch(SQLException ex){
throw new RuntimeException(ex+"数据库查询失败");
}
/* 打印结果
* 1 家电 3000.0 厂家促销
2 家具 8900.0 家具价格上调
3 儿童玩具 300.0 销量火爆
... ...
*/
}
}
【连接池工具】-- 读取 .properties文件配置数据库
db.properties文件
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybase1
username=root
password=123
DBCPUtils类 获取连接池 和 连接对象的静态方法
import java.io.InputStream;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import java.util.Properties;
import org.apache.commons.dbcp.BasicDataSourceFactory;
public class DBCPUtils {
// 声明DataSource类型成员变量
private static DataSource dataSource;
static {
try {
// 使用类的加载器读取数据库.properties配置文件(在src目录下)
InputStream in = DBCPUtils.class.getClassLoader().getResourceAsStream("db.properties");
// 加载输入流
Properties pros = new Properties();
pros.load(in);
// 使用工具类创建连接池(数据源)
dataSource = BasicDataSourceFactory.createDataSource(pros);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 静态方法获得连接池
public static DataSource getDataSource() {
return dataSource;
}
// 静态方法获得连接
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
【c3p0连接池工具】
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:///mybase1</property>
<property name="user">root</property>
<property name="password">123</property>
<property name="initialPoolSize">5</property>
<property name="maxPoolSize">20</property>
</default-config>
<named-config name="namedConfig">
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">jdbc:mysql:///mybase1</property>
<property name="user">root</property>
<property name="password">123</property>
</named-config>
</c3p0-config>
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class C3P0Utils {
// 使用默认配置 -- 自动读取c3p0-config.xml中的配置信息
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
// 使用命名配置
//private static ComboPooledDataSource dataSource = new ComboPooledDataSource("namedConfig");
// 静态方法获得连接池
public static DataSource getDataSource() {
return dataSource;
}
// 静态方法获得连接
public static Connection getConnection() {
try {
return dataSource.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}