?? 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 + -