zoukankan      html  css  js  c++  java
  • 9.30JavaWeb之PreparedStatement获取任意一个对象的属性值

    9.30JavaWeb之PreparedStatement获取任意一个对象的属性值

    获取一个对象的属性值

    关键点:

    • 使用泛型方法来获取

      • 通过泛型的模式获取运行时类

        /*通过反射获取运行是要建立的类的引用*/
       /**
        * 建立泛型参数、泛型方法
        * <T>表示泛型方法
        * 方法名前面的T表示返回值类型
        * Class<T>当中的T表示对应的运行时类
        * @param clazz
        * @param sql
        * @param args
        * @param <T>
        * @return
        */
       public <T> T getInstance(Class<T> clazz, String sql, Object ...args) {
           Connection conn = null;
           PreparedStatement ps = null;
           ResultSet rs = null;
           try {
               //获取数据库连接
               conn = JDBCUtils.getConnection();
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符
               for (int i=0; i<args.length; i++) {
                   ps.setObject(i+1, args[i]);
              }
               //执行sql保存为结果集对象
               rs = ps.executeQuery();

               //获取结果集元数据
               ResultSetMetaData rsmd = rs.getMetaData();
               //获取列数
               int columnCount = rsmd.getColumnCount();
               //获取结果集
               if (rs.next()) {
                   //通过反射获取运行时加载类建立对象的引用--->反射+泛型
                   T t = clazz.newInstance(); //--->任何一个类在提供一个JavaBean对象的时候要提供一个空参的public权限的构造器,在这里使用
                   /*
                   方法当中返回一个t
                   t由当前类决定的
                    */
                   //动态的获取列,列的数量为列数
                   for (int j=0; j<columnCount; j++) {
                       //动态的获取列值--->结果集当中获取列值
                       Object columnValue = rs.getObject(j+1);
                       //获取每列的列名
                       String columnLabel = rsmd.getColumnLabel(j+1);
                       //动态获取加载的类的属性--->获取到域(T类型的)
                       Field field = clazz.getField(columnLabel);
                       //设置私有属性可访问
                       field.setAccessible(true);
                       //将对象属性设置成列值
                       field.set(t, columnValue);
                  }
                   return t;
              }
          }catch (Exception e) {
               e.printStackTrace();
          }
           return null;
      }

    获取集合对象(多个对象)的属性值

    查询结果集返回多条数据--->多个对象

    新语法糖:--->list.forEach(System.out::println)

    由于占位符的使用所以解决了SQL注入的问题

        /**
        * 查询一条sql语句返回多个结果集对象
        * 使用List进行封装然后再集中展示
        * @since JDK 1.8
        * @date 2021/09/30
        * @author Lucifer
        */
       public <T> List<T> getForList(Class<T> clazz, String sql, Object ...args) {
           Connection conn = null;
           PreparedStatement ps = null;
           ResultSet rs = null;
           try {
               //获取数据库连接
               conn = JDBCUtils.getConnection();
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符
               for (int i=0; i<args.length; i++) {
                   ps.setObject(i+1, args[i]);
              }
               //执行sql保存为结果集对象
               rs = ps.executeQuery();

               //获取结果集元数据
               ResultSetMetaData rsmd = rs.getMetaData();
               //获取列数
               int columnCount = rsmd.getColumnCount();
               //创建集合对象--->用于存储查询出的结果集对象
               ArrayList<T> list = new ArrayList<T>();
               //查询多条语句使用循环进行查询
               while (rs.next()) {
                   T t = clazz.newInstance();
                   //处理结果集每一行数据的每一列
                   for (int j=0; j<columnCount; j++) {
                       //获取列值
                       Object columnValue = rs.getObject(j+1);

                       //获取列名
                       String columnLabel = rsmd.getColumnLabel(j+1);
                       //动态获取运行类
                       Field field = clazz.getDeclaredField(columnLabel);
                       field.setAccessible(true);
                       field.set(t, columnValue);
                  }
                   //将t对象添加进入集合数组
                   list.add(t);
                   /*
                   查询未找到
                   1、抛异常了
                   2、没有数据了
                    */
              }
               return list;
          }catch (Exception e) {
               e.printStackTrace();
          }
           return null;
      }

    注意:

    • 占位符的目的是为了解决SQL注入问题

    • 避免拼串的发生

        /**
        * 针对所有得运行时类进行表的查询操作
        * @since JDK 1.8
        * @date 2021/09/30
        * @author Lucifer
        */
       public <T> T getInstanceSQL(Class<T> clazz, String sql, Object ...args) {
           Connection conn = null;
           PreparedStatement ps = null;
           ResultSet rs = null;
           try {
               //建立连接
               conn = JDBCUtils.getConnection();
               //预编译sql
               ps = conn.prepareStatement(sql);
               //填充占位符
               for (int i=0; i<args.length; i++) {
                   ps.setObject(i+1, args[i]);
              }
               //执行查询操作
               rs = ps.executeQuery();

               //获取结果集元数据
               ResultSetMetaData rsmd = rs.getMetaData();
               //通过结果集元数据获取列数
               int columnCount = rsmd.getColumnCount();

               //查询表中第一行数据
               while (rs.next()) {
                   //通过反射获取运行时加载类建立对象的引用--->反射+泛型
                   T t = clazz.newInstance();
                   //循环获取列值
                   for (int j=0; j<columnCount; j++) {
                       //动态的获取列值--->结果集当中获取列值
                       Object columnValue = rs.getObject(j+1);
                       //获取每列的列名
                       String columnLabel = rsmd.getColumnLabel(j+1);
                       //动态获取加载的类的属性--->获取到域(T类型的)
                       Field field = clazz.getField(columnLabel);
                       //设置私有属性可访问
                       field.setAccessible(true);
                       //将对象属性设置成列值
                       field.set(t, columnValue);
                  }
                   return t;
              }
          }catch (Exception e) {
               e.printStackTrace();
          }
           return null;
      }

    测试方法:

        @Test
       public void testLoginNo1() {
           //获取控制台内容
           Scanner scan = new Scanner(System.in);
           System.out.println("UserName:");
           String user = scan.next();

           System.out.println("PassWord:");
           String password = scan.next();

           //提供一个sql语句
           String sql = "select `name`, `password` from users where Name = ? and Password = ?";
           /*
           上诉的写法称为拼串,需要拼写sql语句。--->不是一个完整的sql语句,存在sql注入的风险
            */

           User returnUser = getInstanceSQL(User.class, sql, user, password);

           if (returnUser!=null){
               System.out.println("Successfully!");
          }else {
               System.out.println("UserName or PassWord Error!!!");
          }
      }

    Preparestatement预编译sql语句--->预编译期间已经判断了sql的逻辑关系

    Preparestatement可以传流文件,拼串不可以。

    Preparestatement可以更高效的插入--->预编译期间只需要检验一次,后续的添加只需要填充占位符即可

    Statement因为没有预编译,所以在拼串的时候可以改变其逻辑关系,由且变成或等

    小结

    • 面向接口编程的思想

    • ORM思想


    只需要面向JDBC接口编程

    原则:

    • 不出现第三方的API

    • 将第三方API与代码解耦,第三方API封装到XML或者配置文件中,全程操作使用Driver对象进行操作--->多态的一种形式

    一个JavaBean类对应到数据库当中的一张表

    原则:

    • Java操作的任何东西都是以对象的方式进行呈现

      • getColumnCount

      • getColumnLabel

    使用反射获取到运行时类进行加载获取属性

                        //动态获取加载的类的属性--->获取到域(T类型的)
                       Field field = clazz.getField(columnLabel);
                       //设置私有属性可访问
                       field.setAccessible(true);
                       //将对象属性设置成列值
                       field.set(t, columnValue);

     

    It's a lonely road!!!
  • 相关阅读:
    计算相邻字段 四至
    eclipse+terminal
    10 行 Python 代码实现模糊查询/智能提示
    Sublime Text 3,有了Anaconda就会如虎添翼
    Visual Studio上开发Python六大功能
    11 Python Libraries You Might Not Know
    linux安装PyCharm,PyCharm常用快捷键及调试模式,pycharm里面对文件夹或者文件进行重命名
    mysql mac客户端: sequel,mysql-workbench
    ImageMagick convert多张照片JPG转成pdf格式,pdfunite合并PDF文件
    互联网金融ABS为何遭遇急刹车?
  • 原文地址:https://www.cnblogs.com/JunkingBoy/p/15369371.html
Copyright © 2011-2022 走看看