JDBC - 语句,PreparedStatement和CallableStatement

获得连接后,我们可以与数据库进行交互. JDBC 语句,CallableStatement, PreparedStatement 接口定义了使您能够发送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对象,就可以使用它来执行一个带有三种执行方法之一的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对象的方法(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对象可以使用所有三个.

以下是每个 : 的定义;

参数描述
IN创建SQL语句时其值未知的参数.使用setXXX()方法将值绑定到IN参数.
OUT一个参数,其值由它返回的SQL语句提供.您可以使用getXXX()方法从OUT参数中检索值.
INOUT提供输入和输出值的参数.使用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数据类型绑定到存储过程应返回的数据类型.

调用存储过程后,从OUT参数中检索值使用适当的getXXX()方法.此方法将检索到的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();
}