关灯
开启左侧

利用反射和泛型对JDBC进行简单的封装(添加和查询)

[复制链接]
老毕 发表于 2019-3-18 16:32:23 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 


//对于添加操作的封装, 先来理一下思路
    // 目的:设计一个添加方法,能针对任何当前系统中的表对应的类型
    // 准备两个测试实体类 Book , User
    // 分析:
    // 1. 返回值类型/参数类型应该用泛型T表示识别任意类型
    // 2. 如果在接口中使用泛型,实现类也需要在实现中使用泛型声明方法
    // 3. 在方法中,首先应当生成对应的添加的sql语句, 需要设计一个通用的添加操作字符串
    // "insert into tableName(fieldName...) values(null,?...)";
    // tableName:  t.getClass().getName()+"s"   利用反射的getClass
    // fieldName:   Class c = t.getClass()
    // c.getDeclaredFields  declaredFields[] 获知字段的数量  结合遍历
    // 4. 添加操作的sql字符串组装完成
    // 5. 建立连接, 生成预编译对象,
    // 5. 利用循环, 给参数赋值:  利用反射,获取t对象的特征
代码实现:
接口中的声明:<T>T insert(T t) throws ClassNotFoundException, SQLException, IllegalAccessException;
实现类:public <T> T insert(T t) throws ClassNotFoundException, SQLException, IllegalAccessException {
//   "insert into tableName(fieldName,...) values(null,?...)"
    // 声明一个字符串,用来组装添加语句
    StringBuffer buffer = new StringBuffer("insert into ");
    Class c= t.getClass();
   // System.out.println( c.getName()); // 获取完整的限定的类名
  //  System.out.println( c.getSimpleName()); 只获得类名本身

    // 追加表名, 追加s 和数据表建立对应关系
    buffer.append(c.getSimpleName()).append("s");  // insert into tableName
    //追加一个参数列表的左括号
    buffer.append("(");

    //利用Class对象,获取所有t中的字段
    Field[] declaredFields = c.getDeclaredFields();
    for (Field declaredField : declaredFields) {
        //遍历, 追加所有的字段名到添加语句上
        buffer.append(declaredField.getName()).append(",");
    }
    //当遍历完成, 处理最后一个字段的逗号
    buffer.deleteCharAt(buffer.length()-1);
    //再追加一个") values("
    buffer.append(") values(null");
    //System.out.println(buffer);

    // 循环追加对应数量的占位符?
    for (int i = 0; i < declaredFields.length-1; i++) {
        buffer.append(",?");
    }
    //再追加一个")"
    buffer.append(")");
    System.out.println(buffer);

    // 至此, 添加语句的动态处理就完成

    //预编译
    PreparedStatement preparedStatement = dbUtil.getPreparedStatement(buffer.toString());

    // 赋值 : 利用反射获取所有的字段值
    // fields 中包含id字段, 赋值时不考虑 ,i从1开始
    for (int i = 1; i < declaredFields.length; i++) {
        declaredFields.setAccessible(true);
       // System.out.println(declaredFields.get(t)) ;  // Field
        preparedStatement.setObject(i,declaredFields.get(t));
    }

    int lines =  dbUtil.execUpdate(preparedStatement);
    dbUtil.closeAll();

    // 添加完成之后,
    // 执行查询, 获取当前添加的编号
    // 利用反射将编号赋值给t
    return t;
}
//对于查询全部数据的操作的封装,只需要指定类型,不需要对象的特征值,故传递的参数使用了Class<T>//接口的声明:<T> List<T> selectAll(Class<T> tClass);
//实现类:public  List<T> selectAll(Class<T> tClass) {
    List<T> list = new ArrayList<>();
    // 获取结果集 ResultSet 对象
    String sql = "select * from "+tClass.getSimpleName()+"s";
    try {
        PreparedStatement preparedStatement = dbUtil.getPreparedStatement(sql);
        ResultSet resultSet = preparedStatement.executeQuery();
        while(resultSet.next()){
            T t = tClass.newInstance();
            Field[] declaredFields = tClass.getDeclaredFields();
            for (int i = 0; i < declaredFields.length; i++) {
                Object fieldValue = resultSet.getObject(i+1);
                declaredFields.setAccessible(true);
                declaredFields.set(t,fieldValue);
            }
           list.add(t);
        }
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (SQLException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    }finally {
        try {
            dbUtil.closeAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    return list;
}


 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

排行榜
关闭

站长推荐上一条 /1 下一条

官方微信

全国服务热线:

400-0708-360

公司地址:国家西部信息安全产业基地(成都市高新区云华路333号)

邮编:610000    Email:2908503813@qq.com

Copyright   ©2015-2016  EOIT论坛Powered by©Discuz!    ( 蜀ICP备11000634号-7 )