学习记录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 = stt.executeQuery(sql);
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(sql);
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(sql);
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就修改完成了,但是这个还是有很大的缺点,多线程的话会出问题,当前目前这个够用,等以后弄多线程再改

猜你喜欢

转载自www.cnblogs.com/huajidafahao/p/11288871.html