zoukankan      html  css  js  c++  java
  • JDBC系列教材 (五)- 在JDBC中使用预编译Statement 以及它的优点

    步骤1:使用PreparedStatement
    步骤2:PreparedStatement的优点1-参数设置
    步骤3:PreparedStatement的优点2-性能表现
    步骤4:PreparedStatement的优点3-防止SQL注入式攻击
    步骤5:练习-性能比较
    步骤6:答案-性能比较

    步骤 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(2313.0f);

                ps.setInt(350);

                // 执行

                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(2313.0f);

                ps.setInt(350);

                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(2313.0f);

                    ps.setInt(350);

                    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();

            }

      

        }

    }


    更多内容,点击了解: https://how2j.cn/k/jdbc/jdbc-preparedstatement/388.html

  • 相关阅读:
    CSS基本语法(慕课网学习笔记)
    Sublime Text3 显示左侧的目录树
    设置Sublime插件快捷键--实现CSS颜色选取
    HTML基本语法(慕课网学习笔记)
    cdoj1324卿学姐与公主
    模板-求组合数
    线段树--数据结构专题学习
    最短路径算法
    杭电1874畅通工程续 -最短路径
    杭电1027Ignatius and the Princess II模拟
  • 原文地址:https://www.cnblogs.com/Lanht/p/12615465.html
Copyright © 2011-2022 走看看