JDBC - 语句、PreparedStatement 和 CallableStatement


一旦获得连接,我们就可以与数据库进行交互。JDBC Statement、CallableStatementPreparedStatement接口定义了使您能够发送SQL 或PL/SQL 命令以及从数据库接收数据的方法和属性。

它们还定义了有助于弥合数据库中使用的 Java 和 SQL 数据类型之间的数据类型差异的方法。

下表提供了每个接口用途的摘要,以决定要使用的接口。

接口 推荐用途
陈述 使用它来对数据库进行通用访问。当您在运行时使用静态 SQL 语句时很有用。Statement 接口不能接受参数。
准备好的声明 当您打算多次使用 SQL 语句时,请使用此选项。PreparedStatement 接口在运行时接受输入参数。
可调用语句 当您想要访问数据库存储过程时可以使用它。CallableStatement 接口还可以接受运行时输入参数。

声明对象

创建语句对象

在使用Statement对象执行SQL语句之前,您需要使用Connection对象的createStatement()方法创建一个Statement对象,如下例所示:

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   . . .
}

创建 Statement 对象后,您可以使用它的三个执行方法之一来执行 SQL 语句。

  • boolean execute (String SQL):如果可以检索 ResultSet 对象,则返回布尔值 true;否则,返回 false。使用此方法执行 SQL DDL 语句或需要使用真正的动态 SQL 时。

  • intexecuteUpdate(String SQL) - 返回受 SQL 语句执行影响的行数。使用此方法执行您希望受影响的行数的 SQL 语句 - 例如 INSERT、UPDATE 或 DELETE 语句。

  • ResultSetexecuteQuery(String SQL) - 返回一个 ResultSet 对象。当您希望获得结果集时,请使用此方法,就像使用 SELECT 语句一样。

结束语对象

正如关闭 Connection 对象以节省数据库资源一样,出于同样的原因,您也应该关闭 Statement 对象。

简单地调用 close() 方法即可完成这项工作。如果先关闭 Connection 对象,它也会关闭 Statement 对象。但是,您应该始终显式关闭 Statement 对象以确保正确清理。

Statement stmt = null;
try {
   stmt = conn.createStatement( );
   . . .
}
catch (SQLException e) {
   . . .
}
finally {
   stmt.close();
}

为了更好地理解,我们建议您学习语句 - 示例教程

ReadyStatement 对象

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 数组索引不同,Java 数组索引从 0 开始。

所有与数据库交互的Statement对象方法(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 {
   . . .
}

字符串变量 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();
}

为了更好地理解,我建议学习Callable - Examples Code