一旦获得连接,我们就可以与数据库进行交互。JDBC Statement、 CallableStatement 和 PreparedStatement 接口定义了方法和属性,这些方法和属性使您能够发送 SQL 或 PL/SQL 命令并从数据库接收数据。
它们还定义了有助于弥合数据库中使用的 Java 和 SQL 数据类型之间的数据类型差异的方法。
下表总结了每个接口的用途,以决定要使用的接口。
接口 | 推荐使用 |
---|---|
Statement | 将其用于对数据库的通用访问。在运行时使用静态SQL语句时非常有用。Statement接口不能接受参数。 |
PreparedStatement | 当您计划多次使用SQL语句时,请使用此选项。PreparedStatement接口在运行时接受输入参数。 |
CallableStatement | 当您要访问数据库存储过程时,请使用此选项。CallableStatement接口还可以接受运行时输入参数。 |
在可以使用Statement对象执行SQL语句之前,需要使用Connection对象的createStatement( )方法创建一个SQL语句,如以下示例所示-
Statement stmt = null; try { stmt = conn.createStatement( ); . . . } catch (SQLException e) { . . . } finally { . . . }
一旦创建了Statement对象,就可以使用其三个执行方法之一来执行SQL语句。
boolean execute (String SQL):如果可以检索到ResultSet对象,则返回布尔值true;否则返回false。当需要使用真正的动态SQL时,请使用此方法执行SQL DDL语句。
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(); }
为了更好地理解,我们建议您学习Statement 示例教程。
PreparedStatement接口扩展了Statement接口,它为您提供了附加的功能,与泛型Statement对象相比具有一些优势。
该语句使您可以灵活地动态提供参数。
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 语句。
与关闭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(); }
为了更好地理解,让我们学习“PreparedStatement 示例代码”。
就像 Connection 对象创建 Statement 和 PreparedStatement 对象一样,它也创建 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;
NOTE: 上面的存储过程已经为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 something。 |
OUT | 其值由返回的SQL语句提供的参数。使用getXXX()方法从参数中检索值。 |
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 数据类型绑定到预期存储过程返回的数据类型。
调用存储过程后,可以使用适当的 getXXX() 方法从OUT参数中检索值。此方法将检索到的SQL类型的值转换为Java数据类型。
就像关闭其他Statement对象一样,出于同样的原因,您也应该关闭CallableStatement对象。
简单的调用close()方法就可以了。如果先关闭Connection对象,它也会关闭CallableStatement对象。但是,您应该始终显式关闭CallableStatement对象,以确保正确清理。
CallableStatement cstmt = null; try { String SQL = "{call getEmpName (?, ?)}"; cstmt =conn.prepareCall(SQL); . . . } catch (SQLException e) { . . . } finally { cstmt.close(); }
为了更好地理解,我建议学习CallableStatement 示例代码。