📄 jdbc2.0.frame7.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="100%">
<tr>
<td><font size="-1"><a href="jdbc2.0.frame.html">目录</a> | <a
href="jdbc2.0.frame6.html">上一页</a> | <a href="jdbc2.0.frame8.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="285951"></a> </p>
<h2>7 对 Java 对象的持久性</h2>
<p>JDBC 1.0 API 提供了一些对存储 Java 对象和经由 <code>getObject()</code> 和
<code>setObject()</code> 机制从数据库检索 Java 对象的支持。JDBC 2.0 API
通过提供新型的元数据功能(可以使用元数据功能来检索对数据源所含
Java 对象的描述)从总体上增强了 JDBC 驱动程序实现 Java
对象持久性的能力。Java 类的实例可以作为可序列化的 Java
对象(或其它某种特定于厂商的格式)存储在数据库中。如果采用了对象序列化,则可以根据
Java 对象序列化所指定的规则处理对象之间的引用。</p>
<p><a name="297434"></a>本章所述的 JDBC 2.0 API 功能可支持新一代的能感知
Java 的数据库管理系统,称为 <em>Java 关系式 DBMS</em>。Java 关系式 DBMS
用 Java
对象类型扩展了数据库的类型系统,同时允许用户编写引用这些类型的查询。现在有几家数据库厂商正在创建具有
Java
关系式能力的产品。本章所述的各种机制是可选的。不支持本章所述功能的
JDBC 驱动程序不需要实现这些功能。</p>
<p><a name="293109"></a>让我们先看看典型的 Java 应用程序如何利用 JDBC API
来存储和检索 Java 对象。</p>
<p><a name="288718"></a> </p>
<h3>7.1 检索 Java 对象</h3>
<p>下例显示了利用 JDBC 如何检索对象。示例查询引用了 <code>PERSONNEL</code>
表,而表中包含了称为 <code>Employee</code> 的列,列中包含 Java 类 <code>Employee</code>
的实例。此处,列名 <code>Employee</code> 和 Java
类名相同,但是这并非是 JDBC 所要求的。事实上,由于目前引用 Java
类型的 SQL 查询没有公认的标准语法,所以 JDBC
并没有要求必须使用任何特定的查询语法。</p>
<p><a name="292868"></a> </p>
<blockquote>
<pre>ResultSet rs = stmt.executeQuery(
"SELECT Employee FROM PERSONNEL");
rs.next();
Employee emp = (Employee)rs.getObject(1);
</pre>
</blockquote>
<p><a name="288720"></a></p>
<p><a name="292884"></a>本例从 <code>PERSONNEL</code> 表中选择了所有的 <code>Employee</code>
实例。调用 <code>ResultSet.next() </code>方法将结果集定位到包含 <code>Employee</code>
的第一行。然后,示例应用程序通过调用 <code>ResultSet.getObject()</code>
获得 <code>Employee</code> 实例。这将导致 JDBC
驱动程序(或许是通过恢复序列化的对象实例)构造 <code>Employee</code>
类的实例,然后将实例作为 <code>java.lang.Object</code>
返回,而应用程序将其限定为 <code>Employee</code>。</p>
<p><a name="293026"></a>请注意:上例中没有包含对 JDBC 1.0 API
的增加部分,而只是可能需要一些 JDBC 未规定的扩展的 SQL
查询语法格式。另外,我们注意到以上所示的 JDBC
代码还可用来检索映射成 Java 类的 SQL
自定义类型的数据。稍后一章中我们将详细讨论这一点。</p>
<p><a name="288721"></a> </p>
<h3>7.2 存储 Java 对象</h3>
<p>下例说明了利用 JDBC 更新 Java
对象及使得对象的更新副本能持久的过程。</p>
<p><a name="293066"></a> </p>
<blockquote>
<pre>emp.setSalary(emp.getSalary() * 1.5);
PreparedStatement pstmt = con.preparedStatement(
"UPDATE PERSONNEL SET Employee = ? WHERE Employee.no = 1001");
pstmt.setObject(1, emp);
pstmt.executeUpdate();
</pre>
</blockquote>
<p><a name="293060"></a></p>
<p>下例给某雇员的工资上涨了 50% 。它首先调用 <code>Employee.setSalary()</code>
方法来更新该雇员的工资额。请注意:JDBC 并没有规定 <code>Employee</code>
类上的方法的语义。此处,我们假定 <code>Employee</code> 类是一般的
Java 类,因此调用 <code>Employee.setSalary() </code>只是改变 <code>Employee</code>
实例中某些私有数据域的值。例如,调用 <code>Employee.setSalary()</code>
并不会更新数据库,尽管另外一种替代实现可以做到这一点,实际上也就使数据库更新对于使用
<code>Employee</code> 类的应用程序成为“透明的”。</p>
<p><a name="293065"></a>接着,它将利用扩展的 SQL UPDATE
命令(本例中所用的查询语法也不是 JDBC 必需的)来创建 <code>PreparedStatement</code>
对象。UPDATE 命令表示要改变 <code>PERSONNEL</code> 表中指定行的 <code>Employee</code>
列。<code>PreparedStatement.setObject()</code> 的作用是将 <code>Employee</code>
对象传递给预先准备好的语句,而 <code>executeUpdate()</code>
方法更新存储在数据库中的 <code>Employee</code> 值。</p>
<p><a name="288788"></a>请再次注意:上例并没有涉及 JDBC 1.0 API
没有的语法增加部分。另外,如果要将 Employee 类映射到 SQL
自定义类型,仍可以使用与此相同的 JDBC 代码。</p>
<p><a name="297610"></a> </p>
<h3>7.3 附加元数据 </h3>
<p>JDBC 2.0 API
包含了一种新型的元数据支持,可以使应用程序获得对存储在数据源中的
Java 对象的完整描述。</p>
<p><a name="297533"></a> </p>
<h4>7.3.1 标识 Java 对象</h4>
<p>在 <code>java.sql.Types </code>中新增了一种类型代码 <code>JAVA_OBJECT</code>,可用来表示
Java 对象类型。<code>JAVA_OBJECT</code> 类型代码是由诸如 <code>DatabaseMetaData.getTypeInfo()
</code>和 <code>DatabaseMetaData.getColumns()</code> 的方法返回的。例如,如果
DBMS 支持是 Java 类的类型,则 <code>DatabaseMetaData.getTypeInfo()</code>
将返回包含有以下项的结果集: </p>
<p><a name="297535"></a>
<ul>
<li><a name="297536"></a><strong>TYPE_NAME</strong> String =>
特定于数据源的名称(可以为空) <a name="297537"></a></li>
<li><strong>DATA_TYPE</strong> short => java.sql.Types.JAVA_OBJECT</li>
<li>等等<a name="297539"></a> </li>
</ul>
<p>TYPE_NAME 列包含了 Java 对象的数据源特定的术语,例如“JavaObject”、“Serialized(序列化的)”等等。TYPE_NAME
可以为空。</p>
<p><a name="297551"></a> </p>
<h4>7.3.2 特定于检索架构的 Java 类型描述</h4>
<p>在用 Java 类来定义架构的表之前,通常用特定的数据库架构来注册
Java 类。可以通过调用 <code>DatabaseMetaData.getUDTs()</code>
方法来检索有关特定于架构的自定义类型(<code>JAVA_OBJECT</code>
类型是其中的一种)的信息。例如, </p>
<p><a name="297678"></a> </p>
<blockquote>
<pre><code>int[] types = {Types.JAVA_OBJECT};
ResultSet rs = dmd.getUDTs("catalog-name", "schema-name",
"%", types);
</code></pre>
</blockquote>
<p><a name="297557"></a></p>
<p><a name="297558"></a>将返回在 <code>catalog-name.schema- name </code>架构中<strong>定义的</strong>所有
Java 对象的描述。如果驱动程序不支持 UDT 或没有找到匹配的 UDT,则返回空结果集。</p>
<p><a name="297711"></a>每种类型描述都有以下几列: </p>
<p><a name="297584"></a> </p>
<table Border="0">
<tr>
<td><strong>TYPE_CAT </strong></td>
<td>String => 类型的目录(可以为空) </td>
</tr>
<tr>
<td><strong>TYPE_SCHEM </strong></td>
<td>String => 类型的架构(可以为空) </td>
</tr>
<tr>
<td><strong>TYPE_NAME </strong></td>
<td>String => 数据库类型名称 </td>
</tr>
<tr>
<td><strong>JAVA_CLASS </strong></td>
<td>String => Java 类名称 </td>
</tr>
<tr>
<td><strong>DATA_TYPE </strong></td>
<td>short =>在 <code>java.sql.Types</code> 中定义的数值,例如 JAVA_OBJECT </td>
</tr>
<tr>
<td><strong>REMARKS </strong></td>
<td>String => 类型的说明性注释 </td>
</tr>
</table>
<table>
<tr>
<td></td>
</tr>
</table>
<p><a name="297721"></a> </p>
<p><a name="297585"></a><strong>TYPE_CAT</strong>、<strong>TYPE_SCHEM</strong>、<strong>DATA_TYPE</strong>
和 <strong>REMARKS</strong> 各列应该是无需加以解释的。<strong>TYPE_NAME</strong>
实际上就是 SQL 类型名称。在 CREATE TABLE
语句中就使用该名称来指定这种类型的列。</p>
<p><a name="297586"></a>当 <strong>DATA_TYPE</strong> 是<code>JAVA_OBJECT</code>
时,则 <strong>JAVA_CLASS </strong>就是与 <strong>TYPE_NAME</strong> 相关联的
Java 类的全限定的 Java 类名。实际上存储在 <strong>TYPE_NAME</strong>
列中的所有值必须是该类或其子类的实例。当通过使用 JDBC
的应用程序从 <strong>TYPE_NAME</strong> 列中取出数值时,将由 JDBC
驱动程序实现该类或子类的实例。</p>
<p><a name="300789"></a><code>DatabaseMetaData.getUDTs()</code> 方法也接受 SQL
全限定名作为其第三个参数。这种情况下,将忽略目录和架构模式参数。SQL
全限定名可能包含通配符。例如,下列代码示例与前一例等同。</p>
<p><a name="300794"></a> </p>
<blockquote>
<pre><code>int[] types = {Types.JAVA_OBJECT};
ResultSet rs = dmd.getUDTs(null, null,
"catalog-name.schema-name.%", types);
</code>
</pre>
</blockquote>
<p><a name="300804"></a></p>
<p>此处,我们假设字符“.”是用来分隔全限定名的各组成元素。请注意全限定名的格式在数据库之间可能会有所不同,所以通常不能象上例一样对全限定名进行硬编码。<code>DatabaseMetaData</code>
接口提供了有关特定 JDBC 驱动程序所支持的全限定名格式的信息。</p>
<p><a name="297591"></a> </p>
<h4>7.3.3 检索 Java 类对象</h4>
<p>JDBC 2.0 API 没有为加载 Java 类文件(对应于存储在数据库中的 Java
对象)提供任何特殊的支持。JDBC 应用程序通过调用 <code>Class.forName()</code>
并且将类名作为参数传递,可以获得对应于数据库中的对象的类对象。换句话说,JDBC
2.0 API 假定存储在数据库中的对象的字节码是经由通用 Java
语言架构加载的。</p>
<p><a name="300148"></a> </p>
<p><a name="297646"></a> </p>
<p><br>
</p>
<hr>
<font size="-1"><a href="jdbc2.0.frame.html">
<p>目录</a> | <a href="jdbc2.0.frame6.html">上一页</a> | <a
href="jdbc2.0.frame8.html">下一页</a> </font></p>
<hr>
<address>
<a href="mailto:jdbc@eng.sun.com">jdbc@eng.sun.com</a> 或 <a
href="mailto:jdbc-business@eng.sun.com">jdbc-business@eng.sun.com</a>
</address>
<a href="../../../relnotes/SMICopyright.html"><font size="-1"><i>
<p>版权所有 © 1996, 1997 Sun Microsystems, Inc. 保留所有权利</i></font>。</a><!-- HTML generated by Suzette Pelouch on June 09, 1998 -->
</p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -