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

📄 jdbc2.0.frame5.html

📁 JDBC的学习文档
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<p><a name="287742"></a>通过调用 <code>ResultSet.next()</code> 
方法可以向前遍历结果集,这与 JDBC 1.0 API 
中一样。另外,可滚动的结果集 — 
其类型不是只向前类型的任何结果集 — 实现了方法 <code>beforeFirst()</code>。调用该方法可以将光标定位到结果集中第一行之前。</p>

<p><a name="287782"></a>下例将光标定位到第一行之前,然后向前遍历结果集的内容。本例使用 
<code>getXXX()</code> 方法(属于 JDBC 1.0 API 方法)来检索列值。</p>

<blockquote>
  <pre>
rs.beforeFirst();
while ( rs.next()) {
	System.out.println(rs.getString(&quot;emp_no&quot;) +
			   &quot; &quot; + rs.getFloat(&quot;salary&quot;));
}
</pre>
</blockquote>

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

<p><a name="287750"></a>当然,也可以向后遍历可滚动的结果集,如下所示。</p>

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

<blockquote>
  <pre>rs.afterLast();
while (rs.previous()) {
	System.out.println(rs.getString(&quot;emp_no&quot;) +
		&quot; &quot; + rs.getFloat(&quot;salary&quot;));
}

</pre>
</blockquote>

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

<p>在本例中, <code>ResultSet.afterLast()</code> 
方法将可滚动结果集的光标定位到结果集中最后一行的后面。本例调用 
<code>ResultSet.previous()</code> 
方法将光标移动到最后一行,然后移动到倒数第二行,依此类推。当再没有其它行时,<code>ResultSet.previous() 
</code>返回 <code>false</code>。这样,在访问了所有行之后循环即终止。</p>

<p><a name="287759"></a>在分析了 <code>ResultSet</code> 
接口之后,读者无疑将认识到有多种方式可以遍历可滚动结果集的各行。然而,小心一些还是值得的,如下例所示。下例显示了一种不正确的方式。</p>

<blockquote>
  <pre>
// 不正确!!!
while (!rs.isAfterLast()) {
	rs.relative(1);
	System.out.println(rs.getString(&quot;emp_no&quot;) +
		 &quot; &quot; + rs.getFloat(&quot;salary&quot;));
}


</pre>
</blockquote>

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

<p>本例试图向前遍历可滚动结果集。之所以不正确的原因有几个:一个错误是如果在结果集为空时调用 
<code>ResultSet.isAfterLast()</code>。因为没有最后一行,所以它将返回假值,并且执行循环体, 
而这不是所需结果。当光标定位在包含有数据的结果集的第一行之前时,还会出现另外的问题。这种情况下,由于没有当前行,调用 
<code>rs.relative(1)</code> 就是错误的。</p>

<p><a name="287769"></a>以下的代码示例解决了上例中的问题。本例中通过调用 
<code>ResultSet.first() </code>来区别空结果集和包含数据的结果集这两种情况。由于仅在结果集非空时才调用 
<code>ResultSet.isAfterLast()</code>,所以循环控制能正确地工作。同时,由于 
<code>ResultSet.first()</code> 最初将光标定位到第一行,所以 <code>ResultSet.relative(1)</code> 
将步进地经过结果集的各行。</p>

<blockquote>
  <pre>if (rs.first()) {
	while (!rs.isAfterLast()) {
		System.out.println(rs.getString(&quot;emp_no&quot;) +
			&quot; &quot; + rs.getFloat(&quot;salary&quot;));
	    	rs.relative(1);
	}
}
</pre>
</blockquote>

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

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

<h3>5.8 检测和查看变化</h3>

<p>迄今为止,我们已经介绍了不同的结果集类型且列出了一些有关如何创建、更新及遍历特定类型结果集的实例。本节将详细描述结果集类型之间的差异,同时介绍这些差异对使用结果集的应用程序的意义。</p>

<p><a name="300946"></a>JDBC 2.0 API 
提供了三种不同的结果集类型:只向前类型、滚动不敏感类型和滚动敏感类型。这三种类型在使基本数据的变化对应用程序可见的能力上差异很大。结果集的这方面功能对于支持可滚动性的结果集类型特别有用,因为这些结果集类型允许在结果集打开时多次访问特定行。</p>

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

<h4>5.8.1 变化的可见性</h4>

<p>我们以描述在事务处理层变化的可见性来开始讨论本主题。首先,请注意表面上很明显的事实,即事务处理所作的所有更新对其自身都是可见的。然而,其它事务处理所作的变化(更新、插入和删除)对某个事务处理是否可见则由事务处理隔离层来确定。要设置事务处理的隔离层,可调用 
</p>

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

<blockquote>
  <pre>con.setTransactionIsolation(TRANSACTION_READ_COMMITTED);


</pre>
</blockquote>

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

<p>其中的变量 <code>con</code> 具有类型 <code>Connection</code>。如果系统中的所有事务处理在 
TRANSACTION_READ_COMMITTED 
隔离层或更高隔离层上执行,则事务处理只能看到其它事务处理已提交的变化。在结果集打开时对包含结果集的事务处理可见的变化总是通过结果集可见。事实上,这就是一个事务处理所作更新对另外一个事务处理可见的含义。</p>

<p><a name="300954"></a>但是,当结果集打开时所作变化又如何呢?能否用某种方式(例如调用 
<code>ResultSet.getXXX()</code>)使这些变化通过结果集中可见? 
当结果集处于打开状态时,特定结果集是否会暴露由其它事务处理或属于同一个事务处理的其它结果集对其基本数据所作的变化(我们将这两种变化总称为“它方的变化”)以及由其自身对基本数据所作的变化将取决于结果集类型。</p>

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

<h4>5.8.2 它方的变化</h4>

<p>打开滚动不敏感的结果集后,滚动不敏感结果集就不会让它方(其它事务处理和同一个事务处理中的其它结果集)所作的任何变化可见。滚动不敏感结果集的内容相对于它方所作变化是静态的 
成员、顺序和行值都是固定的。例如,如果另外一个事务处理(在结果集打开时)删除了包含在静态结果集中的某行,则该行仍将保持可见。实现滚动不敏感结果集的一种方法是创建结果集数据的私有副本。</p>

<p><a name="300957"></a>滚动敏感结果集恰恰相反。滚动敏感结果集使得<strong>它方</strong>作出的所有更新(这些更新对包含它的事务处理可见)成为可见。然而,插入和删除可能不可见。</p>

<p><a name="301617"></a>让我们仔细定义一下更新可见的含义。如果另外一个事务处理所作的更新影响了某行在结果集中的出现位置删除之后再插入就会出现这种情况,则直到重新打开结果集时才能移动该行。如果某更新使得某行不再是结果集中的成员删除时就是这样,则该行将保持可见,直到重新打开结果集。如果另外一个事务处理显式地删除了某行,则滚动敏感结果集可以为该行保留一个占位符以允许通过绝对位置来逻辑地取出行。然而,更新的列值总是可见的。</p>

<p><a name="301665"></a><code>DatabaseMetaData</code> 
接口提供了确定结果集所支持的确切功能的途径。例如,可以利用新方法:<code>othersUpdatesAreVisible 
</code>、<code>othersDeletesAreVisible</code> 和 <code>othersInsertsAreVisible</code> 
达到这一目的。</p>

<p><a name="301666"></a>只向前结果集实际上是滚动不敏感结果集或滚动敏感结果集(这取决于 
DBMS 如何评估生成结果集的查询)的退化形式。大多数 DBMS 
对某些查询具有递增地实现查询结果的能力。如果查询结果是递增实现的,则实际上不会检索数据值(直到需要从 
DBMS 
检索数据值时才检索),因而结果集的行为类似于敏感的结果集。然而,对于另外一些查询,递增实现是不可能的。例如,如果结果集是排过序的,则在 
DBMS 
将结果集的第一行返回到应用程序之前,需要先生成整个结果集。在这种情况下,只向前结果集的行为就类似于不敏感的结果集。</p>

<p><a name="301667"></a>对于 <code>TYPE_FORWARD_ONLY</code> 结果集, <code>othersUpdatesAreVisible</code>、<code>othersDeletesAreVisible 
</code>和 <code>othersInsertsAreVisible </code>方法可以确定在 DBMS 
逐渐递增地实现结果集时插入、更新和删除是否可见。如果一次查询的结果是排过序的,则即使以上方法返回的值为真,也不可能进行递增实现而且变化也不可见。</p>

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

<h4>5.8.3 结果集自身的变化</h4>

<p>我们已经指出:由它方作出的变化的可见性通常取决于结果集的类型。与打开的结果集中的变化的可见性有关的最后一点即结果集能否看见自身的变化(插入、更新和删除)。JDBC 
应用程序通过调用以下 <code>DatabaseMetaData </code>方法可以确定结果集所作变化是否对结果集自身可见:<code>ownUpdatesAreVisible</code>、<code>ownDeletesAreVisible</code> 
和 <code>ownInsertsAreVisible</code>。因为这种能力在 DBMS 和 JDBC 
驱动程序之间可能是不同的,所以需要使用以上这些方法。</p>

<p>如果通过在调用 <code>updateXXX()</code> 之后调用 <code>getXXX()</code> 
可以检索到更新的列值,则结果集自身的更新就是可见的。如果在调用 
<code>updateXXX()</code> 之后,<code>getXXX()</code> 
仍然返回最初的列值,则更新就是<strong>不</strong>可见的。同样,如果插入行在调用 
<code>insertRow()</code> 
之后出现在结果集中,则插入行就是可见的。如果插入行在调用 <code>insertRow()</code> 
之后没有立即出现在结果集中(没有关闭结果集或重新打开结果集),则插入行就是不可见的。如果被删除的行不是从结果集中被去掉就是在结果集中留下一个<em>洞</em>,则删除即是可见的。</p>

<p><a name="300965"></a>下例说明了应用程序如何确定 <code>TYPE_SCROLL_SENSITIVE</code> 
结果集能否看见自身的更新。</p>

<blockquote>
  <pre>DatabaseMetaData dmd;
...
if (dmd.<code>ownUpdatesAreVisible</code>(ResultSet.TYPE_SCROLL_INSENSITIVE))
{
	// 变化是可见的
}
</pre>
</blockquote>

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

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

<h4>5.8.4 检测变化</h4>

<p>可以调用 <code>ResultSet.wasUpdated()</code>、<code>wasDeleted()</code> 和 <code>wasInserted()</code> 
方法来分别确定结果集打开以来某行是否受了可见的更新、删除或插入的影响。结果集检测变化的能力与让变化可见的能力互不相关。换句话说,对可见变化的检测并不是自动进行的。</p>

<p><a name="300988"></a><code>DatabaseMetaData</code> 
接口所提供的方法可使应用程序确定某 JDBC 
驱动程序是否能为特定结果集类型检测变化。例如, </p>

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

<blockquote>
  <pre>boolean bool = dmd.deletesAreDetected(
	ResultSet.TYPE_SCROLL_SENSITIVE);
</pre>
</blockquote>

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

<p><a name="300996"></a>如果 deletesAreDetected 返回 <code>true</code>,则可以使用 
<code>ResultSet.wasDeleted() </code>来检测 <code>TYPE_SCROLL_SENSITIVE</code> 
结果集中的“洞”。</p>

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

<h3>5.9 重新取出行</h3>

<p>一些应用程序可能需要查看对行所作出的变化。因为 JDBC 
驱动程序可以预取并高速缓存从基本数据库读出的数据(参见 <code>ResultSet.setFetchSize()</code>),所以应用程序可能看不见对行作出的最新变化,即使采用敏感的结果集且更新可见。<code>ResultSet.refreshRow()</code> 
方法的作用是允许应用程序请求某驱动程序用存储在数据库中的最新数值来刷新某行。如果所取出的尺寸大小大于一行,则 
JDBC 驱动程序实际上可以一次刷新多行。应用程序应该尽量限制对 <code>refreshRow() 
</code>的调用,因为频繁调用该方法可能会降低性能。</p>

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

<h3>5.10 JDBC 灵活性</h3>

<p>尽管我们希望大多数 JDBC 
驱动程序能够支持可滚动结果集,但是我们将这种支持设置成是可选的,从而将为不支持可滚动性的数据源实现 
JDBC 驱动程序的复杂性降到最小。这样做的目的是使 JDBC 
驱动程序可能利用基本数据库系统所提供的支持来为具有这种支持的系统实现可滚动结果集。如果与驱动程序相关联的 
DBMS 并不支持可滚动性,则可忽略该功能。JDBC 驱动程序也可以作为 
DBMS 上面的一层来实现可滚动性。值得注意的是:JDBC 行集合(属于 
JDBC 标准扩展 API 的一部分)总是支持可滚动性,因此当基本 DBMS 
不支持可滚动结果集时可以使用行集合。</p>

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

<p><br>
</p>

<hr>
<font size="-1"><a href="jdbc2.0.frame.html">

<p>目录</a> | <a href="jdbc2.0.frame4.html">上一页</a> | <a
href="jdbc2.0.frame6.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>版权所有 &copy; 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 + -