zoukankan      html  css  js  c++  java
  • Java自学-JDBC 预编译PreparedStatement

    在JDBC中使用预编译PreparedStatement 以及它的优点

    步骤 1 : 使用PreparedStatement

    和 Statement一样,PreparedStatement也是用来执行sql语句的
    与创建Statement不同的是,需要根据sql语句创建PreparedStatement
    除此之外,还能够通过设置参数,指定相应的值,而不是Statement那样使用字符串拼接

    注: 这是JAVA里唯二的基1的地方,另一个是查询语句中的ResultSet也是基1的。

    package jdbc;
        
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
        
    public class TestJDBC {
        public static void main(String[] args) {
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
      
            String sql = "insert into hero values(null,?,?,?)";
            try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                // 根据sql语句创建PreparedStatement
                PreparedStatement ps = c.prepareStatement(sql);
            ) {
                 
                // 设置参数
                ps.setString(1, "提莫");
                ps.setFloat(2, 313.0f);
                ps.setInt(3, 50);
                // 执行
                ps.execute();
      
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
        }
    }
    

    步骤 2 : PreparedStatement的优点1-参数设置

    Statement 需要进行字符串拼接,可读性和维护性比较差

    String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
    

    PreparedStatement 使用参数设置,可读性好,不易犯错

    String sql = "insert into hero values(null,?,?,?)";
    

    .

    package jdbc;
      
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.sql.Statement;
      
    public class TestJDBC {
        public static void main(String[] args) {
      
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
      
            String sql = "insert into hero values(null,?,?,?)";
            try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                Statement s = c.createStatement();
                PreparedStatement ps = c.prepareStatement(sql);
            ) {
                // Statement需要进行字符串拼接,可读性和维修性比较差
                String sql0 = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
                s.execute(sql0);
      
                // PreparedStatement 使用参数设置,可读性好,不易犯错
                // "insert into hero values(null,?,?,?)";
                ps.setString(1, "提莫");
                ps.setFloat(2, 313.0f);
                ps.setInt(3, 50);
                ps.execute();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
      
        }
    }
    

    步骤 3 : PreparedStatement的优点2-性能表现

    PreparedStatement有预编译机制,性能比Statement更快

    package jdbc;
      
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.SQLException;
    import java.sql.Statement;
      
    public class TestJDBC {
        public static void main(String[] args) {
      
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
      
            String sql = "insert into hero values(null,?,?,?)";
            try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                    Statement s = c.createStatement();
                    PreparedStatement ps = c.prepareStatement(sql);
                ) {
                // Statement执行10次,需要10次把SQL语句传输到数据库端
                // 数据库要对每一次来的SQL语句进行编译处理
                for (int i = 0; i < 10; i++) {
                    String sql0 = "insert into hero values(null," + "'提莫'" + ","
                            + 313.0f + "," + 50 + ")";
                    s.execute(sql0);
                }
                s.close();
      
                // PreparedStatement 执行10次,只需要1次把SQL语句传输到数据库端
                // 数据库对带?的SQL进行预编译
      
                // 每次执行,只需要传输参数到数据库端
                // 1. 网络传输量比Statement更小
                // 2. 数据库不需要再进行编译,响应更快
                for (int i = 0; i < 10; i++) {
                    ps.setString(1, "提莫");
                    ps.setFloat(2, 313.0f);
                    ps.setInt(3, 50);
                    ps.execute();
                }
     
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
      
        }
    }
    

    步骤 4 : PreparedStatement的优点3-防止SQL注入式攻击

    假设name是用户提交来的数据

    String name = "'盖伦' OR 1=1";
    

    使用Statement就需要进行字符串拼接
    拼接出来的语句是:

    select * from hero where name = '盖伦' OR 1=1
    

    因为有OR 1=1,这是恒成立的
    那么就会把所有的英雄都查出来,而不只是盖伦
    如果Hero表里的数据是海量的,比如几百万条,把这个表里的数据全部查出来
    会让数据库负载变高,CPU100%,内存消耗光,响应变得极其缓慢

    而PreparedStatement使用的是参数设置,就不会有这个问题

    package jdbc;
      
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Statement;
      
    public class TestJDBC {
        public static void main(String[] args) {
      
            try {
                Class.forName("com.mysql.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
      
            String sql = "select * from hero where name = ?";
            try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
                    Statement s = c.createStatement();
                PreparedStatement ps = c.prepareStatement(sql);
            ) {
                // 假设name是用户提交来的数据
                String name = "'盖伦' OR 1=1";
                String sql0 = "select * from hero where name = " + name;
                // 拼接出来的SQL语句就是
                // select * from hero where name = '盖伦' OR 1=1
                // 因为有OR 1=1,所以恒成立
                // 那么就会把所有的英雄都查出来,而不只是盖伦
                // 如果Hero表里的数据是海量的,比如几百万条,把这个表里的数据全部查出来
                // 会让数据库负载变高,CPU100%,内存消耗光,响应变得极其缓慢
                System.out.println(sql0);
      
                ResultSet rs0 = s.executeQuery(sql0);
                while (rs0.next()) {
                    String heroName = rs0.getString("name");
                    System.out.println(heroName);
                }
      
                s.execute(sql0);
      
                // 使用预编译Statement就可以杜绝SQL注入
      
                ps.setString(1, name);
      
                ResultSet rs = ps.executeQuery();
                // 查不出数据出来
                while (rs.next()) {
                    String heroName = rs.getString("name");
                    System.out.println(heroName);
                }
     
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
      
        }
    }
    

    更多内容,点击了解: 在JDBC中使用预编译PreparedStatement 以及它的优点

  • 相关阅读:
    【转】CUDA5/CentOS6.4
    【转】centos 6.4 samba 安装配置
    【转】Install MATLAB 2013a on CentOS 6.4 x64 with mode silent
    【转】Getting xrdp to work on CentOS 6.4
    【VLFeat】使用matlab版本计算HOG
    Unofficial Windows Binaries for Python Extension Packages
    March 06th, 2018 Week 10th Tuesday
    March 05th, 2018 Week 10th Monday
    March 04th, 2018 Week 10th Sunday
    March 03rd, 2018 Week 9th Saturday
  • 原文地址:https://www.cnblogs.com/jeddzd/p/13121451.html
Copyright © 2011-2022 走看看