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

2021/10/5 20:11:08

本文主要是介绍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);

 



这篇关于9.30JavaWeb之PreparedStatement获取任意一个对象的属性值的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程