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

📄 preparedstatement.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="resultset.doc.html">上一页</a> 
    | <a href="callablestatement.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="999738"></a> </p>

<h1>6 - PreparedStatement</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="999746"></a> </p>

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

<h2>6.1&nbsp; 概述</h2>

<p>该 <code>PreparedStatement</code> 接口继承 <code>Statement</code>,并与之在两方面有所不同: 

<ol>
  <p><a name="999754"></a></p>
  <li><code>PreparedStatement</code> 实例包含已编译的 SQL 
    语句。这就是使语句“准备好”。<a name="999755"></a> </li>
  <li>包含于 <code>PreparedStatement</code> 对象中的 SQL 语句可具有一个或多个 
    IN 参数。IN 参数的值在 SQL 
    语句创建时未被指定。相反的,该语句为每个 IN 
    参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的 
    <code>setXXX</code> 方法来提供。</li>
</ol>

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

<p>由于 <code>PreparedStatement</code> 
对象已预编译过,所以其执行速度要快于 <code>Statement</code> 
对象。因此,多次执行的 SQL 语句经常创建为 <code>PreparedStatement</code> 
对象,以提高效率。</p>

<p>作为 <code>Statement</code> 的子类,<code>PreparedStatement</code> 继承了 <code>Statement</code> 
的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代 
IN 参数占位符的值。同时,三种方法 <code>execute</code>、 <code>executeQuery</code> 
和 <code>executeUpdate</code> 已被更改以使之不再需要参数。这些方法的<code> 
Statement</code> 形式(接受 SQL 语句参数的形式)不应该用于 <code>PreparedStatement</code> 
对象。</p>

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

<h3>6.1.1 创建 PreparedStatement 对象</h3>

<p>以下的代码段(其中 <code>con</code> 是 <code>Connection</code> 
对象)创建包含带两个 IN 参数占位符的 SQL 语句的 <code>PreparedStatement</code> 
对象: </p>

<pre><a name="999760"></a>    PreparedStatement pstmt = con.prepareStatement(
<a
name="999761"></a>        &quot;UPDATE table4 SET m = ? WHERE x = ?&quot;);
</pre>
<code>

<p>pstmt</code> 对象包含语句 <code>&quot;UPDATE table4 SET m = ? WHERE x = ?&quot;</code>,它已发送给 
DBMS,并为执行作好了准备。</p>

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

<h3>6.1.2 传递 IN 参数</h3>

<p>在执行 <code>PreparedStatement</code> 对象之前,必须设置每个 <code>?</code> 
参数的值。这可通过调用 <code>setXXX</code> 方法来完成,其中 <code>XXX</code> 
是与该参数相应的类型。例如,如果参数具有 Java 类型 <code>long</code>,则使用的方法就是 
<code>setLong</code>。<code>setXXX</code> 
方法的第一个参数是要设置的参数的<em>序数位置</em>,第二个参数是设置给该参数的<em>值</em>。例如,以下代码将第一个参数设为 
<code>123456789</code>,第二个参数设为 <code>100000000</code>: </p>

<pre><a name="999765"></a>    pstmt.setLong(1, 123456789);
<a name="999766"></a>    pstmt.setLong(2, 100000000);
</pre>

<p>一旦设置了给定语句的参数值,就可用它多次执行该语句,直到调用 
<code>clearParameters</code> 方法清除它为止。</p>

<p><a name="999768"></a>在连接的缺省模式下(启用自动提交),当语句完成时将自动提交或还原该语句。</p>

<p><a name="999769"></a>如果基本数据库和驱动程序在语句提交之后仍保持这些语句的打开状态,则同一个 
PreparedStatement 可执行多次。如果这一点不成立,那么试图通过使用 <code>PreparedStatement</code> 
对象代替 <code>Statement</code> 对象来提高性能是没有意义的。</p>

<p><a name="999770"></a>利用 <code>pstmt</code>(前面创建的 <code>PreparedStatement</code> 
对象),以下代码例示了如何设置两个参数占位符的值并执行 <code>pstmt</code> 
10 次。如上所述,为做到这一点,数据库不能关闭 <code>pstmt</code>。在该示例中,第一个参数被设置为 
<code>&quot;Hi&quot;</code>并保持为常数。在 <code>for</code> 
循环中,每次都将第二个参数设置为不同的值:从 <code>0</code> 
开始,到 <code>9</code> 结束。</p>

<pre><a name="999771"></a>    pstmt.setString(1, &quot;Hi&quot;);
<a name="999772"></a>    for (int i = 0; i &lt; 10; i++) {
<a
name="999773"></a>      pstmt.setInt(2, i);
<a name="999774"></a>      int rowCount = pstmt.executeUpdate();
<a
name="999775"></a>    }
</pre>
<a name="999776"></a>
<h3>6.1.3&nbsp; IN 参数中数据类型的一致性</h3>
<code>

<p>setXXX</code> 方法中的 <code>XXX</code> 是 Java 类型。它是一种隐含的 
JDBC 类型(一般 SQL 类型),因为驱动程序将把 Java 
类型映射为相应的 JDBC 类型(遵循该 <em>JDBC Guide</em>中§<a
href="mapping.doc.html#1004752">8.6.2</a> “映射 Java 和 JDBC 
类型”表中所指定的映射),并将该 JDBC 
类型发送给数据库。例如,以下代码段将 <code>PreparedStatement</code> 
对象 <code>pstmt</code> 的第二个参数设置为 <code>44</code>,Java 类型为 <code>short</code>: 
</p>

<pre><a name="999781"></a>    pstmt.setShort(2, 44);
</pre>

<p>驱动程序将 44 作为 JDBC <code>SMALLINT</code> 发送给数据库,它是 Java <code>short</code> 
类型的标准映射。</p>

<p><a name="999783"></a>程序员的责任是确保将每个 IN 参数的 Java 
类型映射为与数据库所需的 JDBC 数据类型兼容的 JDBC 
类型。不妨考虑数据库需要 JDBC <code>SMALLINT</code> 
的情况。如果使用方法 <code>setByte</code> ,则驱动程序将 JDBC <code>TINYINT</code> 
发送给数据库。这是可行的,因为许多数据库可从一种相关的类型转换为另一种类型,并且通常 
<code>TINYINT</code> 可用于 <code>SMALLINT</code> 
适用的任何地方。然而,对于要适用于尽可能多的数据库的应用程序,最好使用与数据库所需的确切的 
JDBC 类型相应的 Java 类型。如果所需的 JDBC 类型是 <code>SMALLINT</code>,则使用 
<code>setShort</code> 代替 <code>setByte</code> 
将使应用程序的可移植性更好。</p>

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

<h3>6.1.4 使用 setObject</h3>

<p>程序员可使用 <code>setObject</code> 
方法显式地将输入参数转换为特定的 JDBC 
类型。该方法可以接受第三个参数,用来指定目标 JDBC 类型。将 Java <code>Object</code> 
发送给数据库之前,驱动程序将把它转换为指定的 JDBC 类型。</p>

<p><a name="999787"></a>如果没有指定 JDBC 类型,驱动程序就会将 Java <code>Object</code> 
映射到其缺省的 JDBC 类型(参见第 <a href="mapping.doc.html#1004830">8.6.4</a> 
节中的表格),然后将它发送到数据库。这与常规的 <code>setXXX</code> 
方法类似;在这两种情况下,驱动程序在将值发送到数据库之前,会将该值的 
Java 类型映射为适当的 JDBC 类型。二者的差别在于 <code>setXXX</code> 
方法使用从 Java 类型到 JDBC 类型的标准映射(参见第 <a
href="mapping.doc.html#1004752">8.6.2</a> 节中的表格),而 <code>setObject</code> 
方法使用从 Java <code>Object</code> 类型到 JDBC 类型的映射(参见第 <a
href="mapping.doc.html#1004830">8.6.4</a> 节中的表格)。</p>

<p><a name="999798"></a>方法 <code>setObject</code> 允许接受所有 Java 
对象的能力使应用程序更为通用,并可在运行时接受参数的输入。这种情况下,应用程序在编译时并不清楚输入类型。通过使用 
<code>setObject</code>,应用程序可接受所有 Java 
对象类型作为输入,并将其转换为数据库所需的 JDBC 类型。第 <a
href="mapping.doc.html#1004845">8.6.5</a> 节中的表格显示了 <code>setObject</code> 
可执行的所有可能转换。</p>

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

<h3>6.1.5 将 JDBC NULL 作为 IN 参数发送</h3>
<code>

<p>setNull</code> 方法允许程序员将 JDBC <code>NULL</code> 值作为 IN 
参数发送给数据库。但要注意,仍然必须指定参数的 JDBC 类型。</p>

<p><a name="999804"></a>当把 Java <code>null</code> 值传递给 <code>setXXX</code> 
方法时(如果它接受 Java 对象作为参数),也将同样把 JDBC <code>NULL</code> 
发送到数据库。但仅当指定 JDBC 类型时,方法 <code>setObject</code> 
才能接受 <code>null</code> 值。</p>

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

<h3>6.1.6 发送大的 IN 参数</h3>
<code>

<p>setBytes</code> 和 <code>setString</code> 
方法能够发送无限量的数据。但是,有时程序员更喜欢用较小的块传递大型的数据。这可通过将 
IN 参数设置为 Java 输入流来完成。当语句执行时,JDBC 
驱动程序将重复调用该输入流,读取其内容并将它们当作实际参数数据传输。</p>

<p>JDBC 提供了三种将 IN 参数设置为输入流的方法:<code>setBinaryStream</code> 
用于含有未说明字节的流, <code>setAsciiStream</code> 用于含有 ASCII 
字符的流,而 <code>setUnicodeStream</code> 用于含有 Unicode 
字符的流。因为必须指定流的总长度,所以这些方法所采用的参数比其它的 
<code>setXXX</code> 
方法要多一个。这很有必要,因为一些数据库在发送数据之前需要知道其总的传送大小。</p>

<p><a name="999808"></a>以下代码例示了使用流作为 IN 
参数来发送文件内容: </p>

<pre><a name="999809"></a>    java.io.File file = new java.io.File(&quot;/tmp/data&quot;);
<a
name="999810"></a>    int fileLength = file.length();
<a name="999811"></a>    java.io.InputStream fin = new java.io.FileInputStream(file);
<a
name="999812"></a>    java.sql.PreparedStatement pstmt = con.prepareStatement(
<a
name="999813"></a>      &quot;UPDATE Table5 SET stuff = ? WHERE index = 4&quot;);
<a
name="999814"></a>    pstmt.setBinaryStream (1, fin, fileLength);
<a name="999815"></a>    pstmt.executeUpdate();
</pre>

<p>当语句执行时,将反复调用输入流 <code>fin</code> 以传递其数据。</p>

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

<p><br>
</p>

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

<p>目录</a> | <a href="resultset.doc.html">上一页</a> | <a
href="callablestatement.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 + -