zoukankan      html  css  js  c++  java
  • 使用元数据简化jdbc代码---查询操作(用到反射)

    使用元数据简化jdbc代码---查询操作(用到反射)

    一  思路分析

        简化就是把共同的地方提取出来并放到一个方法里,在用到时只要调用就ok了,上一篇介绍了更新的操作,而查询的操作相对来说比较复杂,因为在查询之后不知道输出的列是多少,这是相对于框架的设计者来说的,但是如果相对于程序员是知道有多少列的,所以可以传一个接口,用实现类去给结果集赋值,并返回。

    二  代码分析(根据ID获取)

    1.提取简化的代码   DBManager.java

        //对查询的优化        

        public static Object find(String sql, Object[] params, ResultSetHandler rsh) throws SQLException {

           Connection con = null;

           PreparedStatement st = null;

           ResultSet rs = null;

           try {

               con = DBManager_c3p0.getConnection();

               st = con.prepareStatement(sql);

               for (int i = 0; i < params.length; i++) {

                  st.setObject(i + 1, params[i]);

               }

               rs = st.executeQuery();

               // 对结果集的处理,不知道有多少行,给他传个方法,

               // 即是调用程序员传过来对结果集进行处理 的方法

               return rsh.handler(rs);

           }  finally {

               DBManager.release(con, st, rs);

           }

      }

    注:Object[] params为占位符的数组

         ResultSetHandler rsh对结果集的处理器,即上面所说的接口。

     

    2.接口---用来向上一个方法中传的对象    ResultSetHandler.java

        import java.sql.ResultSet;

    //结果集处理器接口

    public interface ResultSetHandler {

            public Object handler(ResultSet rs);

    }

     

    3. 编写接口的实现类

    public class MyResultSetHandler implements ResultSetHandler {

     

        // 编写实现的类

        public Object handler(ResultSet rs) {

           User user = new User();

           try {

               if (rs.next()) {

                  user.setId(rs.getInt(1));

                  user.setName(rs.getString(2));

                  user.setPassword(rs.getString(3));

                  user.setEamil(rs.getString(4));

               }

           } catch (SQLException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           }

           return user;

        }

    }

    4.使用方法    UserDaoImpl.java

        public void find() throws SQLException {

           String sql = "select * from users where id=?";

           Object[] params = { 5 };

           MyResultSetHandler rsh = new MyResultSetHandler();

           User user = (User) DBManager.find(sql, params, rsh);

           System.out.println(user.toString());

        }

    5.测试

        new UserDaoImpl().find();

    三  缺陷思考和解决

    1.缺陷

    这样虽然可以解决查询的问题,但是只是相对于一个类,一个程序员知道类有多少列,但是如果让开发框架的人来写,他们不知道是什么类,不知道类中有多少列,所以要用到反射的机制来获取类,获取类的属性(数据库中的字段封装成的私有属性),这样实现接口的类又是一次变革。

    2.实现接口的类

    //作为框架的开发者,构建一个结果集的处理器,将结果集的一行记录封装在一个bean对象中

    public class BeanHandler implements ResultSetHandler {

        // 传递javabean对象的class对象

        public Class clazz;// 一种类型的对象利用反射机制创建指定类型的对象

        public BeanHandler(Class clazz) {

           this.clazz = clazz;

        }

        public Object handler(ResultSet rs) {

           try {

               if (!rs.next()) {

                  return null;

               }

               // 读取结果集中的各个类封装到javabean

               // 创建的是javabean对象

               Object bean = clazz.newInstance();

               // 读取结果集的元数据对象-------得到结果集中有多少列

               ResultSetMetaData meta = (ResultSetMetaData) rs.getMetaData();

               // 得到一共有几列

               int count = meta.getColumnCount();

               for (int i = 1; i <= count; i++) {

                  // 得到第i列的列名

                  String columnName = meta.getColumnName(i);

                  // 从结果集中根据列名读取值

                  Object value = rs.getObject(columnName);

                  // 通过反射的机制得到javabean里的某一个属性对应的Field对象

                  Field f = bean.getClass().getDeclaredField(columnName);

                  f.setAccessible(true);

                  f.set(bean, value);

               }

               return bean;

           } catch (Exception e) {

               // 再次抛出异常,让上一级去处理

               throw new RuntimeException(e);

           }  

        }

    }

    3.用此方法去调用

    public void findById() throws SQLException {

           // 通过反射的机制去传任意一个javabean对象

            String sql = "select * from users where id=?";

           Object[] params = { 1 };

           BeanHandler rsh = new BeanHandler(User.class);

           User user = (User) DBManager.find(sql, params, rsh);

           System.out.println(user.toString());

    }

    四  查询所有---用反射的机制获取并测试

    1.查询所有并返回

        public class BeanListHandler implements ResultSetHandler {

        // 传递javabean对象的class对象

        public Class clazz;// 一种类型的对象 利用反射机制创建指定类型的对象.

        public BeanListHandler(Class clazz) {

           this.clazz = clazz;

        }

        public Object handler(ResultSet rs) {

            try {

               List list = new ArrayList();

               // 读取一行

               while (rs.next()) {

                  // 封装到bean对象

                  Object bean = clazz.newInstance();

                  ResultSetMetaData meta = rs.getMetaData();

                  int count = meta.getColumnCount();

                  for (int i = 1; i <= count; i++) {

                      String columnName = meta.getColumnName(i);

                      // 通过列的名称读取列的值

                      Object value = rs.getObject(columnName);

                      // 得到属性值

                      Field f = clazz.getDeclaredField(columnName);

                      // 设置值 是私有的必须先为true,才可访问

                      f.setAccessible(true);

                      f.set(bean, value);

                  }

                  // 该bean对象加入到list集合

                  list.add(bean);

               }

               return list;

           } catch (Exception e) {

               throw new RuntimeException();

           }

        }

    }

    2.使用方法去调用

        public List findAll() {

           List list = null;

           String sql = "select * from users";

           Object[] params = {};

           BeanListHandler rsh = new BeanListHandler(User.class);

           try {

               list = (List) DBManager.find(sql, params, rsh);

           } catch (SQLException e) {

               // TODO Auto-generated catch block

               e.printStackTrace();

           }

           return list;

        }

    3.测试类

        public static void main(String[] args) {

           UserDaoImpl obj = new UserDaoImpl();

           List<User> list = obj.findAll();

           System.out.println(list.size());

           for(User entity:list){

               System.out.println(entity.toString());

           }

        }

  • 相关阅读:
    pm2
    php 基础知识
    EBADF, read
    php apache
    noah
    ejs
    node linux
    枚举系统进程
    c++ 进程权限的提升
    Liunx的目录结构
  • 原文地址:https://www.cnblogs.com/firstdream/p/8672929.html
Copyright © 2011-2022 走看看