⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callablestatement.doc.html

📁 JDBC入门中文文档
💻 HTML
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>

<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; CHARSET=gb2312">
<title></title>
</head>

<body bgcolor="#ffffff">

<table width="600">
  <tr>
    <td><font size="-1"><a href="introTOC.doc.html">目录</a> | <a
    href="preparedstatement.doc.html">上一页</a> | <a href="mapping.doc.html">下一页</a> 
    </font></td>
    <td align="right"><i>JDBC<sup><font size="-2">TM</font></sup> 指南:入门</i></td>
  </tr>
</table>

<hr>

<p><br>
<a name="998919"></a> </p>

<h1>7 - CallableStatement</h1>

<p>本概述是从《<em>JDBC<font size="-1"><sup>TM</sup></font> Database Access from 
Java<font size="-1"><sup>TM</sup></font>: A Tutorial and Annotated Reference</em> 
》这本书中摘引来的。JavaSoft 
目前正在准备这本书。这本书是一本教程,同时也是 JDBC 
的重要参考手册,它将作为 Java 系列的组成部份在 1997 年春季由 
Addison-Wesley 出版公司出版。</p>

<p><a name="997085"></a> </p>

<h2>7.1 概述</h2>
<code>

<p>CallableStatement</code> 对象为所有的 DBMS 
提供了一种以标准形式调用已储存过程的方法。已储存过程储存在数据库中。对已储存过程的<em>调用</em>是 
<code>CallableStatement</code> 
对象所含的内容。这种调用是用一种换码语法来写的,有两种形式:一种形式带结果参数,另一种形式不带结果参数(有关换码语法的信息,参见第 
<a href="statement.doc.html#999752">4</a> 节“语句”)。结果参数是一种输出 
(OUT) 
参数,是已储存过程的返回值。两种形式都可带有数量可变的输入(IN 
参数)、输出(OUT 参数)或输入和输出(INOUT 
参数)的参数。问号将用作参数的占位符。</p>

<p><a name="999016"></a>在 JDBC 
中调用已储存过程的语法如下所示。注意,方括号表示其间的内容是可选项;方括号本身并不是语法的组成部份。</p>

<pre><a name="999017"></a>    {call 过程名[(?, ?, ...)]}
</pre>

<p>返回结果参数的过程的语法为: </p>

<pre><a name="999019"></a>    {? = call 过程名[(?, ?, ...)]}
</pre>

<p>不带参数的已储存过程的语法类似: </p>

<pre><a name="999021"></a>    {call 过程名}
</pre>

<p>通常,创建 <code>CallableStatement</code> 对象的人应当知道所用的 DBMS 
是支持已储存过程的,并且知道这些过程都是些什么。然而,如果需要检查,多种 
<code>DatabaseMetaData</code> 方法都可以提供这样的信息。例如,如果 DBMS 
支持已储存过程的调用,则<code> supportsStoredProcedures</code> 方法将返回 
true,而<code> getProcedures</code> 方法将返回对已储存过程的描述。</p>

<p><code>CallableStatement</code> 继承 <code>Statement</code> 
的方法(它们用于处理一般的 SQL 语句),还继承了 <code>PreparedStatement</code> 
的方法(它们用于处理 IN 参数)。<code>CallableStatement</code> 
中定义的所有方法都用于处理 OUT 参数或 INOUT 参数的输出部分:注册 
OUT 参数的 JDBC 类型(一般 SQL 
类型)、从这些参数中检索结果,或者检查所返回的值是否为<code> 
JDBC</code> <code>NULL</code>。</p>

<p><a name="998954"></a> </p>

<h3>7.1.1 创建 CallableStatement 对象</h3>
<code>

<p>CallableStatement</code> 对象是用 <code>Connection</code> 方法 <code>prepareCall</code> 
创建的。下例创建 <code>CallableStatement</code> 
的实例,其中含有对已储存过程 <code>getTestData</code> 
调用。该过程有两个变量,但不含结果参数: </p>

<pre><a name="998956"></a>    CallableStatement cstmt = con.prepareCall(
<a name="998957"></a>                  &quot;{call getTestData(?, ?)}&quot;);
</pre>

<p>其中 <code>?</code> 占位符为 IN、 OUT 还是 INOUT 
参数,取决于已储存过程 <code>getTestData</code>。</p>

<p><a name="998959"></a> </p>

<h3>7.1.2 IN 和 OUT 参数</h3>

<p>将 IN 参数传给 <code>CallableStatement</code> 对象是通过 <code>setXXX</code> 
方法完成的。该方法继承自 <code>PreparedStatement</code>。所传入参数的类型决定了所用的 
<code>setXXX</code> 方法(例如,用<code> setFloat</code> 来传入 <code>float</code> 
值等)。</p>

<p><a name="998961"></a>如果已储存过程返回 OUT 参数,则在执行 <code>CallableStatement</code> 
对象以前必须先注册每个 OUT 参数的 JDBC 
类型(这是必需的,因为某些 DBMS 要求 JDBC 类型)。注册 JDBC 
类型是用 <code>registerOutParameter</code> 方法来完成的。语句执行完后,<code>CallableStatement</code> 
的 <code>getXXX</code> 方法将取回参数值。正确的 <code>getXXX</code> 
方法是为各参数所注册的 JDBC 类型所对应的 Java 类型(从 JDBC 类型到 
Java 类型的标准映射见 <a href="mapping.doc.html#1004864">8.6.1</a> 
节中的表)。换言之, <code>registerOutParameter</code> 使用的是 JDBC 
类型(因此它与数据库返回的 JDBC 类型匹配),而 <code>getXXX</code> 
将之转换为 Java 类型。</p>

<p><a name="998965"></a>作为示例,下述代码先注册 OUT 参数,执行由 <code>cstmt</code> 
所调用的已储存过程,然后检索在 OUT 参数中返回的值。方法 <code>getByte</code> 
从第一个 OUT 参数中取出一个 Java 字节,而<code> getBigDecimal</code> 
从第二个 OUT 参数中取出一个 <code>BigDecimal</code> 
对象(小数点后面带三位数): </p>

<pre><a name="998966"></a>    CallableStatement cstmt = con.prepareCall(
<a name="998967"></a>                          &quot;{call getTestData(?, ?)}&quot;);
<a
name="998968"></a>    cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
<a
name="998969"></a>    cstmt.registerOutParameter(2, java.sql.Types.DECIMAL, 3);
<a
name="998970"></a>    cstmt.executeQuery();
<a name="998971"></a>    byte x = cstmt.getByte(1);
<a
name="998972"></a>    java.math.BigDecimal n = cstmt.getBigDecimal(2, 3);
</pre>
<code>

<p>CallableStatement</code> 与 <code>ResultSet</code> 
不同,它不提供用增量方式检索大 OUT 值的特殊机制。</p>

<p><a name="998974"></a> </p>

<h3>7.1.3 INOUT 参数</h3>

<p>既支持输入又接受输出的参数(INOUT 参数)除了调用 <code>registerOutParameter</code> 
方法外,还要求调用适当的 <code>setXXX</code> 方法(该方法是从 <code>PreparedStatement</code> 
继承来的)。<code>setXXX</code> 方法将参数值设置为输入参数,而 <code>registerOutParameter</code> 
方法将它的 JDBC 类型注册为输出参数。<code>setXXX</code> 方法提供一个 
Java 值,而驱动程序先把这个值转换为 JDBC 
值,然后将它送到数据库中。</p>

<p><a name="999089"></a>这种 IN 值的 JDBC 类型和提供给 <code>registerOutParameter</code> 
方法的 JDBC 类型应该相同。然后,要检索输出值,就要用对应的 <code>getXXX</code> 
方法。例如,Java 类型为 <code>byte</code> 的参数应该使用方法 <code>setByte</code> 
来赋输入值。应该给 <code>registerOutParameter</code> 提供类型为<code> 
TINYINT</code> 的 JDBC 类型,同时应使用 <code>getByte</code> 来检索输出值 
(第 <a href="mapping.doc.html#996857">8</a> 节“JDBC 和 Java 
类型之间的映射”将给出详细信息和类型映射表)。</p>

<p><a name="998976"></a>下例假设有一个已储存过程 <code>reviseTotal</code>,其唯一参数是 
INOUT 参数。方法 <code>setByte</code> 把此参数设为 <code>25</code>,驱动程序将把它作为 
JDBC <code>TINYINT</code> 类型送到数据库中。接着,<code>registerOutParameter</code> 
将该参数注册为 JDBC <code>TINYINT</code>。执行完该已储存过程后,将返回一个新的 
JDBC <code>TINYINT</code> 值。方法 <code>getByte</code> 将把这个新值作为 Java <code>byte</code> 
类型检索。</p>

<pre><a name="998977"></a>    CallableStatement cstmt = con.prepareCall(
<a name="998978"></a>        &quot;{call reviseTotal(?)}&quot;);
<a
name="998979"></a>    cstmt.setByte(1, 25);
<a name="998980"></a>    cstmt.registerOutParameter(1, java.sql.Types.TINYINT);
<a
name="998981"></a>    cstmt.executeUpdate();
<a name="998982"></a>    byte x = cstmt.getByte(1);
</pre>
<a name="998983"></a>
<h3>7.1.4 先检索结果,再检索 OUT 参数</h3>

<p>由于某些 DBMS 
的限制,为了实现最大的可移植性,建议先检索由执行 <code>CallableStatement</code> 
对象所产生的结果,然后再用 <code>CallableStatement.getXXX</code> 
方法来检索 OUT 参数。</p>

<p><a name="998985"></a>如果 <code>CallableStatement</code> 对象返回多个 <code>ResultSet</code> 
对象(通过调用 <code>execute</code> 方法),在检索 OUT 
参数前应先检索所有的结果。这种情况下,为确保对所有的结果都进行了访问,必须对 
<code>Statement</code> 方法 <code>getResultSet</code>、<code>getUpdateCount</code> 和 <code>getMoreResults</code> 
进行调用,直到不再有结果为止。</p>

<p><a name="998986"></a>检索完所有的结果后,就可用 <code>CallableStatement</code>.<code>getXXX</code> 
方法来检索 OUT 参数中的值。</p>

<p><a name="998987"></a> </p>

<h3>7.1.5 检索作为 OUT 参数的 NULL 值</h3>

<p>返回到 OUT 参数中的值可能会是 <code>JDBC</code> <code>NULL</code>。当出现这种情形时,将对 
<code>JDBC</code> <code>NULL</code> 值进行转换以使 <code>getXXX</code> 
方法所返回的值为 <code>null</code>、<code>0</code> 或 <code>false</code>,这取决于 
<code>getXXX</code> 方法类型。对于 <code>ResultSet</code> 对象,要知道 <code>0</code> 
或 <code>false</code> 是否源于 <code>JDBC</code> <code>NULL</code> 
的唯一方法,是用方法 <code>wasNull</code> 进行检测。如果 <code>getXXX</code> 
方法读取的最后一个值是 <code>JDBC</code> <code>NULL</code>,则该方法返回<code> 
true</code>,否则返回 <code>flase</code>。第 <a href="resultset.doc.html#1002724">5</a> 
节“ResultSet”将给出详细信息。</p>

<pre><a name="997998"></a>
</pre>

<p><br>
</p>

<hr>
<font size="-1"><a href="introTOC.doc.html">

<p>目录</a> | <a href="preparedstatement.doc.html">上一页</a> | <a
href="mapping.doc.html">下一页</a> </font></p>

<hr>

<address>
  <a href="mailto:jdbc@wombat.eng.sun.com">jdbc@wombat.eng.sun.com</a> 或 <a
  href="mailto:jdbc-odbc@wombat.eng.sun.com">jdbc-odbc@wombat.eng.sun.com</a> 
</address>
<a href="copyright.doc.html"><font size="-1"><i>

<p>版权所有 &copy; 1996, 1997 Sun Microsystems, Inc. 保留所有权利</i></font>。</a><!-- HTML generated by dkramer on March 14, 1997 --> 
</p>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -