网站首页 > 资源文章 正文
Apache—DBUtils简介
commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
1、DbUtils类
DbUtils :提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的。主要方法如下:
public static void close(…) throws java.sql.SQLException: DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭Connection、Statement和ResultSet。
public static void closeQuietly(…): 这一类方法不仅能在Connection、Statement和ResultSet为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception。
public static void commitAndClose(Connection conn)throws SQLException 用来提交连接的事务,然后关闭连接
public static void commitAndCloseQuietly(Connection conn): 用来提交连接的事务,然后关闭连接,并且在关闭连接时不抛出SQL异常。
public static void rollback(Connection conn)throws SQLException允许conn为null,因为方法内部做了判断
public static void rollbackAndClose(Connection conn)throws SQLException
rollbackAndCloseQuietly(Connection)
public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。/2QueryRunner类
该类封装了SQL的执行,是线程安全的。
(1)可以实现增、删、改、查、批处理、
(2)考虑了事务处理需要共用Connection。
(3)该类最主要的就是简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
QueryRunner类提供了两个构造方法:
(1)QueryRunner():默认的构造方法
(2)QueryRunner(DataSource ds):需要一个 javax.sql.DataSource 来作参数的构造方法。
使用QueryRunner类实现更新(增、删、改、批处理)
(1)更新
public int update(Connection conn, String sql, Object... params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
public int update(Connection conn, String sql) throws SQLException:用来执行一个不需要置换参数的更新操作。
(2)插入
public <T> T insert(Connection conn,String sql,ResultSetHandler<T> rsh)throws SQLException:其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
public <T> T insert(Connection conn,String sql,ResultSetHandler<T> rsh, Object... params) throws SQLException:只支持INSERT
public <T> T insert(String sql,ResultSetHandler<T> rsh)throws SQLException:只支持INSERT
public <T> T insert(String sql,ResultSetHandler<T> rsh,Object... params)throws SQLException:只支持INSERT
(3)批处理
public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
public int[] batch(String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
public <T> T insertBatch(Connection conn,String sql,ResultSetHandler<T> rsh,Object[][] params)throws SQLException:只支持INSERT
public <T> T insertBatch(String sql,ResultSetHandler<T> rsh,Object[][] params)throws SQLException:只支持INSERT
(4)是否需要传递Connection?
A:不需要传递Connection对象:
前提是不考虑事务而且QueryRunner对象创建时指定数据源,这样在QueryRunner的所有增删改查方法中都会从数据源中自己获取连接
B:必须传递Connection对象
如果有事务,必须传递Connection对象,因为同一个事务的多条语句必须在一个Connection连接中完成
public static void main(String[] args) throws Exception{
//1、通过数据库连接池来获取连接
DataSource ds = new ComboPooledDataSource("mypool");
//2、传sql,并执行,并接收结果
String sql = "insert into t_goods(pname,price,description)values(?,?,?)";
QueryRunner qr = new QueryRunner(ds);
int len = qr.update(sql, "电源",78,"充电必备");//自己到数据库连接池中拿连接
System.out.println(len>0?"添加成功":"添加失败");
}
public static void main(String[] args)throws Exception{
//1、通过数据库连接池来获取连接
DataSource ds = new ComboPooledDataSource("mypool");
QueryRunner qr = new QueryRunner();
//从web页面传过来,有这样的数据
int uid = 1;
int[] pids = {5,6,7};
int[] amount = {1,1,1};
double[] price = {560,58,68};
String sql1 = "insert into t_order(ordertime,sumprice,uid)values(now(),?,?)";
String sql2 = "insert into t_detail(oid,pid,amount)values(?,?,?)";
//2、获取连接
Connection conn = null;
try {
conn = ds.getConnection();
conn.setAutoCommit(false);//手动提交事务
double sumprice = 0;
for(int i=0; i<amount.length; i++){
sumprice += amount[i] * price[i];
}
//返回的是自增的键值
Object object = qr.insert(conn, sql1, new ScalarHandler(), sumprice,uid);
Object[][] params = new Object[pids.length][3];
for(int i=0;i<params.length;i++){
for(int j=0; j<params[i].length; j++){
params[i][0] = object;//订单编号
params[i][1] = pids[i];//产品编号
params[i][2] = amount[i];//每一件产品的数量
}
}
qr.insertBatch(conn, sql2, new ScalarHandler(), params);//如果没有自增的键值,那么返回值是null
//提交事务
conn.commit();
} catch (Exception e) {
//回滚事务
if(conn!=null){
conn.rollback();
}
} finally{
if(conn!=null){
//在关闭之前,要设置conn的事务方式为自动提交
conn.setAutoCommit(true);
//关闭连接
DbUtils.closeQuietly(conn);
}
}
}
使用QueryRunner类实现查询
public Object query(Connection conn, String sql, ResultSetHandler rsh,Object... params) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
public Object query(String sql, ResultSetHandler rsh, Object... params) throws SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源(DataSource) 或使用的setDataSource 方法中重新获得 Connection。
public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 执行一个不需要置换参数的查询操作。
public Object query( String sql, ResultSetHandler rsh) throws SQLException : 执行一个不需要置换参数的查询操作。
ResultSetHandler接口
该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet rs)
该方法的返回值将作为QueryRunner类的query()方法的返回值。
@Test
public void testResultSetHandler() {
// 1.创建QueryRunner的实例
QueryRunner qr = new QueryRunner();
Connection conn = null;
try {
// 2.获取连接
conn = JDBCTools.getConnection();
class MyResultSetHandler implements ResultSetHandler{
@Override
public Object handle(ResultSet rs) throws SQLException {
Student stu = new Student();
if (rs.next()) {
stu.setId(rs.getInt(1));
stu.setSname(rs.getString(2));
stu.setSex(rs.getString(3));
stu.setMajor(rs.getString(4));
stu.setClasses(rs.getString(5));
}
return stu;
}
}
String sql = "select sno,sname,sex,major,classes from t_stu where sno =?";
// 3、使用query方法
// QueryRunner 的 query 方法的返回值取决于其 ResultSetHandler 参数的handle 方法的返回值
Object obj = qr.query(conn, sql, new MyResultSetHandler(),1);
System.out.println(obj);
} catch (SQLException e) {
e.printStackTrace();
} finally {
JDBCTools.free(null, null, conn);
}
}
ArrayHandler:把结果集中的第一行数据转成对象数组。
ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
ColumnListHandler:将结果集中某一列的数据存放到List中。
KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
BeanHandler实现类
/*
* BeanHandler: 把结果集的第一条记录转为创建 BeanHandler 对象时传入的 Class参数对应的对象.
* 当JavaBean的属性名与字段名不一致时,可以通过指定别名告知属性名
*/
public static void main(String[] args) throws SQLException {
//1、连接池
DataSource ds = new ComboPooledDataSource("mypool");
//2、直接使用QueryRunner
QueryRunner qr = new QueryRunner(ds);
String sql = "select pid as id,pname,price,description from t_goods where pid =?";
Goods goods = qr.query(sql, new BeanHandler<Goods>(Goods.class), 1);
System.out.println(goods);
}
BeanListHandler实现类
/*
* BeanListHandler: 把结果集转为一个 List, 该 List 不为 null, 但可能为空集合(size() 方法返回 0) 若
* SQL 语句的确能够查询到记录, List 中存放创建 BeanListHandler 传入的 Class对象对应的对象.
*/
public static void main(String[] args) throws SQLException {
//1、连接池
DataSource ds = new ComboPooledDataSource("mypool");
//2、直接使用QueryRunner
QueryRunner qr = new QueryRunner(ds);
String sql = "select pid as id,pname,price,description from t_goods";
List<Goods> query = qr.query(sql, new BeanListHandler<Goods>(Goods.class));
for (Goods goods : query) {
System.out.println(goods);
}
}
MapHandler实现类
public static void main(String[] args) throws SQLException {
// 1、连接池
DataSource ds = new ComboPooledDataSource("mypool");
// 2、直接使用QueryRunner
QueryRunner qr = new QueryRunner(ds);
String sql = "select did,count(*) from employee where did = 1";
Map<String, Object> map = qr.query(sql, new MapHandler());
Set<Entry<String, Object>> entrySet = map.entrySet();
for (Entry<String, Object> entry : entrySet) {
// System.out.println(entry.getKey() +"-->" + entry.getValue());
if ("did".equals(entry.getKey())) {
System.out.println("部门编号:" + entry.getValue());
} else {
System.out.println("人数:" + entry.getValue());
}
}
}
MapListHandler实现类
public static void main(String[] args) throws SQLException {
//1、连接池
DataSource ds = new ComboPooledDataSource("mypool");
//2、直接使用QueryRunner
QueryRunner qr = new QueryRunner(ds);
String sql = "select did,count(*) from employee group by did";
/*
* did count(*)
* 1 7
* 2 3
* 3 1
*
* List:
* map:
* key(did) value(1)
* key(count(*) value(7)
* 第二行
* map:
* key(did) value(2)
* key(count(*) value(3)
* 第三行
* map:
* key(did) value(3)
* key(count(*) value(1)
*
*/
List<Map<String, Object>> query = qr.query(sql, new MapListHandler());
for (Map<String, Object> map : query) {
Set<Entry<String, Object>> entrySet = map.entrySet();
for (Entry<String, Object> entry : entrySet) {
//System.out.println(entry.getKey() +"-->" + entry.getValue());
if("did".equals(entry.getKey())){
System.out.println("部门编号:" + entry.getValue());
}else{
System.out.println("人数:" + entry.getValue());
}
}
}
}
ScalarHandler实现类
/*
* ScalarHandler: 把结果集转为一个数值(可以是任意基本数据类型和字符串, Date 等)返回
* ScalarHandler()只取第一行第一列
* ScalarHandler(int columnIndex):取第一行的第columnIndex列
* ScalarHandler(String columnName):取第一行的列名为columnName列的值
*/
@Test
public static void main(String[] args) throws SQLException {
//1、连接池
DataSource ds = new ComboPooledDataSource("mypool");
//2、直接使用QueryRunner
QueryRunner qr = new QueryRunner(ds);
// String sql = "select count(*) from t_goods";
String sql = "select max(price) from t_goods";
Object query = qr.query(sql, new ScalarHandler());
System.out.println(query);
}
2、JDBC修改成DbUtils版
package com.atguigu.utils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import org.apache.commons.dbutils.DbUtils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class DBUtilsTool {
//创建数据源,用的是c3p0-config.xml文件中<default-config>
private static ComboPooledDataSource dataSource = new ComboPooledDataSource();
//获取数据源对象
public static ComboPooledDataSource getDataSource() {
return dataSource;
}
//获取连接
public static Connection getConnection() throws SQLException{
return dataSource.getConnection();
}
public static void closeQuietly(Connection conn){
DbUtils.closeQuietly(conn);
}
public static void closeQuietly(Statement st){
DbUtils.closeQuietly(st);
}
public static void closeQuietly(ResultSet rs){
DbUtils.closeQuietly(rs);
}
}
相关阅读:
- 上一篇: 半导体FAB厂 PIE 入门技术知识解读
- 下一篇: 为什么我找不到快捷键驱动程序(ATKACPI)
猜你喜欢
- 2024-11-03 Go 每日一库之 sqlc:根据 sql 生成代码
- 2024-11-03 「干货」货代专业词汇整理(一)(货代专业术语大全)
- 2024-11-03 Rust 学习笔记-15 模块化(rust官方社区模组)
- 2024-11-03 使用POI进行写操作(poi写数据)
- 2024-11-03 「整理」390种外贸单证名称中英文互译大全
- 2024-11-03 系动词come和go的用法(系动词come和go的用法与例举)
- 2024-11-03 JavaSE基础-包(javase入门)
- 2024-11-03 100个常用生活物品的英文名称,值得收藏!
- 2024-11-03 The Gifts (礼物)4人英文话剧剧本
- 2024-11-03 为什么我找不到快捷键驱动程序(ATKACPI)
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- 电脑显示器花屏 (79)
- 403 forbidden (65)
- linux怎么查看系统版本 (54)
- 补码运算 (63)
- 缓存服务器 (61)
- 定时重启 (59)
- plsql developer (73)
- 对话框打开时命令无法执行 (61)
- excel数据透视表 (72)
- oracle认证 (56)
- 网页不能复制 (84)
- photoshop外挂滤镜 (58)
- 网页无法复制粘贴 (55)
- vmware workstation 7 1 3 (78)
- jdk 64位下载 (65)
- phpstudy 2013 (66)
- 卡通形象生成 (55)
- psd模板免费下载 (67)
- shift (58)
- localhost打不开 (58)
- 检测代理服务器设置 (55)
- frequency (66)
- indesign教程 (55)
- 运行命令大全 (61)
- ping exe (64)
本文暂时没有评论,来添加一个吧(●'◡'●)