JDBC - Statements, PreparedStatement and CallableStatement

  • 简述

    一旦获得连接,我们就可以与数据库进行交互。JDBC Statement、CallableStatementPreparedStatement接口定义了使您能够发送 SQL 或 PL/SQL 命令并从数据库接收数据的方法和属性。
    它们还定义了有助于弥合数据库中使用的 Java 和 SQL 数据类型之间的数据类型差异的方法。
    下表总结了每个接口的用途,以决定要使用的接口。
    接口 推荐用途
    Statement 将此用于对数据库进行通用访问。在运行时使用静态 SQL 语句时很有用。Statement 接口不能接受参数。
    PreparedStatement 当您计划多次使用 SQL 语句时使用此选项。PreparedStatement 接口在运行时接受输入参数。
    CallableStatement 当您要访问数据库存储过程时使用此选项。CallableStatement 接口还可以接受运行时输入参数。
  • 语句对象

    创建语句对象

    在使用 Statement 对象执行 SQL 语句之前,您需要使用 Connection 对象的 createStatement() 方法创建一个,如下例所示 -
    
    
    Statement stmt = null;
    
    try {
    
       stmt = conn.createStatement( );
    
       . . .
    
    }
    
    catch (SQLException e) {
    
       . . .
    
    }
    
    finally {
    
       . . .
    
    }
    
    
    一旦创建了 Statement 对象,就可以使用它通过三个 execute 方法之一来执行 SQL 语句。
    • boolean execute (String SQL):如果可以检索到 ResultSet 对象,则返回布尔值 true;否则,它返回 false。使用此方法执行 SQL DDL 语句或需要使用真正动态 SQL 时。
    • int executeUpdate (String SQL)− 返回受 SQL 语句执行影响的行数。使用此方法执行 SQL 语句,您希望得到许多受影响的行 - 例如,INSERT、UPDATE 或 DELETE 语句。
    • ResultSet executeQuery (String SQL)− 返回一个 ResultSet 对象。当您希望获得结果集时使用此方法,就像使用 SELECT 语句一样。
  • 结束语对象

    正如您关闭 Connection 对象以节省数据库资源一样,出于同样的原因,您也应该关闭 Statement 对象。
    对 close() 方法的简单调用即可完成这项工作。如果先关闭 Connection 对象,它也会关闭 Statement 对象。但是,您应该始终明确关闭 Statement 对象以确保正确清理。
    
    
    Statement stmt = null;
    
    try {
    
       stmt = conn.createStatement( );
    
       . . .
    
    }
    
    catch (SQLException e) {
    
       . . .
    
    }
    
    finally {
    
       stmt.close();
    
    }
    
    
  • PreparedStatement 对象

    PreparedStatement的接口扩展了Statement接口,它为您提供了一个通用的Statement对象有两个优点附加功能。
    此语句使您可以灵活地动态提供参数。
  • 创建 PreparedStatement 对象

    
    
    PreparedStatement pstmt = null;
    
    try {
    
       String SQL = "Update Employees SET age = ? WHERE id = ?";
    
       pstmt = conn.prepareStatement(SQL);
    
       . . .
    
    }
    
    catch (SQLException e) {
    
       . . .
    
    }
    
    finally {
    
       . . .
    
    }
    
    
    JDBC 中的所有参数都由 ?符号,称为参数标记。在执行 SQL 语句之前,您必须为每个参数提供值。
    setXXX() 方法将值绑定到参数,其中 XXX表示您希望绑定到输入参数的值的 Java 数据类型。如果您忘记提供值,您将收到 SQLException。
    每个参数标记由其序号位置引用。第一个标记表示位置 1,下一个位置 2,依此类推。此方法与 Java 数组索引的方法不同,后者从 0 开始。
    全部 Statement object's与数据库交互的方法 (a) execute()、(b) executeQuery() 和 (c) executeUpdate() 也适用于 PreparedStatement 对象。但是,这些方法被修改为使用可以输入参数的 SQL 语句。
  • 关闭 PreparedStatement 对象

    就像关闭 Statement 对象一样,出于同样的原因,您也应该关闭 PreparedStatement 对象。
    对 close() 方法的简单调用即可完成这项工作。如果先关闭 Connection 对象,它也会关闭 PreparedStatement 对象。但是,您应该始终明确关闭 PreparedStatement 对象以确保正确清理。
    
    
    PreparedStatement pstmt = null;
    
    try {
    
       String SQL = "Update Employees SET age = ? WHERE id = ?";
    
       pstmt = conn.prepareStatement(SQL);
    
       . . .
    
    }
    
    catch (SQLException e) {
    
       . . .
    
    }
    
    finally {
    
       pstmt.close();
    
    }
    
    
  • CallableStatement 对象

    正如 Connection 对象创建 Statement 和 PreparedStatement 对象一样,它还创建了 CallableStatement 对象,该对象将用于执行对数据库存储过程的调用。
  • 创建 CallableStatement 对象

    假设,您需要执行以下 Oracle 存储过程 -
    
    
    CREATE OR REPLACE PROCEDURE getEmpName 
    
       (EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS
    
    BEGIN
    
       SELECT first INTO EMP_FIRST
    
       FROM Employees
    
       WHERE ID = EMP_ID;
    
    END;
    
    
    注意 − 以上存储过程是为 Oracle 编写的,但我们使用的是 MySQL 数据库,所以让我们为 MySQL 编写相同的存储过程,如下所示在 EMP 数据库中创建它 −
    
    
    DELIMITER $
    
    
    
    DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $
    
    CREATE PROCEDURE `EMP`.`getEmpName` 
    
       (IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
    
    BEGIN
    
       SELECT first INTO EMP_FIRST
    
       FROM Employees
    
       WHERE ID = EMP_ID;
    
    END $
    
    
    
    DELIMITER ;
    
    
    存在三种类型的参数:IN、OUT 和 INOUT。PreparedStatement 对象仅使用 IN 参数。CallableStatement 对象可以使用所有三个。
    以下是每个的定义 -
    范围 描述
    创建 SQL 语句时其值未知的参数。您可以使用 setXXX() 方法将值绑定到 IN 参数。
    出去 一个参数,其值由它返回的 SQL 语句提供。您可以使用 getXXX() 方法从 OUT 参数中检索值。
    进出 提供输入和输出值的参数。您可以使用 setXXX() 方法绑定变量并使用 getXXX() 方法检索值。
    下面的代码片段展示了如何使用 Connection.prepareCall() 实例化一个的方法 CallableStatement 基于前面存储过程的对象 -
    
    
    CallableStatement cstmt = null;
    
    try {
    
       String SQL = "{call getEmpName (?, ?)}";
    
       cstmt = conn.prepareCall (SQL);
    
       . . .
    
    }
    
    catch (SQLException e) {
    
       . . .
    
    }
    
    finally {
    
       . . .
    
    }
    
    
    String 变量 SQL,代表存储过程,带有参数占位符。
    使用 CallableStatement 对象与使用 PreparedStatement 对象非常相似。您必须在执行语句之前将值绑定到所有参数,否则您将收到 SQLException。
    如果您有 IN 参数,只需遵循适用于 PreparedStatement 对象的相同规则和技术;使用与您要绑定的 Java 数据类型相对应的 setXXX() 方法。
    当您使用 OUT 和 INOUT 参数时,您必须使用额外的 CallableStatement 方法 registerOutParameter()。registerOutParameter() 方法将 JDBC 数据类型绑定到存储过程预期返回的数据类型。
    一旦调用了存储过程,就可以使用适当的 getXXX() 方法从 OUT 参数中检索值。此方法将检索到的 SQL 类型值转换为 Java 数据类型。
  • 关闭 CallableStatement 对象

    正如您关闭其他 Statement 对象一样,出于同样的原因,您也应该关闭 CallableStatement 对象。
    对 close() 方法的简单调用即可完成这项工作。如果先关闭 Connection 对象,它也会关闭 CallableStatement 对象。但是,您应该始终显式关闭 CallableStatement 对象以确保正确清理。
    
    
    CallableStatement cstmt = null;
    
    try {
    
       String SQL = "{call getEmpName (?, ?)}";
    
       cstmt = conn.prepareCall (SQL);
    
       . . .
    
    }
    
    catch (SQLException e) {
    
       . . .
    
    }
    
    finally {
    
       cstmt.close();
    
    }