Statement、PreparedStatement

1.statement(Java 执行数据库操作的一个重要方法)编辑
Statement 是 Java 执行数据库操作的一个重要方法,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。Statement对象,用于执行不带参数的简单SQL语句。

在默认情况下,同一时间每个 Statement 对象在只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与读取另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。

Statement 对象用于将 SQL 语句发送到数据库中。实际上有三种 Statement 对象,它们都作为在给定连接上执行 SQL 语句的包容器:Statement、PreparedStatement(它从 Statement 继承而来)和 CallableStatement(它从 PreparedStatement 继承而来)。它们都专用于发送特定类型的 SQL 语句: Statement 对象用于执行不带参数的简单 SQL 语句;PreparedStatement 对象用于执行带或不带 IN 参数的预编译 SQL 语句;CallableStatement 对象用于执行对数据库已存在的存储过程的调用。

Statement 接口提供了执行语句和获取结果的基本方法。PreparedStatement 接口添加了处理 IN 参数的方法;而CallableStatement 添加了处理 OUT 参数的方法。有些 DBMS 将已存储过程中的每条语句视为独立的语句;而另外一些则将整个过程视为一个复合语句。在启用自动提交时,这种差别就变得非常重要,因为它影响什么时候调用 commit 方法。在前一种情况中,每条语句单独提交;在后一种情况中,所有语句同时提交。

2.PreparedStatement
PreparedStatement继承自Statement,但比Statement功能强大的多。

优点:

1、PreparedStatement是预编译的,比Statement速度快。

当同时要执行多条相同结构sql语句时使用,这时可以用setObject(),addBatch()和executeBatch()这几个函数。

2、可以防止sql注入。

对JDBC而言,SQL注入攻击只对Statement有效,对PreparedStatement是无效的,这是因为PreparedStatement不允许在插入时改变查询的逻辑结构.

举例分析:

例一: 说明PreparedStatement速度快 插入两条语句只需编译一次,而Statement则需要编译两次。

package com;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class TestPreparedStatement {
    public static void main(String[] args) {
        Connection con = null;
        PreparedStatement pst = null;
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

            String url = "jdbc:sqlserver://127.0.0.1:1433;databaseName=userManager";
            con = DriverManager.getConnection(url, "as", "");


            String sql = "insert into myuser (userName,pwd) values (? , ?)";
            pst = con.prepareStatement(sql);


            pst.setString(1, "张三");  //也可以用setObject()
            pst.setString(2, "123");
            pst.addBatch();

            pst.setString(1, "李四");
            pst.setString(2, "456");
            pst.addBatch();

            pst.executeBatch();

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
           try {
               if (pst != null) {
                   pst.close();
                   pst = null;
               }
               if (con != null) {
                   con.close();
                   con = null;
               }
           } catch (SQLException e) {
               e.printStackTrace();
           }
       }
    }
}

例二:说明PreparedStatement可以防止sql注入。

System.out.println("请输入用户名:");
name = input.nextLine();
System.out.println("请输入密码:");
pwd = input.nextLine();

String sql = "select * from myuser where userName = '" + name + "' and pwd = '" + pwd + "'";

Statement st = con.createStatement();
ResultSet rs = st.executeQuery(sql);
if (rs.next()) {
    System.out.println("登陆成功!");
} else {
    System.out.println("登陆失败!");
}

当输入用户名为任意,密码为:123' or '1' = '1时,则都可以登录成功。



System.out.println("请输入用户名:");
name = input.nextLine();
System.out.println("请输入密码:");
pwd = input.nextLine();

String sql = "select * from myuser where userName = ? and pwd = ? ";
PreparedStatement pst = con.prepareStatement(sql);

pst.setString(1, name);
pst.setString(2, pwd);
ResultSet rs = pst.executeQuery();
System.out.println(sql);
if (rs.next()) {
    System.out.println("登陆成功!");
} else {
    System.out.println("登陆失败!");
}

当输入用户名为任意,密码为:123’ or ‘1’ = ‘1时,则都可以登录失败。防止了sql注入。

原文地址:https://www.cnblogs.com/lllini/p/11955376.html