DBUtils学习

来源:互联网 发布:方舟生存进化优化mod 编辑:程序博客网 时间:2024/05/20 12:25


DBUtils对JDBC作了简单的封装。使用起来方便,同时又不会影响性能。

Class QueryRunner

Executes SQL queries with pluggable strategies for handling ResultSets. This class is thread safe.

这个类中间提供了查找和更新的方法。

有以下的四种构造函数:
QueryRunner() 
  Constructor for QueryRunner.
QueryRunner(boolean pmdKnownBroken) 
          Constructor for QueryRunner, allows workaround for Oracle drivers
QueryRunner(DataSource ds) 
          Constructor for QueryRunner, allows workaround for Oracle drivers.
QueryRunner(DataSource ds, boolean pmdKnownBroken) 
          Constructor for QueryRunner, allows workaround for Oracle drivers

这个类提供了如下种类的方法:
1)batch     批量处理 Execute a batch of SQL INSERT, UPDATE, or DELETE queries.
2)query     查询     Executes the given SELECT SQL query
3)update    更新     Execute an SQL INSERT, UPDATE, or DELETE query
4)close 关闭操作


一、测试DBUtils工具中QueryRunner类中的update方法:
package com.lj95801.cla1;import java.lang.reflect.InvocationTargetException;import java.sql.Connection;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.ResultSetHandler;import org.junit.Test;import com.lj95801.utils.JDBCUtils;public class testDBUtils {// 1、创建QueryRunner的实现类QueryRunner queryRunner = new QueryRunner();/* * 1、测试DBUtils中QueryRunner类的update方法 */@Testpublic void testQueryRunnerUpdate() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句String sql = "DELETE FROM customers WHERE ste_id IN(?, ?)";try {queryRunner.update(connection, sql, 7, 10);} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(null, null, null, connection);}}}

二、测试QueryRunner类中的query方法,通过自己写MyHandler类来充分理解Handler方法是怎么工作的:
package com.lj95801.cla1;import java.lang.reflect.InvocationTargetException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.ResultSetHandler;import org.junit.Test;import com.lj95801.utils.JDBCUtils;public class testDBUtils {// 1、创建QueryRunner的实现类QueryRunner queryRunner = new QueryRunner();/* * 2、测试DBUtils中QueryRunner类的query方法 * 要从这个测试实例中充分认识Handler的原理和过程。 */@Testpublic void testQueryRunnerQuery() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。映射关系为:数据库ste_id对应类中的id成员,数据库的name对应类成员的name。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+  "FROM customers WHERE ste_id > ?";try {/*建立一个类,作为映射对象,把从数据库中读取出来的数据映射到这个类。 * 映射关系在sql语句中间确定下来。由别名将数据和类成员对应起来。 */List<Student> list = null;/* * 很重要的一个思想:MyResultHandler中handle方法返回什么类型的结果 * query方法就返回什么类型的结果。 */list = queryRunner.query(connection, sql, new MyResultHandler(), 2);//4、打印查询的结果for(Student stu : list){System.out.println(stu.toString());}}catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.release(null, null, null, connection);}}// 实际上也就是相当于一个回调函数,查询的结果交给外面来处理class MyResultHandler implements ResultSetHandler<List<Student>> {@Overridepublic List<Student> handle(ResultSet rs) throws SQLException {return transferResultSetToList(Student.class, rs);}}/** * 用于ResultSetHandler接口的实现 * @param clazz * @param rs * @return * @throws SQLException */public <T> List<T> transferResultSetToList(Class<T> clazz, ResultSet rs)throws SQLException {List<T> list = new ArrayList<T>();if(rs.next()){ResultSetMetaData rsmd = rs.getMetaData();int resultColumCunt = rsmd.getColumnCount();String name_c = null; Object value = null;do{T student = null;try {student = clazz.newInstance();} catch (InstantiationException e1) {e1.printStackTrace();} catch (IllegalAccessException e1) {e1.printStackTrace();}for(int i = 0; i < resultColumCunt; i++){name_c = rsmd.getColumnLabel(i + 1);value = rs.getObject(name_c);//使用BeanUtils工具,处理getter和setter是很好的。try {BeanUtils.setProperty(student, name_c, value);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}list.add(student);}while(rs.next());}return list;//即便没有也返回空的list,而不会返回null。这样可以放心的使用list方法。}}
测试结果:

 

上述代码中list = queryRunner.query(connection, sql, new MyResultHandler(), 2)方法实际上就是将sql查询得到的结果集ResultSet传递给MyResultHandler中的handler方法处理成我们想要的结果形式。为了满足不同的需求,我们必须要实现ResultSetHandler这个接口,实现接口中的handler方法。query方法返回的结果就是handler方法返回的结果。

  上面是我们自己实现的ResultSetHandler接口,在DBUtils工具中也实现了该接口的常用处理形式。就是其org.apache.commons.dbutils.handlers包下的类。下面介绍几种常用的:

1)BeanHandler     返回类型是T
 Convert the first row of the ResultSet into a bean with the Class given in the constructor.
就是将查询结果的第一行转换成一个与构造函数中指定的类相对应的实例。
和我们自己的JDBCUtils中的get方法功能是一致的。

2)BeanListHandler     返回类型是List<T>
Convert the whole ResultSet into a List of beans with the Class given in the constructor.
就是将查询结果的所有行一一的转换成构造函数指定类相对应的实例,并且将这些类的实例放置在一个list中,返回这个list。
和我们自己的JDBCUtils中的getForList方法功能是一致的。

3)MapHandler    返回类型是Map<String, Object>
Converts the first row in the ResultSet into a Map.
将结果的第一行转换成一个map。

4)MapListHandler返回的类型是List<Map<String, Object>>
Creates a new instance of MapListHandler
有两个重载构造函数:无参的默认使用BasicRowProcessor来处理,也可以自己指定RowProcessor convert类型。

5)ScalarHandler返回类型是Object
Returns one ResultSet column as an object via the ResultSet.getObject() method that performs type conversions.
可以根据不同的需要选择不同的构造函数:无参的默认返回第一行第一个元素,可以指定行的索引值,还可以指定行的名字。

下面通过实例,看看如何使用这些Handler。
①、使用BeanHandler来处理结果:
public class testDBUtils {// 1、创建QueryRunner的实现类QueryRunner queryRunner = new QueryRunner();/* * 三、使用BeanHandler 返回结果是一个类的引用。 */@Testpublic void testBeanHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。映射关系为:数据库ste_id对应类中的id成员,数据库的name对应类成员的name。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id = ?";try {/* * 4、query方法返回的结果为new BeanHandler<Student>(Student.class)中 * 指定的Student类的一个引用 */Student stu = null;stu = queryRunner.query(connection, sql, new BeanHandler<Student>(Student.class), 13);//5、打印结果System.out.println(stu.toString());} catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.release(null, null, null, connection);}}}
打印结果:

②、测试BeanListHandler得到一个list
<pre name="code" class="java">public class testDBUtils {// 1、创建QueryRunner的实现类QueryRunner queryRunner = new QueryRunner();/* * 四、测试BeanListHandler来得到一个指定类的list */@Testpublic void testBeanListHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。映射关系为:数据库ste_id对应类中的id成员,数据库的name对应类成员的name。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id > 2";try {//4、返回结果是一个listList<Student> list = null;list = queryRunner.query(connection, sql, new BeanListHandler<Student>(Student.class));//5、打印结果for(Student stu : list){System.out.println(stu.toString());}} catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.release(null, null, null, connection);}}}

执行结果:

③、测试MapHandler方法:
/* * 五、测试MapHandler的使用。返回第一条记录,将其转换成map * 键:列名      值:值 */@Testpublic void testMapHandler() {<span style="white-space:pre"></span>// 2、获得连接<span style="white-space:pre"></span>Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。即便sql语句返回多行记录,也只处理第一行。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "<span style="white-space:pre"></span>+ "FROM customers WHERE ste_id > 2";try {//4、将结果存放到map中Map<String, Object> map = null;map = queryRunner.query(connection, sql, new MapHandler());//5、打印结果。两种打印方式System.out.println(map);for(Map.Entry<String, Object> entry : map.entrySet()){System.out.println(entry.toString());}} catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.release(null, null, null, connection);}}
执行结果:

④、测试ScalerHandler,返回一个结果。返回类型为Object类型。
/* * 六、测试ScalerHandler。返回结果为一个Object。按照不同的需求,其有中不同的构造函数。 * 即便返回多条记录,也只处理第一行记录。 * ①、无参构造函数处理的是第一列。 * ②、可以指定处理列的索引值,也可以指定其列名。 */@Testpublic void testScalerHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。即便sql语句返回多行记录,也只处理第一行。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id > 2";try {Object obj = null;//4、分别用三种不同的构造函数,看看处理结果。注意,SQL返回的是两条记录,只会处理第一行记录。//无参默认处理第一行第一列。obj = queryRunner.query(connection, sql, new ScalarHandler());System.out.println(obj);obj = queryRunner.query(connection, sql, new ScalarHandler(2));System.out.println(obj);obj = queryRunner.query(connection, sql, new ScalarHandler("email"));System.out.println(obj);} catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.release(null, null, null, connection);}}
测试结果:



下面是完整的测试文件代码:
package com.lj95801.cla1;import java.lang.reflect.InvocationTargetException;import java.sql.Connection;import java.sql.ResultSet;import java.sql.ResultSetMetaData;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import java.util.Map;import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.ResultSetHandler;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import org.apache.commons.dbutils.handlers.MapHandler;import org.apache.commons.dbutils.handlers.ScalarHandler;import org.junit.Test;import com.lj95801.utils.JDBCUtils;public class testDBUtils {// 1、创建QueryRunner的实现类QueryRunner queryRunner = new QueryRunner();/* * 一、测试DBUtils中QueryRunner类的update方法 */@Testpublic void testQueryRunnerUpdate() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句String sql = "DELETE FROM customers WHERE ste_id IN(?, ?)";try {queryRunner.update(connection, sql, 7, 10);} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(null, null, null, connection);}}/* * 二、测试DBUtils中QueryRunner类的query方法 要从这个测试实例中充分认识Handler的原理和过程。 */@Testpublic void testQueryRunnerQuery() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。映射关系为:数据库ste_id对应类中的id成员,数据库的name对应类成员的name。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id > ?";try {/* * 建立一个类,作为映射对象,把从数据库中读取出来的数据映射到这个类。 * 映射关系在sql语句中间确定下来。由别名将数据和类成员对应起来。 */List<Student> list = null;/* * 很重要的一个思想:MyResultHandler中handle方法返回什么类型的结果 query方法就返回什么类型的结果。 */list = queryRunner.query(connection, sql, new MyResultHandler(), 2);// 4、打印查询的结果for (Student stu : list) {System.out.println(stu.toString());}} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(null, null, null, connection);}}/* * 三、使用BeanHandler 返回结果是一个类的引用。 */@Testpublic void testBeanHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。映射关系为:数据库ste_id对应类中的id成员,数据库的name对应类成员的name。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id = ?";try {/* * 4、query方法返回的结果为new BeanHandler<Student>(Student.class)中 * 指定的Student类的一个引用 */Student stu = null;stu = queryRunner.query(connection, sql, new BeanHandler<Student>(Student.class), 13);// 5、打印结果System.out.println(stu.toString());} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(null, null, null, connection);}}/* * 四、测试BeanListHandler来得到一个指定类的list */@Testpublic void testBeanListHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。映射关系为:数据库ste_id对应类中的id成员,数据库的name对应类成员的name。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id > 2";try {// 4、返回结果是一个listList<Student> list = null;list = queryRunner.query(connection, sql,new BeanListHandler<Student>(Student.class));// 5、打印结果for (Student stu : list) {System.out.println(stu.toString());}} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(null, null, null, connection);}}/* * 五、测试MapHandler的使用。返回第一条记录,将其转换成map 键:列名 值:值 */@Testpublic void testMapHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。即便sql语句返回多行记录,也只处理第一行。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id > 2";try {// 4、将结果存放到map中Map<String, Object> map = null;map = queryRunner.query(connection, sql, new MapHandler());// 5、打印结果。两种打印方式System.out.println(map);for (Map.Entry<String, Object> entry : map.entrySet()) {System.out.println(entry.toString());}} catch (Exception e) {e.printStackTrace();} finally {JDBCUtils.release(null, null, null, connection);}}/* * 六、测试ScalerHandler。返回结果为一个Object。按照不同的需求,其有中不同的构造函数。 * 即便返回多条记录,也只处理第一行记录。 * ①、无参构造函数处理的是第一列。 * ②、可以指定处理列的索引值,也可以指定其列名。 */@Testpublic void testScalerHandler() {// 2、获得连接Connection connection = JDBCUtils.getConnection("jdbc.properties");// 3、准备sql语句。即便sql语句返回多行记录,也只处理第一行。String sql = "SELECT ste_id \"id\", name \"name\", email \"email\" "+ "FROM customers WHERE ste_id > 2";try {Object obj = null;//4、分别用三种不同的构造函数,看看处理结果。注意,SQL返回的是两条记录,只会处理第一行记录。//无参默认处理第一行第一列。obj = queryRunner.query(connection, sql, new ScalarHandler());System.out.println(obj);obj = queryRunner.query(connection, sql, new ScalarHandler(2));System.out.println(obj);obj = queryRunner.query(connection, sql, new ScalarHandler("email"));System.out.println(obj);} catch (Exception e) {e.printStackTrace();}finally{JDBCUtils.release(null, null, null, connection);}}/* * 自己实现一个Handler 实际上也就是相当于一个回调函数,查询的结果交给外面来处理 */class MyResultHandler implements ResultSetHandler<List<Student>> {@Overridepublic List<Student> handle(ResultSet rs) throws SQLException {return transferResultSetToList(Student.class, rs);}}/** * 用于ResultSetHandler接口的实现 *  * @param clazz * @param rs * @return * @throws SQLException */public <T> List<T> transferResultSetToList(Class<T> clazz, ResultSet rs)throws SQLException {List<T> list = new ArrayList<T>();if (rs.next()) {ResultSetMetaData rsmd = rs.getMetaData();int resultColumCunt = rsmd.getColumnCount();String name_c = null;Object value = null;do {T student = null;try {student = clazz.newInstance();} catch (InstantiationException e1) {e1.printStackTrace();} catch (IllegalAccessException e1) {e1.printStackTrace();}for (int i = 0; i < resultColumCunt; i++) {name_c = rsmd.getColumnLabel(i + 1);value = rs.getObject(name_c);// 使用BeanUtils工具,处理getter和setter是很好的。try {BeanUtils.setProperty(student, name_c, value);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}}list.add(student);} while (rs.next());}return list;// 即便没有也返回空的list,而不会返回null。这样可以放心的使用list方法。}}




0 0