DBUtils的使用
一. DBUtils的引出
1、connection不能提前关闭
当我们查出结果集resultSet的时候,就关闭了connection连接,这时resultSet就不能使用了
示例代码如下:
public class jdbcDBUtils { @Test public void test() throws Exception{ Connection connection = JDBCUtils.getConnection(); String sql = "select * from admin"; PreparedStatement preStatement = connection.prepareStatement(sql); ResultSet resultSet = preStatement.executeQuery(); /**注意: * 以下三种方式,都会导致 java.sql.SQLException: Operation not allowed after ResultSet closed * 在使用完resultSet结果集之前,不能将resultSet、preStatement、connection关闭。 */ //JDBCUtils.Close(resultSet,null,null); //JDBCUtils.Close(null,preStatement,null); JDBCUtils.Close(null,null,connection); while(resultSet.next()){ int id = resultSet.getInt("id"); String name = resultSet.getString("name"); String pwd = resultSet.getString("pwd"); System.out.println("id:" + id +" name:" + name + " pwd:" + pwd); } } }
运行结果如下:
总结:在使用resultSet结果集之前,不能提前关闭resultSet,preStatement以及connection。
2.resultSet无法重复使用
当遍历完resultSet之后,肯定要关闭连接,导致resultSet无法重复使用。
由1和2引出如下问题:
① 如何让resultSet结果集重复使用
② 在遍历的过程中,能否简化遍历过程
解决方案:使用DBUtils的jar包
二. DBUtils的使用
1. 在libs中引入dbutils的jar包
2. query语句:
① 将表中数据全部查找出来【多行】
public class jdbcDBUtils { /** * 查询表中所有结果 * @throws Exception */ @Test public void testSearchAll() throws Exception{ // 1. 在libs中引入dbutils的jar包 // 2. 获取druid连接池的连接 Connection connection = JDBCUtilsByDruid.getConnection(); // 3.使用queryRunner查询结果 String sql = "select * from admin"; QueryRunner queryRunner = new QueryRunner(); // 4.将connection,sql,bean对象,作为参数放入query()中 // 1)传入连接connection // 2)传入sql语句 // 3)传入bean对象 new BeanListHandler<>(Admin.class) 【反射机制】 // resultSet -> admin对象 -> List<Admin>集合 /** QueryRunner的query()源码如下: * 1) public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh) throws SQLException { * return this.query(conn, sql, rsh, (Object[])null); * * } * 注意在 1) 中 调用 2) 时,传入的可变参数是null * * 2) public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) * throws SQLException { * PreparedStatement stmt = null; * ResultSet rs = null; * Object result = null; * * try { * // 通过conn和sql创建PreparedStatement类的stmt对象 * stmt = this.prepareStatement(conn, sql); * // 将可变参数params传入给sql语句的占位符? * this.fillStatement(stmt, params); * // stmt执行sql语句 * rs = this.wrap(stmt.executeQuery()); * // 将得到的结果集resultSet--反射机制-->admin对象--封装-->result集合中 * result = rsh.handle(rs); // handle()动态绑定机制 * } catch (SQLException var33) { * this.rethrow(var33, sql, params); * } finally { * try { * this.close(rs); * } finally { * this.close((Statement)stmt); * } * } * * // 返回result集合 * return result; * } */ List<Admin> query = queryRunner.query(connection,sql, new BeanListHandler<>(Admin.class)); for (Admin admin : query) { System.out.println(admin); } JDBCUtilsByDruid.Close(null,null,connection); } }
①运行结果如下:
Admin{id=3, name='Tom3', pwd='123'} Admin{id=5, name='Tom2', pwd='123'} Admin{id=6, name='Tom3', pwd='123'} Admin{id=8, name='Tom2', pwd='123'} Admin{id=9, name='Tom3', pwd='123'} Admin{id=11, name='zw', pwd='123'} Admin{id=12, name='郑为', pwd='1234'} Admin{id=13, name='郑威', pwd='1234'} Admin{id=14, name='郑为', pwd='1234'} Admin{id=15, name='郑威', pwd='1234'} Process finished with exit code 0
注意①中源码 1) 和 2) 的区别,体现了重载的好处。
② 将表中数据按照指定条件筛选出来【单行】
public class jdbcDBUtils { /** * 查询单行结果 * @throws Exception */ @Test public void testSearchSingle() throws Exception{ Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner(); String sql = "select * from admin where id = ?"; Admin admin = queryRunner.query(connection, sql, new BeanHandler<>(Admin.class),3); System.out.println(admin); JDBCUtilsByDruid.Close(null,null,connection); } }
② 运行结果如下:
Admin{id=3, name='Tom3', pwd='123'}
③ 将表中的某一字段按照指定条件筛选出来【单行单列】
public class jdbcDBUtils { /** * 执行单行单列的查询 * @throws Exception */ @Test public void testSearchScalar() throws Exception{ Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner(); String sql = "select name from admin where id = ?"; Object query = queryRunner.query(connection, sql, new ScalarHandler(), 3); System.out.println(query); JDBCUtilsByDruid.Close(null,null,connection); } }
③ 运行结果如下:
Tom3
①,②,③的区别
① 返回集合,调用的方法:
List<Admin> query = queryRunner.query(connection,sql, new BeanListHandler<>(Admin.class));
具体运行步骤:resultSet--反射机制--》admin对象--封装--》result集合中。
② 返回对象,调用的方法:
Admin admin = queryRunner.query(connection, sql, new BeanHandler<>(Admin.class),3);
具体运行步骤:resultSet--反射机制--》admin对象。
③ 返回字段,调用的方法:
Object query = queryRunner.query(connection, sql, new ScalarHandler(), 3);
总结1:
ScalarHandler、BeanHandler、BeanListHandler 都实现了 handle()的方法,①的源码 result = rsh.handle(rs),由动态绑定机制可知,result结果不相同
总结2:
当需要查出多行数据集时,使用 new BeanListHandler<>(Admin.class) ;
当需要查出单行数据时,使用 new BeanHandler<>(Admin.class);
当需要查出单行单例【字段】时,使用 new ScalarHandler()。
3. update语句
public class jdbcDBUtils { /** * 执行DML语句 * @throws Exception */ @Test public void testDML() throws Exception{ Connection connection = JDBCUtilsByDruid.getConnection(); QueryRunner queryRunner = new QueryRunner(); // 增加insert /* String insert = "insert into admin values(null,?,?),(null,?,?)"; int ins = queryRunner.update(connection, insert, "郑为", "1234", "郑威", "1234"); System.out.println(ins > 0 ? "添加成功":"添加失败"); */ // 修改update /* String update = "update admin set pwd = ? where id = ?"; int upd = queryRunner.update(connection, update, "123456", 2); System.out.println(upd > 0 ? "更新成功":"更新失败"); */ // 删除delete /* String delete = "delete from admin where id = ?"; queryRunner.update(connection,delete,2); */ // 展现查询结果集,验证是否插入成功 String sql = "select * from admin"; // new BeanListHandler<>(Admin.class) 反射机制 result->admin对象->装入list集合 List<Admin> query1 = queryRunner.query(connection, sql, new BeanListHandler<>(Admin.class)); for (Admin admin : query1) { System.out.println(admin); } // 查询单行结果,验证是否修改/删除成功 sql = "select * from admin where id = ?"; Admin query2 = queryRunner.query(connection, sql, new BeanHandler<>(Admin.class),2); System.out.println(query2); // 带条件的查询,查询结果 sql = "select * from admin where name = ?"; List<Admin> query3 = queryRunner.query(connection, sql, new BeanListHandler<>(Admin.class), "郑为"); for (Admin admin : query3) { System.out.println(admin); } JDBCUtilsByDruid.Close(null,null,connection); } }
4. 总结
a:使用DBUtils工具类时,无论执行查询语句,还是DML语句,都是由QueryRunner类的对象queryRunner来执行;
b:查询时,queryRunner调用query()方法;修改【增,删,改】时,queryRunner调用update()方法;
c:执行sql语句时,queryRunner(连接名,SQL语句,具体语句具体分析)。
如果是查询,则是2中①②③的某一类的对象;
如果是修改,则是3中传入参数。