利用反射实现JDBC的数据库通用查询方法
来源:互联网 发布:淘宝宝贝展示图片大小 编辑:程序博客网 时间:2024/05/16 15:47
/** * 通用的查询方法 * 这里的SQL语句作为一个变量参数传递进来 * 如果是根据id或者name等模糊查询还需要将具体的参数传递进来 * 但是这里是通用的方法,我们不知道具体传入的是emp还是dept * 所以直接利用一个对象数组的这样一个参数传递进来 */ //返回一个结果集 public List<E> query(String sql,Object[] parames,Class<?> cla){ //这里还需要一个Class<?>属性来通过方法的名字以及方法的参数属性 //来得到一个方法,这里利用了反射的原理 List<E> list = new ArrayList<E>(); //获取连接 con = JDBCUtil.getConnection(); //预处理 try { ps = con.prepareStatement(sql); //由于这里的SQL语句是一个变量 //不知道需要查询哪些变量和哪些字段 //以及对应的字段名是什么 //预处理之后需要设置通过SQL语句传入进来的值 //比如通过id进行查询,and name like%S%等 //那么就需要先将这些问号设置具体的值,而这些值是存放在 //一个对象数组里面的,我们需要通过遍历拿到对应的值,才能进行 //具体的设置 for (int i = 0; i < parames.length; i++) { ps.setObject(i+1, parames[i]); } //做好SQL语句的准备工作之后就是执行SQL语句了 ResultSet rs = ps.executeQuery(); //接下来的工作就是将查询的结果从数据库中返回给用户 //同样利用rs的游标性质,通过while循环取出来 ResultSetMetaData data = rs.getMetaData(); //变化结果集的列数 //通过变化结果集来获取列数 int count = data.getColumnCount(); E o = null; while(rs.next()){ //通过rs先通过字段类型和字段名称来取出每一行对应的字段的值 //但是现在我们不知道具体是什么类型和字段 //这里我们通过结果集的metadata的属性来获取 //返回的数据类型为结果集变化数据 //然后我们从变化的数据中(metadata)获取字段名称也就是列名 //这里的参数需要传入第几列data.getColumnName(column) //所以我们还需要拿到变化结果集中由多少列 //遍历data中的列数,依次获取对应的列名 for (int i = 1; i <=count ; i++) { /* * 从结果集中获取数据 */ //之前的做法是通过rs.getstring("addr") //但是这里我不知道取出的是什么类型的的字段名称 //所以直接用getObject来表示 //然后具体的字段名称直接再用for循环遍历列名的时候 //用i来取值 Object val = rs.getObject(i); //获取到数据之后就是开始new一个student或者emp将从结果集中取出的一行行的数据 //封装成一个对象,然后添加到结果集中 //但是这里我们不能通过new一个对象来获取 //因为可能有的实体类没有构建构造方法 //并且构造器需要严格要求字段的顺序保持一致 //所以这里我们实例化对象的时候采用set+具体的字段名称 //所以这里我们需要先获取到具体的字段名称, String columnName = data.getColumnName(i); //获取到实体的具体的字段名称之后就需要构造一个和实体类里面 //定义的set方法一样的格式来调用set函数 String relMethodName = "set"+columnName.substring(0,1).toUpperCase()+columnName.substring(1).toLowerCase(); /* * public void setName(String name) { this.name = name; } 到这里我们已经拿到了setName(),下面还需要拿到字段的属性 同样是利用结果变化数据来拿到columnclassname */ String columnClassName = data.getColumnClassName(i); //但是这里我们拿到的只是字段的属性名称,是一个字符串类型的 //我们需要通过这个名称来转为具体的属性 //就需要通过forname的反射来实现 try { Class<?> columnType = Class.forName(columnClassName); //由于这里返回的class属性太多我们不知道具体是哪个,比如可能有string double int 或者public void 函数等 //所以这里我们利用Class<?>的泛化来表示 通过属性名称反射的属性 /** * 同时需要注意的是虽然我们已经得到了具体的字段属性 * 但是Java的数据类型表示方法和数据库的数据类型表示方法不一致 * 所以我们还需要将Java中数据类型转为数据库的类型 * 主要需要转换的就是decimal类型 */ //所以这里需要一个if判断得到的column type属性是否有decimal属性,有的话 //就将对应的属性转为int类型 //同时还需要将里面的值也要强制转为int类型 if(java.math.BigDecimal.class.equals(columnType)){ columnType = int.class; //这里的val是通过getobject属性获取的,是object类型,所以需要先强制转换为 //bigdecimal类型,然后转为int类型 val = ((java.math.BigDecimal)val).intValue(); } try { //到这里我们已经拿到了方法名字如:setName //以及需要设置的字段的类型 如 string //那么就相当于我们可以创建一个public void setName(String name) {} //这样的函数方法了 //要拿到一个实体的set方法那么我们需要先得到这个属性的class属性 //但是这个实体是一个变化的可能是Emp,或者Dept, //所以这里也需要通过一个参数传递进来 Method method = cla.getMethod(relMethodName, columnType); try { //现在我们已经得到了方法 /** * public void setName(String name) { this.name = name; } */ //然后就是需要找到this 也就是调用方法的执行体 //而这里的this指的就是当前的对象 //但是在这个通用的查询方法中我们并不知道 //传入进来的对象到底是什么,所以我们初始化一个对象 //利用E o = null,来实例化一个对象泛指所有的对象 //然后利用方法的invoke属性来执行将取出的val设置给对象O method.invoke(o, val); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } } //封装好对象之后就需要添加到集合中 //遍历一张表就添加一次 //for循环完了就添加一个对象 list.add(o); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return list; }
然后再写一个具体的子类继承上面的通用方法
StuDAO
public class StuDAO extends BaseDAO<Student> {public List<Student> findAll(Object[] parames){ String sql = "select * from student"; //调用父类的方法query return this.query(sql, parames, Student.class); //返回当前方法的query方法 //方法中调用方法 //子类中的方法调用父类中的方法 }
这里还需要一个中转作用的StuService,起一个在数据库和用户中间的参数传递的桥梁
public class Stuservice {/** * findAll() */ public List<Student> findAll(){ //查询所有的时候不需要参数 //这里定义需要传入的参数为空的集合 Object[] parames ={}; //调用StuDAO的方法findAll return sd.findAll(parames); } }
在测试类中进行测试
public class TestInfo { private StudentDAO sd = new StudentDAO(); private Stuservice ss = new Stuservice(); /** * 查询所有 */ @Test public void testFindAll(){ //调用StuService的方法findAll,返回一个结果集 List<Student> list = ss.findAll(); for (Student student : list) { System.out.println(student); } }}
阅读全文
0 0
- 利用反射实现JDBC的数据库通用查询方法
- 利用java反射创建通用的数据库查询方法
- JDBC:利用反射及JDBC元数据编写通用的查询方法
- JDBC:利用 ResultSetMetaData 和反射编写通用查询方法
- (JDBC)利用Java反射编写一个万能的数据库表查询方法
- JDBC查询的通用方法
- 利用反射及JDBC元数据编写通用的查询方法 cp66的头像 cp66 7 2015-02-13 23:16 0
- 使用JDBC编写通用的查询方法
- 【Java学习】使用泛型和反射 创建通用的数据库查询方法
- 使用泛型和反射 创建通用的数据库查询方法
- 利用java反射机制编写通用的toString 方法
- jdbc查询的通用方法的简单版
- 利用java的反射机制实现通用dao
- JDBC(六) 编写通用的更新和查询方法
- 利用存储过程实现交叉表格式数据查询的一种通用方法
- JDBC查询表返回List通用方法
- java JDBC执行查询通用方法
- 利用元数据编写查询的通用方法
- 欢迎使用CSDN-markdown编辑器
- 利用图片实现表单功能
- 给你一台大疆无人机,你能用来做点啥?(一)----------获取正射影像
- 知网__
- Struts2.5文件上传和下载详解(一)
- 利用反射实现JDBC的数据库通用查询方法
- 在一个二维数组中查找一个数,这个数组的行和列都是以递增形式存储的
- PHP面向对象深入理解之五(内省函数与反射类)
- 构造函数实现一个省市县三级联动
- vim编辑器-分屏
- Linux系统如何查看版本信息
- break与continue的区别
- 关于垃圾回收的一些基本原理及技术解析
- Mybatis 杂项