• 学习记录07 --- 升级DBTools,防止SQL注入


    今天上午才了解到我之前写的DBTools会导致sql注入,所以今天来升级下这个DBTools

    这次我们连接数据库就不用一个方法了,直接在static里面完成

     1 //创建一个静态代码块连接数据库
     2     static {
     3         try {
     4             //导入驱动类
     5             Class.forName("com.mysql.jdbc.Driver");
     6             //创建连接对象
     7             conn = DriverManager.getConnection(url,user,pwd);
     8         } catch (ClassNotFoundException | SQLException e) {
     9             e.printStackTrace();
    10         }
    11     }

    这样在程序执行的时候就连接了数据库,不需要再调用一个方法了

    那么先来重写查询的方法,我们原本的方法是这样的

     1 //数据库查询操作
     2     public static ResultSet executeQuery(String sql) throws Exception {
     3         //调用连接数据库方法连接数据库
     4         connetcDatabase();
     5         //创建命令行
     6         stt = conn.createStatement();
     7         //执行sql语句
     8         ResultSet result = stt.executeQuery(sql);
     9         //返回操作结果
    10         return result;
    11     }

    如果按照以上方式写,使用Statement对象,很容易导致SQL注入,我们就可以这样写

    1 //数据库查询操作
    2     public static ResultSet executeQuery(String sql) throws Exception {
    3         //创建命令行
    4         PreparedStatement ppt = conn.prepareStatement(sql);
    5         //执行sql语句
    6         ResultSet result = ppt.executeQuery();
    7         //返回操作结果
    8         return result;
    9     }

    那使用预编译的Statement可以防止sql注入,因为这个是把值当作参数传给sql语句

    也就是说我们需要传值的地方写个?   然后使用setObject等等方式来进行传值

    但是这里有个问题,我们不知道会有多少个参数,那就需要可变参数来完成,然后用for循环遍历

     1 //数据库查询操作
     2     public static ResultSet executeQuery(String sql,Object ... objs) throws Exception {
     3         //创建预编译的Statement
     4         PreparedStatement ppt = conn.prepareStatement(sql);
     5         //遍历传值
     6         for(int i=0;i<objs.length;i++){
     7             ppt.setObject(i+1,objs[i]);
     8         }
     9         //执行sql语句
    10         ResultSet result = ppt.executeQuery();
    11         //返回操作结果
    12         return result;
    13     }

    但是这还有个问题,因为查询全部的话,就不需要传参数过来,那么objs为null就会报异常

    那么我们需要在for的条件判断再加一个

    //遍历传值
            for(int i=0;objs!=null&&i<objs.length;i++){
                ppt.setObject(i+1,objs[i]);
            }

    那么这样就解决了这个问题,那么增删改的也是一样,复制过去

     1 //数据库增删改操作
     2     public static int executeUpdate(String sql,Object ... objs) throws Exception {
     3         //创建预编译的Statement
     4         PreparedStatement ppt = conn.prepareStatement(sql);
     5         //遍历传值
     6         for(int i=0;objs!=null&&i<objs.length;i++){
     7             ppt.setObject(i+1,objs[i]);
     8         }
     9         //执行sql语句
    10         int line = ppt.executeUpdate();
    11         //返回操作结果
    12         return line;
    13     }

    然后我们会发现,里面的for循环一模一样,那么我们可以把这个单独封装成一个方法

     1 //获取PreparedStatement对象
     2     public static PreparedStatement getPreparedStatement(String sql,Object ... objs) throws Exception {
     3         //创建预编译的Statement
     4         PreparedStatement ppt = conn.prepareStatement(sql);
     5         //遍历传值
     6         for(int i=0;objs!=null&&i<objs.length;i++){
     7             ppt.setObject(i+1,objs[i]);
     8         }
     9         //返回PreparedStatement对象
    10         return ppt;
    11     }

    那么这么封装以后,我们的查询和增删改的方法就可以简短一些

    然后关闭连接的方法依旧是关闭连接的方法,不变

    1 //关闭数据库连接
    2     public static void closeConnection() throws Exception {
    3         //关闭数据库连接
    4         conn.close();
    5     }

    那么这个DBTools就修改完成了,但是进行测试的时候发现出了问题,进行第一次数据库操作会把数据库给关闭连接了

    所以我们不能把数据库连接写在静态代码块中了,只能写一个方法了

    1 //创建一个方法连接数据库
    2     public static void getConnection() throws Exception {
    3         //创建连接对象
    4         conn = DriverManager.getConnection(url,user,pwd);
    5     }

    那么我们在getPreparedStatement这个方法中调用就OK了

  • 相关阅读:
    这难道就是一个普通人的一生???
    【纪念】纪念随笔数上3位数
    【移动端】js禁止页面滑动与允许滑动
    【react懒加载组件】--react-lazyload
    ES6知识整理(7)--Set和Map数据结构
    Hibernate检索策略
    Hibernate HQL多表查询
    Hibernate各种查询操作(二)
    Hibernate各种查询操作(一)
    Hibernate多对多操作
  • 原文地址:https://www.cnblogs.com/huajidafahao/p/11288871.html
Copyright © 2020-2023  润新知