JDBC基本教程之CallableStatement
副标题#e#
概述
CallableStatement 工具为所有的 DBMS 提供了一种以尺度形式挪用已储存 进程的要领。已储存进程储存在数据库中。对已储存进程的挪用是 CallableStatement工具所含的内容。这种挪用是用一种换码语法来写的,有两 种形式:一种形式带功效参,另一种形式不带功效参数。功效参数是一种输出 (OUT) 参数,是已储存进程的返回值。两种形式都可带有数量可变的输入(IN 参数)、输出(OUT 参数)或输入和输出(INOUT 参数)的参数。问号将用作参 数的占位符。
在 JDBC 中挪用已储存进程的语法如下所示。留意,方括号暗示其间的内容 是可选项;方括号自己并不是语法的构成部份。
{call 进程名[(?, ?, …)]}
返回功效参数的进程的语法为:
{? = call 进程名[(?, ?, …)]}
不带参数的已储存进程的语法雷同:
{call 进程名}
凡是,建设 CallableStatement 工具的人该当知道所用的 DBMS 是支持已储 存进程的,而且知道这些进程都是些什么。然而,假如需要查抄,多种 DatabaseMetaData 要领都可以提供这样的信息。譬喻,假如 DBMS 支持已储存 进程的挪用,则supportsStoredProcedures 要领将返回 true,而 getProcedures 要领将返回对已储存进程的描写。CallableStatement 担任 Statement 的要领(它们用于处理惩罚一般的 SQL 语句),还担任了 PreparedStatement 的要领(它们用于处理惩罚 IN 参)。
CallableStatement 中界说的所有要领都用于处理惩罚 OUT 参数或 INOUT 参数 的输出部门:注册 OUT 参数的 JDBC 范例(一般 SQL 范例)、从这些参数中检 索功效,可能查抄所返回的值是否为 JDBC NULL。
1、建设 CallableStatement 工具
CallableStatement 工具是用 Connection 要领 prepareCall 建设的。下例 建设 CallableStatement 的实例,个中含有对已储存进程 getTestData 挪用。 该进程有两个变量,但不含功效参数:
CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
个中?占位符为IN、OUT照旧INOUT参数,取决于已储存进程getTestData。
2、IN和OUT参数
将IN参数传给 CallableStatement 工具是通过 setXXX 要领完成的。该要领 担任自 PreparedStatement。所传入参数的范例抉择了所用的setXXX要领(譬喻 ,用 setFloat 来传入 float 值等)。
假如已储存进程返回 OUT 参数,则在执行 CallableStatement 工具以前必 须先注册每个 OUT 参数的 JDBC 范例(这是必须的,因为某些 DBMS 要求 JDBC 范例)。注册 JDBC 范例是用 registerOutParameter 要领来完成的。语句执行 完后,CallableStatement 的 getXXX 要领将取回参数值。正确的 getXXX 要领 是为各参数所注册的 JDBC 范例所对应的 Java 范例。换言之, registerOutParameter 利用的是 JDBC 范例(因此它与数据库返回的 JDBC 类 型匹配),而 getXXX 将之转换为 Java 范例。
作为示例,下述代码先注册 OUT 参数,执行由 cstmt 所挪用的已储存进程 ,然后检索在 OUT 参数中返回的值。要领 getByte 从第一个 OUT 参数中取出 一个 Java 字节,而 getBigDecimal 从第二个 OUT 参数中取出一个 BigDecimal 工具(小数点后头带三位数):
CallableStatement cstmt = con.prepareCall("{call getTestData(?, ?)}");
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
cstmt.executeQuery();
byte x = cstmt.getByte(1);
java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
CallableStatement 与 ResultSet 差异,它不提供用增量方法检索大 OUT 值的非凡机制。
#p#副标题#e#
3、INOUT参数
既支持输入又接管输出的参数(INOUT 参数)除了挪用 registerOutParameter 要领外,还要求挪用适当的 setXXX 要领(该要领是从 PreparedStatement 担任来的)。setXXX 要领将参数值配置为输入参数,而 registerOutParameter 要领将它的 JDBC 范例注册为输出参数。setXXX 要领提 供一个 Java 值,而驱动措施先把这个值转换为 JDBC 值,然后将它送到数据库中。这种 IN 值的 JDBC 范例和提供应 registerOutParameter 要领的 JDBC 类 型应该沟通。然后,要检索输出值,就要用对应的 getXXX 要领。譬喻,Java 范例为byte 的参数应该利用要领 setByte 来赋输入值。应该给 registerOutParameter 提供范例为 TINYINT 的 JDBC 范例,同时应利用 getByte 来检索输出值。
下例假设有一个已储存进程 reviseTotal,其独一参数是 INOUT 参数。要领 setByte 把此参数设为 25,驱动措施将把它作为 JDBC TINYINT 范例送到数据 库中。接着,registerOutParameter 将该参数注册为 JDBC TINYINT。执行完该 已储存进程后,将返回一个新的 JDBC TINYINT 值。要领 getByte 将把这个新 值作为 Java byte 范例检索。
#p#分页标题#e#
CallableStatement cstmt = con.prepareCall("{call reviseTotal (?)}");
cstmt.setByte(1, 25);
cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
cstmt.executeUpdate();
byte x = cstmt.getByte(1);
4、先检索功效,再检索 OUT 参数
由于某些 DBMS 的限制,为了实现最大的可移植性,发起先检索由执行 CallableStatement 工具所发生的功效,然后再用 CallableStatement.getXXX 要领来检索 OUT 参数。假如 CallableStatement 工具返回多个 ResultSet 对 象(通过挪用 execute 要领),在检索 OUT 参数前应先检索所有的功效。这种 环境下,为确保对所有的功效都举办了会见,必需对 Statement 要领 getResultSet、getUpdateCount 和getMoreResults 举办挪用,直到不再有功效 为止。
检索完所有的功效后,就可用 CallableStatement.getXXX 要领来检索 OUT 参数中的值。
5、检索作为OUT参数的NULL值
返回到 OUT 参数中的值大概会是JDBC NULL。当呈现这种景象时,将对 JDBC NULL 值举办转换以使 getXXX 要领所返回的值为 null、0 或 false,这取决于 getXXX 要领范例。对付 ResultSet 工具,要知道0或false是否源于JDBCNULL的 独一要领,是用要领wasNull举办检测。假如 getXXX 要领读取的最后一个值是 JDBC NULL,则该要领返回 true,不然返回 flase。