使用元数据简化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());

       }

    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值