JDBC学习笔记(9)——DBUtils的使用
使用DBUtils提供的功能需要使用commons-dbutils-1.6.jar这个JAR包,在Apache官网可以下载到
使用DBUtils进行更新操
测试QueryRunner类的update方法 ,该方法可用于insert,update,delete操作
具体代码实现
@Test
public void testQuertRunnerUpdate() {
// 1.创建QueryRunner的实现类
String sql = "delete from customers" + " where id in (?,?)";
Connection connection = null;
try {
connection = JDBCTools.getConnection();
queryRunner.update(connection, sql, 3, 4); } catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
我们可以查看一下update方法的源码,可以看到是调用的是重载形式的update:
conn:数据库连接
sql:SQL语句
params:填充占位符的参数
public int update(Connection conn, String sql, Object... params) throws SQLException {
return update(conn, false, sql, params);
}
看具体实现代码:
1 private int update(Connection conn, boolean closeConn, String sql, Object... params) throws SQLException {
2 if (conn == null) {
3 throw new SQLException("Null connection");
4 }
5
6 if (sql == null) {
7 if (closeConn) {
8 close(conn);
9 }
10 throw new SQLException("Null SQL statement");
11 }
12 //封装使用的是PreparedStatement
13 PreparedStatement stmt = null;
14 int rows = 0;
15
16 try {
17 stmt = this.prepareStatement(conn, sql);
//填充占位符的操作
18 this.fillStatement(stmt, params);
//执行更新操作
19 rows = stmt.executeUpdate();
20
21 } catch (SQLException e) {
22 this.rethrow(e, sql, params);
23
24 } finally {
25 close(stmt);
26 if (closeConn) {
27 close(conn);
28 }
29 }
30
31 return rows;
32 }
可以看到QueryRunner中封装的都是我们所熟悉的基本操作,测试我们的testQuertRunnerUpdate方法,可以发现对应id为3,4的记录已经被删除
测试QueryRunner的查询方法query
// 因为是线程安全的,所以queryRunner可以放到这个位置
QueryRunner queryRunner = new QueryRunner(); class MyResultSetHandler implements ResultSetHandler { @Override
public Object handle(ResultSet resultSet) throws SQLException {
List<Customer> customers = new ArrayList<Customer>();
while (resultSet.next()) {
int id = resultSet.getInt(1);
String name = resultSet.getString(2);
String email = resultSet.getString(3);
Date birth = resultSet.getDate(4);
Customer customer = new Customer(id, name, email, birth);
customers.add(customer);
}
return customers;
} } @Test
public void testQuery() {
QueryRunner queryRunner = new QueryRunner();
Connection connection = null;
try {
connection = JDBCTools.getConnection();
String sql = "select id,name,email,birth" + " from customers";
Object obj = queryRunner.query(connection, sql,
new MyResultSetHandler());
System.out.println(obj);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
运行方法可以看到我们要查询的结果:
[Customer [id=1, name=ATGUIGU, email=simale@163.com, birth=2016-05-08], Customer [id=2, name=ABCDE, email=abcd@guigu.com, birth=2016-05-08], Customer [id=5, name=dsv, email=474405914@qq.com, birth=2016-05-10]]
我们查看一下query方法的源码
private <T> T query(Connection conn, boolean closeConn, String sql, ResultSetHandler<T> rsh, Object... params)
throws SQLException {
if (conn == null) {
throw new SQLException("Null connection");
} if (sql == null) {
if (closeConn) {
close(conn);
}
throw new SQLException("Null SQL statement");
} if (rsh == null) {
if (closeConn) {
close(conn);
}
throw new SQLException("Null ResultSetHandler");
} PreparedStatement stmt = null;
ResultSet rs = null;
T result = null; try {
stmt = this.prepareStatement(conn, sql);
this.fillStatement(stmt, params);
rs = this.wrap(stmt.executeQuery());
result = rsh.handle(rs); } catch (SQLException e) {
this.rethrow(e, sql, params); } finally {
try {
close(rs);
} finally {
close(stmt);
if (closeConn) {
close(conn);
}
}
} return result;
}
其中最关键的是这四个语句:
stmt = this.prepareStatement(conn, sql);
this.fillStatement(stmt, params);
rs = this.wrap(stmt.executeQuery());
result = rsh.handle(rs);
测试DBUtils工具类 QueryRunner:
* query(Connection conn,String sql,ResultSetHandler rsh){
* 这三个步骤就是为了得到结果集
* stmt = this.prepareStatement(conn, sql);
* this.fillStatement(stmt, params);
* rs = this.wrap(stmt.executeQuery());
* 调用传入的ResultSetHandler对象的handle方法,并且把前面得到的ResultSet对象作为参数传入
* result =rsh.handle(rs);
* 把result作为结果返回
* return result
* }
测试BeanHandler的用法
BeanHandler:把结果集的第一条记录转为创建BeanHandler 对象时传入的Class参数对应的对象。
具体测试代码:
public void testBeanHandler() {
Connection connection = null;
try {
connection = JDBCTools.getConnection();
String sql = "select id,name,email,birth"
+ " from customers where id=?";
Customer customer = queryRunner.query(connection, sql,
new BeanHandler(Customer.class), 5);
System.out.println(customer);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
查看源码可以看到query函数中用到的handler函数实现的功能是这样的
@Override
public T handle(ResultSet rs) throws SQLException {
return rs.next() ? this.convert.toBean(rs, this.type) : null;
}
实现的功能是把结果集的第一条记录转为创建BeanHandler 对象时传入的Class参数对应的对象。
其中的toBean方法的实现方式:(多看源码吧,有点乱了)
public <T> T toBean(ResultSet rs, Class<T> type) throws SQLException { PropertyDescriptor[] props = this.propertyDescriptors(type); ResultSetMetaData rsmd = rs.getMetaData();
int[] columnToProperty = this.mapColumnsToProperties(rsmd, props); return this.createBean(rs, type, props, columnToProperty);
}
测试BeanListHandler的用法
和前面那个差不多,只不过将查询的结果放到了一个List容器中了
@Test
public void testBeanListHandler() {
Connection connection = null;
try {
connection = JDBCTools.getConnection();
String sql = "select id,name,email,birth" + " from customers";
List<Customer> customers = queryRunner.query(connection, sql,
new BeanListHandler(Customer.class));
System.out.println(customers);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
运行结果:
[Customer [id=1, name=ATGUIGU, email=simale@163.com, birth=2016-05-08], Customer [id=2, name=ABCDE, email=abcd@guigu.com, birth=2016-05-08], Customer [id=5, name=dsv, email=474405914@qq.com, birth=2016-05-10]]
测试MapHandler的用法
MapHandler:返回SQL对应的第一条记录对应的Map对象 键:SQL查询的列名(不是列别名) 值:列的值
@Test
public void testMapHandler() {
Connection connection = null;
try {
connection = JDBCTools.getConnection();
String sql = "select id,name,email,birth" + " from customers";
Map<String, Object> result = queryRunner.query(connection, sql,
new MapHandler());
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
运行结果:
{id=1, name=ATGUIGU, email=simale@163.com, birth=2016-05-08}
测试MapListHandler的用法
MapListHandler:将结果集转为一个Map的List, Map对应查询的一条记录的Map对象
键:SQL查询的列名(不是列别名)
值:列的值 而MapListHandler:返回的多条记录对应的Map集合
@Test
public void testMapListHandler() {
Connection connection = null;
try {
connection = JDBCTools.getConnection();
String sql = "select id,name,email,birth" + " from customers";
List<Map<String, Object>> result = queryRunner.query(connection,
sql, new MapListHandler());
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
运行结果:
[{id=1, name=ATGUIGU, email=simale@163.com, birth=2016-05-08}, {id=2, name=ABCDE, email=abcd@guigu.com, birth=2016-05-08}, {id=5, name=dsv, email=474405914@qq.com, birth=2016-05-10}]
测试ScalarHandler的用法
ScalarHandle:把结果集转为一个数值(可以是任意基本数据类型和字符串,Date等)返回
@Test
public void testScalarHandler() {
Connection connection = null;
try {
connection = JDBCTools.getConnection();
String sql = "select count(id) from customers";
Object result = queryRunner.query(connection, sql,
new ScalarHandler());
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCTools.release(null, null, connection);
}
}
运行结果:3
至此为止我们学习了JDBC中常用的一些知识点,下面我们就使用DBUtils编写通用的DAO(DAO其实就是封装了操作数据库数据的一些方法的接口)
使用DButils编写通用的DAO
第一步:先写一个访问数据的DAO接口
package com.atguigu.jdbc; import java.sql.Connection;
import java.util.List; /**
* 访问数据的DAO接口
* 里面定义好访问数据表的各种方法
* @author Administrator
* @param T:DAO处理的实体类的类型
*/
public interface DAO {
/**
* 批量处理的方法
* @param connection
* @param sql
* @param args:填充占位符的Object[]类型的可变参数
*/
void batch(Connection connection,
String sql,Object[] ...args);
/**
* 返回一个具体的一个值,例如总人数,平均工资
* 某一个认得email
* @param connection
* @param sql
* @param args
* @return
*/
<E> E getForValue(Connection connection,
String sql, Object ...args); /**
* 返回T的一个集合
* @param <T>
* @param connection
* @param sql
* @param args
* @return
*/
<T> List<T> getForList(Connection connection,
String sql,Object ...args);
/**
* 返回一个T的对象
* @param <T>
* @param connection
* @param sql
* @param args
* @return
* @throws Exception
*/
<T> T get(Connection connection,String sql,Object ...args) throws Exception;
/**
*
* @param connection:数据库连接
* @param sql:SQL语句
* @param args:填充占位符的可变参数
*/
void update(Connection connection,String sql,Object ...args);
}
第二步:定义实现该接口的实例类JdbcDAOImpl
package com.atguigu.jdbc; import java.sql.Connection;
import java.util.List; import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler; /**
* 使用QueryRunner提供其具体的实现
* @author Administrator
*
* @param <T>:子类需传入的泛型类型
*/
public class JdbcDAOImpl<T> implements DAO {
private QueryRunner queryRunner=null;
private Class<T> type;
public JdbcDAOImpl() {
queryRunner=new QueryRunner();
type= (Class<T>) ReflectionUtils.getGenericSuperClass(getClass(),0);
}
@Override
public void batch(Connection connection, String sql, Object[]... args) {
} @Override
public <E> E getForValue(Connection connection, String sql, Object... args) { return null;
} @Override
public List<T> getForList(Connection connection, String sql,
Object... args) { return null;
} @Override
public T get(Connection connection, String sql, Object... args) throws Exception { return queryRunner.query(connection, sql,
new BeanHandler<>(type),args);
} @Override
public void update(Connection connection, String sql, Object... args) {
} }
第三步:定义一个具体操作的类继承自JdbcDAOImpl
package com.atguigu.jdbc; public class CustomerDAO extends JdbcDAOImpl<Customer>{ }
第四步:我们测试一下我们已经实现的get方法,其他的方法实现过程类似
package com.atguigu.jdbc; import static org.junit.Assert.*; import java.sql.Connection; import org.junit.Test; public class CustomerDaoTest {
CustomerDAO customerDAO=new CustomerDAO(); @Test
public void testBatch() {
fail("Not yet implemented");
} @Test
public void testGetForValue() {
fail("Not yet implemented");
} @Test
public void testGetForList() {
fail("Not yet implemented");
} @Test
public void testGet() {
Connection connection=null;
try {
connection=JDBCTools.getConnection();
String sql = "select id,name,email,birth"
+ " from customers where id=?";
Customer customer=customerDAO.get(connection, sql, 5);
System.out.println(customer);
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCTools.release(null, null, connection);
}
} @Test
public void testUpdate() {
fail("Not yet implemented");
} }
运行一下:
Customer [id=5, name=dsv, email=474405914@qq.com, birth=2016-05-10]
可以通过我们的get方法得到我们想要的数据信息
个人感悟:把简单的事情做到极致,打扎实的基础,写优秀的代码
本文为博主原创文章,转载请注明出处:http://www.cnblogs.com/ysw-go/
1、本博客的原创原创文章,都是本人平时学习所做的笔记,如有错误,欢迎指正。
2、如有侵犯您的知识产权和版权问题,请通知本人,本人会即时做出处理文章。
3、本博客的目的是知识交流所用,转载自其它博客或网站,作为自己的参考资料的,感谢这些文章的原创人员
JDBC学习笔记(9)——DBUtils的使用的更多相关文章
- 【转】JDBC学习笔记(9)——DBUtils的使用
转自:http://www.cnblogs.com/ysw-go/ 使用DBUtils提供的功能需要使用commons-dbutils-1.6.jar这个JAR包,在Apache官网可以下载到 使用D ...
- JDBC 学习笔记(十一)—— JDBC 的事务支持
1. 事务 在关系型数据库中,有一个很重要的概念,叫做事务(Transaction).它具有 ACID 四个特性: A(Atomicity):原子性,一个事务是一个不可分割的工作单位,事务中包括的诸操 ...
- JDBC 学习笔记(十)—— 使用 JDBC 搭建一个简易的 ORM 框架
1. 数据映射 当我们获取到 ResultSet 之后,显然这个不是我们想要的数据结构. 数据库中的每一个表,在 Java 代码中,一定会有一个类与之对应,例如: package com.gerrar ...
- JDBC 学习笔记(六)—— PreparedStatement
1. 引入 PreparedStatement PreparedStatement 通过 Connection.createPreparedStatement(String sql) 方法创建,主要用 ...
- JDBC学习笔记二
JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...
- JDBC学习笔记一
JDBC学习笔记一 JDBC全称 Java Database Connectivity,即数据库连接,它是一种可以执行SQL语句的Java API. ODBC全称 Open Database Conn ...
- JDBC学习笔记(2)——Statement和ResultSet
Statement执行更新操作 Statement:Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句.Statement ...
- JDBC学习笔记(1)——JDBC概述
JDBC JDBC API是一个Java API,可以访问任何类型表列数据,特别是存储在关系数据库中的数据.JDBC代表Java数据库连接. JDBC库中所包含的API任务通常与数据库使用: 连接到数 ...
- 【转】JDBC学习笔记(2)——Statement和ResultSet
转自:http://www.cnblogs.com/ysw-go/ Statement执行更新操作 Statement:Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数 ...
随机推荐
- The type xxx cannot be resolved. It is indirectly referenced from required .class files
项目A中引入一个jar包B,在项目A中调用项目B,出现如下错误提示: 大致意思是:这上面所需的包是间接引用的,即A项目调用B项目,B项目又引用了另外一个包C,而这个包现在不在你的A项目的引用中. ...
- HDFS 小文件处理——应用程序实现
在真实环境中,处理日志的时候,会有很多小的碎文件,但是文件总量又是很大.普通的应用程序用来处理已经很麻烦了,或者说处理不了,这个时候需要对小文件进行一些特殊的处理——合并. 在这通过编写java应用程 ...
- [HDOJ2473]Junk-Mail Filter(并查集,删除操作,马甲)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2473 给两个操作:M X Y:将X和Y看成一类. S X:将X单独划归成一类. 最后问的是有多少类. ...
- ios程序开发杂记
ios程序开发杂记 一.程序构建 与一般的程序构建无太大区别,都是源文件编译链接这一套,通常是在mac上做交叉编译,也就是利用xcode里带的ios编译工具集去生成arm架构的ios程序(或是x86的 ...
- Android系统服务-WindowManager
WindowManager是Android中一个重要的服务 (Service ).WindowManager Service 是全局的,是唯一的.它将用户的操作,翻译成为指令,发送给呈现在界面上的 ...
- EXT 数据按F12,F11 显示问题
最近做关于EXT的项目,因为是刚开始接触EXT,对什么都不熟悉,所以把其他人写好的浏览页代码考过了来,换成自己需要的. 一切都做好了,然后数据不出来,就调试看,后台也出现数据了,然后就按F12调试前台 ...
- asp.net实现文件解压和压缩
C#解压RAR压缩文件(--转载--测试通过) using System; using System.Collections.Generic; using System.Text; using Sys ...
- 深入理解移动web开发之PPI,Pixel,DevicePixelRatio(转)
如果你是一个开始接触移动Web开发的前端工程师,那么你或许也遇到了和我曾经遇到的过问题:有太多新的概念需要掌握,太多相似的概念需要区分.没关系,我将用两篇文章的篇幅来解决这些问题.上篇文章关于解释和区 ...
- zoj 1119 /poj 1523 SPF
题目描述:考虑图8.9中的两个网络,假定网络中的数据只在有线路直接连接的2个结点之间以点对点的方式传输.一个结点出现故障,比如图(a)所示的网络中结点3出现故障,将会阻止其他某些结点之间的通信.结点1 ...
- jvm内部现成运行
hi,all 最近抽时间把JVM运行过程中产生的一些线程进行了整理,主要是围绕着我们系统jstack生成的文件为参照依据. 前段时间因为系统代码问题,造成性能瓶颈,于是就dump了一份stack出来 ...