zoukankan      html  css  js  c++  java
  • 浅析Statement和PreparedStatement的区别

       当我们使用java程序来操作sql server时会使用到Statement和PreparedStatement,俩者都可以用于把sql语句从java程序中发送到指定数据库,并执行sql语句。那么如何进行一个较好的选择?

    首先,我们来看俩者的区别:

    Statement和PreparedStatement的区别(1)

    1、直接使用Statement,驱动程序一般不会对sql语句作处理而直接交给数据库;使用PreparedStamen,形成预编译的过程,并且会对语句作字符集的转换(至少在sql server)中如此。

        如此,有两个好处:对于多次重复执行的语句,使用PreparedStament效率会更高一点,并且在这种情况下也比较适合使用batch;另外,可以比较好地解决系统的本地化问题。

    2、PreparedStatement还能有效的防止危险字符的注入,也就是sql注入的问题。(但是必须使用“对?赋值的方法”才管用)

     

    我们用一个实例来进行演示:

    PreparedStatement的使用[Sql_test2.java]

    /**

     * PreparedStatement使用CRUD

     *1、PreparedStatement可以提高执行效率(因为它有预编译的功能)

     *2、PreparedStatement可以防止SQL注入,但是要求用?赋值的方式才可以

     */

    packagecom.sqlserver;

    importjava.sql.*;

    publicclass Sql_test2 {

        public static void main(String[] args) {

            Connection ct=null;

            PreparedStatement ps=null;

            ResultSet rs=null;

            try {

                //1、加载驱动(把需要的驱动程序加入内存)

                Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

                //2、得到连接(指定连接到哪个数据源、数据库的用户名和密码)

                ct=DriverManager.getConnection("jdbc:odbc:mytest","sa","sa");

                //3、创建PreparedStatement

                //PreparedStatement用处:主要用于发送SQL语句到数据库

    //          ps=ct.prepareStatement("select *from dept where deptno=? and loc=?");

    //          //给?赋值(可防止SQL注入漏洞问题),不要直接使用拼接的方式

    //          ps.setInt(1, 20);

    //          ps.setString(2, "dallas");

    //          //演示:查询,显示所有的部门信息

    //          //ResultSet结果集,大家可以把ResultSet理解成返回一张表行的结果集

    //          rs=ps.executeQuery();

    //          //循环取出

    //          while(rs.next()){

    //              int a=rs.getInt(1);

    //              String b=rs.getString(2);

    //              String c=rs.getString(3);

    //              System.out.println(a+" "+b+" "+c);   

    //          }

               

                //使用PreparedStetement添加一条记录

    //          ps=ct.prepareStatement("insert into dept values(?,?,?)");

    //          ps.setInt(1, 60);

    //          ps.setString(2, "安全部");

    //          ps.setString(3, "上海");

    //          //执行

    //          int i=ps.executeUpdate();

    //          if(i==1){

    //              System.out.println("添加成功");

    //          }else{

    //              System.out.println("添加失败");

    //          }

               

                //使用PreparedStetement修改一条记录从dept表中修改loc=上海deptno改为50

    //          ps=ct.prepareStatement("update dept set deptno=? where loc='上海'");

    //          ps.setInt(1, 50);

    //          //执行

    //          int i=ps.executeUpdate();

    //          if(i==1){

    //              System.out.println("修改成功");

    //          }else{

    //              System.out.println("修改失败");

    //          }

               

                //使用PreparedStetement删除一条记录

                ps=ct.prepareStatement("delete from dept where deptno=?");

                ps.setInt(1, 50);

                int i=ps.executeUpdate();

                if(i==1){

                    System.out.println("删除成功");

                }else{

                    System.out.println("删除失败");

                }

            } catch (Exception e) {

                e.printStackTrace();

            }finally{

                //关闭资源,关闭顺序先创建后关闭,后创建先关闭

                try {

                    if(rs!=null){

                        rs.close();

                    }

                    if(ps!=null){

                        ps.close();

                    }

                    if(ct!=null){

                        ct.close();

                    }

                } catch (SQLException e) {

                    e.printStackTrace();

                }

            }

        }

    }



    此段代码比较容易理解,使用了PreparedStatement,其中对问号(?)的赋值防止了SQL的危险注入问题

    如果使用Statement,则在有时候会产生危险注入。比如,一个database中有一张表user

    create table  user

    {

        username   varchar(30)

        passwd     varchar(30)

    }

    insert  into user values('ywq' , 'ywqwd')

    select * from user where username='ywq' and passwd='ywqwd'

    通过以上语句将建立一张表,并且将数据查询显示出来。

    然而问题就出现在这儿!!!当我们写成select * from user where username='ywq' and passwd='ffwd' or 1='1'的时候,还是可以查询并且显示出数据,这就意味着前面的用户名和密码成为了虚设的,不起任何作用。如此看来,漏洞就在这儿。


    当使用Statement时,ps=ct.createStatement("select *from dept where deptno='10' and loc='北京'");此语句将产生危险注入,导致系统不安全。所以我们很有必要使用PreparedStatement

    修改之后的代码如下所示:

       ps=ct.prepareStatement("select * from user where username=? and passwd=?");

              ps.setString(1, "ywq");

              ps.setString(2, "ywqwd");

        此时将正确查询到数据。当第三行改为:ps.setString(2,""ywqwd" or 1=1") 时将得不到正确结果。   


    总结下对问号?赋值的格式如下所示:

           ps=ct.prepareStatement("insert into dept values(?,?,?)");

              ps.setInt(1, 60);

              ps.setString(2, "安全部");

              ps.setString(3, "上海");

    其中后三句分别对第一句中的?进行赋值。

    此时较好的解决了危险注入的问题。




  • 相关阅读:
    Three.js实现3D地图实例分享
    three.js中让模型自动居中的代码如下:
    three.js obj转js的详细步骤 convert_obj_three.py的用法
    three.js
    Web三维编程入门总结之三:3D碰撞检测初探
    Web三维编程入门总结之二:面向对象的基础Web3D框架
    Web三维编程入门总结之一:WebGL与Threejs入门知识
    主流浏览器css兼容问题的总结
    Three.js三维模型几何体旋转、缩放和平移
    从3dMax导出供threeJS使用的带动作模型与加载
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6467348.html
Copyright © 2011-2022 走看看