2.6 测试结果演示
ps:
以下测试功能按部门表为例详细展示,员工表亦是相同做法,故不做员工表做详细演示
2.6.1 测试部门DAO实现类
①尝试添加数据到t_department中
更新数据前:
代码演示如下:
@Test //测试添加数据 public void test01(){ Scanner input=new Scanner(System.in); System.out.print("请输入部门名称:"); //注:这里要么全用nextLine(),要么全不用 String dname=input.nextLine(); System.out.print("请输入部门简介:"); String description=input.nextLine(); department d=new department(dname,description); DepartmentDAOlmpl dao=new DepartmentDAOlmpl(); boolean b = dao.addDepartment(d); System.out.println(b?"添加成功":"添加失败"); input.close(); }
②查询t_department所有的数据
@Test //查询t_employee表中所有的信息 public void test04(){ DepartmentDAOlmpl dao=new DepartmentDAOlmpl(); List<department> allDepartment = dao.getAllDepartment(); allDepartment.forEach(t -> System.out.println(t)); }
③尝试更新数据,修改t_department表的用户指定的did字段那行的dname与description字段的值
更新之前:
更新数据代码演示如下:
@Test //测试方法test3的优化版 //尝试修改t_department表的用户指定的did字段那行的dname与description字段的值 public void test03_1(){ DepartmentDAOlmpl dao=new DepartmentDAOlmpl(); Scanner input=new Scanner(System.in); System.out.print("请输入要修改的部门编号:"); int did=input.nextInt(); input.nextLine(); department department = dao.getBydid(did); System.out.print("请输入部门新名称("+department.getDname()+"):"); //注:这里要么全用nextLine(),要么全不用 String dname=input.nextLine(); //如果什么都输入,就默认使用原来的部门名称 if (dname.trim().length()==0){ dname=department.getDname(); } System.out.print("请输入部门新简介("+department.getDescription()+"):"); String description=input.nextLine(); if (description.trim().length()==0){ description=department.getDescription(); } input.close(); department=new department(department.getDid(),dname,description); boolean b = dao.updateDepartment(department); System.out.println(b?"更新成功":"更新失败"); /* 参数索引越界异常 java.lang.RuntimeException: java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 2). 可能原因:可能是update的sql语句的标点写了中文的标点符号 */ }
④尝试查询部门编号为4的数据
代码演示如下:
@Test //查询t_department表指定did的行的记录 public void test05(){ Scanner input=new Scanner(System.in); System.out.print("请输入部门编号:"); int did=input.nextInt(); DepartmentDAOlmpl dao=new DepartmentDAOlmpl(); department department = dao.getBydid(did); System.out.println(department); input.close(); }
⑤尝试删除部门编号为1012的数据
删除之前:
删除代码演示如下:
@Test //测试删除数据 public void test02(){ Scanner input=new Scanner(System.in); System.out.print("请输入部门编号:"); //注:这里要么全用nextLine(),要么全不用 int did=input.nextInt(); department d=new department(did); DepartmentDAOlmpl dao=new DepartmentDAOlmpl(); boolean b = dao.removeDepart(d); System.out.println(b?"删除成功":"删除失败"); input.close(); }
三、Dbutils优化代码
可引入Dbutils对DAO层的BaseDAOImpl类进行优化,其余代码不变,实现的功能亦是相同
3.1 Dbutils简介
dbutils,全称commons-dbutils,它 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
其中QueryRunner类封装了SQL的执行,是线程安全的。
- 可以实现增、删、改、查、批处理。
- 考虑了事务处理需要共用Connection。
- 该类最主要的就是简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。
- 不需要手动关闭连接,runner会自动关闭连接,释放到连接池中
3.2 如何使用Dbutils?
使用前提:
使用之前先导入Dbutils的jar包,导入步骤可参考我的这篇博客Java SE: JUnit快速入门指南,导入的步骤和它一模一样,只是jar包的名字不一样而已
(1)更新
public int update(Connection conn, String sql, Object... params) throws SQLException
:用来执行一个更新(插入、更新或删除)操作。
…
(2)插入
public T insert(Connection conn,String sql,ResultSetHandler rsh, Object… params) throws SQLException:只支持INSERT语句,其中 rsh - The handler used to create the result object from the ResultSet of auto-generated keys. 返回值: An object generated by the handler.即自动生成的键值
…
(3)批处理
public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException: INSERT, UPDATE, or DELETE语句
public T insertBatch(Connection conn,String sql,ResultSetHandler rsh,Object[][] params)throws SQLException:只支持INSERT语句
…
(4)使用QueryRunner类实现查询
public Object query(Connection conn, String sql, ResultSetHandler rsh,Object... params) throws SQLException
:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement 和 ResultSet 的创建和关闭。
…
ResultSetHandler接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler 接口提供了一个单独的方法:Object handle (java.sql.ResultSet rs)该方法的返回值将作为QueryRunner类的query()方法的返回值。
该接口有如下实现类可以使用:
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
BeanListHandler
:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。ScalarHandler
:查询单个值对象- MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
- MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
3.3 BaseDAOImply优化版
代码演示如下:
import org.apache.commons.dbutils.QueryRunner; import org.apache.commons.dbutils.handlers.BeanHandler; import org.apache.commons.dbutils.handlers.BeanListHandler; import org.apache.commons.dbutils.handlers.ScalarHandler; import util.JDBCToolsFinal; import java.sql.SQLException; import java.util.List; public class BaseDAOImpl { private QueryRunner queryRunner=new QueryRunner(); //通用的增,删,改的方法 /** * * @param sql : 执行的sql语句 * @param args :sql中有多少个?,就有多少个args,用来替代?并赋值 * @return int : 影响的记录条数 * @throws SQLException : 可能出现的sql异常 */ protected int update(String sql,Object ...args) throws SQLException{ return queryRunner.update(JDBCToolsFinal.getConnection(),sql, args); } /** * 通用查询多个JavaBean对象的方法 * @param clazz Class JavaBean.对象的类型的Class对象 * @param sql 执行的sql语句 * @param args Object ...为sqL中的?赋值,如果没有?,可以不传args实参 * @param <T> java.Been包中类的类型 * @return List<T> 里面包含查询出来的多个的T对象 * @throws Exception : 可能出现的sql异常 */ protected <T> List<T> getList(Class clazz,String sql,Object ...args) throws Exception{ return queryRunner.query(JDBCToolsFinal.getConnection(),sql,new BeanListHandler<T>(clazz),args); } /** * 通用查询单个JavaBean对象的方法 * @param clazz Class JavaBean.对象的类型的Class对象 * @param sql 执行的sql语句 * @param args Object ...为sqL中的?赋值,如果没有?,可以不传args实参 * @param <T> java.Been包中类的类型 * @return T 一个JavaBean对象 * @throws Exception : 可能出现的sql异常 */ protected <T> T getBean(Class clazz,String sql,Object ...args) throws Exception{ return queryRunner.query(JDBCToolsFinal.getConnection(),sql,new BeanHandler<T>(clazz),args); /* BeanHandler.类的对象作用是把数据库中的表中的一条记录封装为一个JavaBean.对象, 这条记录对应的是T类型的对象,如果创建T类型的对象,是通过clazz对象来完成, clazz是T类型的Class对象。 */ } //通用的查询某个值的方法 protected Object getValue(String sql,Object ... args) throws SQLException { return queryRunner.query(JDBCToolsFinal.getConnection(),sql,new ScalarHandler(),args); //ScalarHandler对象的作用是把sgL查询结果中的单个值返回 } //批处理:批量执行一组sql命令 protected void batch(String sql,Object[][] args) throws SQLException { queryRunner.batch(JDBCToolsFinal.getConnection(),sql,args); } }