mirror of
https://github.com/berkeleydb/je.git
synced 2024-11-15 01:46:24 +00:00
692 lines
25 KiB
HTML
692 lines
25 KiB
HTML
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|||
|
<title>Getting Records Using the Cursor</title>
|
|||
|
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
|||
|
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
|
|||
|
<link rel="start" href="index.html" title="Getting Started with Berkeley DB Java Edition" />
|
|||
|
<link rel="up" href="Cursors.html" title="Chapter 9. Using Cursors" />
|
|||
|
<link rel="prev" href="Cursors.html" title="Chapter 9. Using Cursors" />
|
|||
|
<link rel="next" href="PutEntryWCursor.html" title="Putting Records Using Cursors" />
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
<div xmlns="" class="navheader">
|
|||
|
<div class="libver">
|
|||
|
<p>Library Version 12.2.7.5</p>
|
|||
|
</div>
|
|||
|
<table width="100%" summary="Navigation header">
|
|||
|
<tr>
|
|||
|
<th colspan="3" align="center">Getting Records Using the Cursor</th>
|
|||
|
</tr>
|
|||
|
<tr>
|
|||
|
<td width="20%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td>
|
|||
|
<th width="60%" align="center">Chapter 9. Using Cursors</th>
|
|||
|
<td width="20%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td>
|
|||
|
</tr>
|
|||
|
</table>
|
|||
|
<hr />
|
|||
|
</div>
|
|||
|
<div class="sect1" lang="en" xml:lang="en">
|
|||
|
<div class="titlepage">
|
|||
|
<div>
|
|||
|
<div>
|
|||
|
<h2 class="title" style="clear: both"><a id="Positioning"></a>Getting Records Using the Cursor</h2>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="toc">
|
|||
|
<dl>
|
|||
|
<dt>
|
|||
|
<span class="sect2">
|
|||
|
<a href="Positioning.html#diskorderedcursors">Disk Ordered Cursors</a>
|
|||
|
</span>
|
|||
|
</dt>
|
|||
|
<dt>
|
|||
|
<span class="sect2">
|
|||
|
<a href="Positioning.html#cursorsearch">Searching for Records</a>
|
|||
|
</span>
|
|||
|
</dt>
|
|||
|
<dt>
|
|||
|
<span class="sect2">
|
|||
|
<a href="Positioning.html#getdups">Working with Duplicate Records</a>
|
|||
|
</span>
|
|||
|
</dt>
|
|||
|
</dl>
|
|||
|
</div>
|
|||
|
<p>
|
|||
|
To iterate over database records, from the first record to
|
|||
|
the last, simply open the cursor and then use the
|
|||
|
<code class="methodname">Cursor.getNext()</code>
|
|||
|
|
|||
|
|
|||
|
method.
|
|||
|
|
|||
|
For example:
|
|||
|
</p>
|
|||
|
<a id="je_cursor3"></a>
|
|||
|
<pre class="programlisting">package je.gettingStarted;
|
|||
|
|
|||
|
import com.sleepycat.je.Cursor;
|
|||
|
import com.sleepycat.je.Database;
|
|||
|
import com.sleepycat.je.DatabaseEntry;
|
|||
|
import com.sleepycat.je.DatabaseException;
|
|||
|
import com.sleepycat.je.LockMode;
|
|||
|
import com.sleepycat.je.OperationStatus;
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
Cursor cursor = null;
|
|||
|
try {
|
|||
|
...
|
|||
|
// Database and environment open omitted for brevity
|
|||
|
...
|
|||
|
|
|||
|
// Open the cursor.
|
|||
|
cursor = myDatabase.openCursor(null, null);
|
|||
|
|
|||
|
// Cursors need a pair of DatabaseEntry objects to operate. These hold
|
|||
|
// the key and data found at any given position in the database.
|
|||
|
DatabaseEntry foundKey = new DatabaseEntry();
|
|||
|
DatabaseEntry foundData = new DatabaseEntry();
|
|||
|
|
|||
|
// To iterate, just call getNext() until the last database record has
|
|||
|
// been read. All cursor operations return an OperationStatus, so just
|
|||
|
// read until we no longer see OperationStatus.SUCCESS
|
|||
|
while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==
|
|||
|
OperationStatus.SUCCESS) {
|
|||
|
// getData() on the DatabaseEntry objects returns the byte array
|
|||
|
// held by that object. We use this to get a String value. If the
|
|||
|
// DatabaseEntry held a byte array representation of some other
|
|||
|
// data type (such as a complex object) then this operation would
|
|||
|
// look considerably different.
|
|||
|
String keyString = new String(foundKey.getData(), "UTF-8");
|
|||
|
String dataString = new String(foundData.getData(), "UTF-8");
|
|||
|
System.out.println("Key | Data : " + keyString + " | " +
|
|||
|
dataString + "");
|
|||
|
}
|
|||
|
} catch (DatabaseException de) {
|
|||
|
System.err.println("Error accessing database." + de);
|
|||
|
} finally {
|
|||
|
// Cursors must be closed.
|
|||
|
cursor.close();
|
|||
|
}</pre>
|
|||
|
<p>
|
|||
|
To iterate over the database from the last record to the first,
|
|||
|
instantiate the cursor, and then
|
|||
|
use <code class="methodname">Cursor.getPrev()</code> until you read the first record in
|
|||
|
the database. For example:
|
|||
|
</p>
|
|||
|
<a id="je_cursor4"></a>
|
|||
|
<pre class="programlisting">package je.gettingStarted;
|
|||
|
|
|||
|
import com.sleepycat.je.Cursor;
|
|||
|
import com.sleepycat.je.Database;
|
|||
|
import com.sleepycat.je.DatabaseEntry;
|
|||
|
import com.sleepycat.je.DatabaseException;
|
|||
|
import com.sleepycat.je.LockMode;
|
|||
|
import com.sleepycat.je.OperationStatus;
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
Cursor cursor = null;
|
|||
|
try {
|
|||
|
...
|
|||
|
// Database and environment open omitted for brevity
|
|||
|
...
|
|||
|
|
|||
|
// Open the cursor.
|
|||
|
cursor = myDatabase.openCursor(null, null);
|
|||
|
|
|||
|
// Get the DatabaseEntry objects that the cursor will use.
|
|||
|
DatabaseEntry foundKey = new DatabaseEntry();
|
|||
|
DatabaseEntry foundData = new DatabaseEntry();
|
|||
|
|
|||
|
// Iterate from the last record to the first in the database
|
|||
|
while (cursor.getPrev(foundKey, foundData, LockMode.DEFAULT) ==
|
|||
|
OperationStatus.SUCCESS) {
|
|||
|
|
|||
|
String theKey = new String(foundKey.getData(), "UTF-8");
|
|||
|
String theData = new String(foundData.getData(), "UTF-8");
|
|||
|
System.out.println("Key | Data : " + theKey + " | " +
|
|||
|
theData + "");
|
|||
|
}
|
|||
|
} catch (DatabaseException de) {
|
|||
|
System.err.println("Error accessing database." + de);
|
|||
|
} finally {
|
|||
|
// Cursors must be closed.
|
|||
|
cursor.close();
|
|||
|
}</pre>
|
|||
|
<div class="sect2" lang="en" xml:lang="en">
|
|||
|
<div class="titlepage">
|
|||
|
<div>
|
|||
|
<div>
|
|||
|
<h3 class="title"><a id="diskorderedcursors"></a>Disk Ordered Cursors</h3>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<p>
|
|||
|
The previous example shows how to scan through the records in
|
|||
|
your database sequentially; that is, in the record's sort order.
|
|||
|
This is mostly determined by the value contained in the records' keys
|
|||
|
(additional sorting is required in the case of duplicate
|
|||
|
records). However, you can use cursors to retrieve records based
|
|||
|
on how they are stored on disk. This can improve retrieval times,
|
|||
|
and is useful if your application needs to scan all the records
|
|||
|
in the database quickly, without concern for key sort order.
|
|||
|
You do this using the <code class="classname">DiskOrderedCursor</code>
|
|||
|
class.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
<code class="classname">DiskOrderedClass</code> works in the same way as
|
|||
|
a regular cusor: you simply open the cursor, then retrieve
|
|||
|
records one after another using the
|
|||
|
<code class="methodname">DiskOrderedClass.getNext()</code>
|
|||
|
method.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
You open a <code class="classname">DiskOrderedCursor</code>
|
|||
|
using the <code class="methodname">Database.openCursor()</code>
|
|||
|
method. This version of the method takes a single parameter: an
|
|||
|
instance of the
|
|||
|
<code class="classname">DiskOrderedCursorConfig</code>
|
|||
|
class, which can be used to configure various aspects of the
|
|||
|
<code class="classname">DiskOrderedCursor</code>
|
|||
|
class.
|
|||
|
</p>
|
|||
|
<a id="je_diskorderedcursor1"></a>
|
|||
|
<pre class="programlisting">package je.gettingStarted;
|
|||
|
|
|||
|
import com.sleepycat.je.Database;
|
|||
|
import com.sleepycat.je.DatabaseEntry;
|
|||
|
import com.sleepycat.je.DatabaseException;
|
|||
|
import com.sleepycat.je.DiskOrderedCursor;
|
|||
|
import com.sleepycat.je.DiskOrderedCursorConfig;
|
|||
|
import com.sleepycat.je.LockMode;
|
|||
|
import com.sleepycat.je.OperationStatus;
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
DiskOrderedCursor dcursor = null;
|
|||
|
DiskOrderedCursorConfig docc = new DiskOrderedCursorConfig();
|
|||
|
try {
|
|||
|
...
|
|||
|
// Database and environment open omitted for brevity
|
|||
|
...
|
|||
|
|
|||
|
// Open the cursor.
|
|||
|
dcursor = myDatabase.openCursor(docc);
|
|||
|
|
|||
|
// Cursors need a pair of DatabaseEntry objects to operate. These hold
|
|||
|
// the key and data found at any given position in the database.
|
|||
|
DatabaseEntry foundKey = new DatabaseEntry();
|
|||
|
DatabaseEntry foundData = new DatabaseEntry();
|
|||
|
|
|||
|
// To iterate, just call getNext() until the last database record has
|
|||
|
// been read. All cursor operations return an OperationStatus, so just
|
|||
|
// read until we no longer see OperationStatus.SUCCESS
|
|||
|
while (dcursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==
|
|||
|
OperationStatus.SUCCESS) {
|
|||
|
// getData() on the DatabaseEntry objects returns the byte array
|
|||
|
// held by that object. We use this to get a String value. If the
|
|||
|
// DatabaseEntry held a byte array representation of some other
|
|||
|
// data type (such as a complex object) then this operation would
|
|||
|
// look considerably different.
|
|||
|
String keyString = new String(foundKey.getData(), "UTF-8");
|
|||
|
String dataString = new String(foundData.getData(), "UTF-8");
|
|||
|
System.out.println("Key | Data : " + keyString + " | " +
|
|||
|
dataString + "");
|
|||
|
}
|
|||
|
} catch (DatabaseException de) {
|
|||
|
System.err.println("Error accessing database." + de);
|
|||
|
} finally {
|
|||
|
// Cursors must be closed.
|
|||
|
cursor.close();
|
|||
|
}</pre>
|
|||
|
</div>
|
|||
|
<div class="sect2" lang="en" xml:lang="en">
|
|||
|
<div class="titlepage">
|
|||
|
<div>
|
|||
|
<div>
|
|||
|
<h3 class="title"><a id="cursorsearch"></a>Searching for Records</h3>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<p>
|
|||
|
You can use cursors to search for database records. You can search based
|
|||
|
on just a key, or you can search based on both the key and the data.
|
|||
|
You can also perform partial matches if your database supports sorted
|
|||
|
duplicate sets. In all cases, the key and data parameters of these
|
|||
|
methods are filled with the key and data values of the database record
|
|||
|
to which the cursor is positioned as a result of the search.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Also, if the search fails, then cursor's state is left unchanged
|
|||
|
and
|
|||
|
<code class="literal">OperationStatus.NOTFOUND</code>
|
|||
|
|
|||
|
is returned.
|
|||
|
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
The following <code class="classname">Cursor</code> methods allow you to
|
|||
|
perform database searches:
|
|||
|
</p>
|
|||
|
<div class="itemizedlist">
|
|||
|
<ul type="disc">
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<code class="methodname">Cursor.getSearchKey()</code>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Moves the cursor to the first record in the database with
|
|||
|
the specified key.
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<code class="methodname">Cursor.getSearchKeyRange()</code>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
|
|||
|
<span>Moves the cursor</span>
|
|||
|
|
|||
|
to the first record in the database whose
|
|||
|
key is greater than or equal to the specified key. This comparison
|
|||
|
is determined by the
|
|||
|
<span>comparator</span>
|
|||
|
|
|||
|
that you provide for the database. If no
|
|||
|
<span>comparator</span>
|
|||
|
|
|||
|
is provided, then the default
|
|||
|
<span> unsigned byte-by-byte </span>
|
|||
|
lexicographical sorting is used.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
For example, suppose you have database records that use the
|
|||
|
following
|
|||
|
<span>Strings</span>
|
|||
|
|
|||
|
as keys:
|
|||
|
</p>
|
|||
|
<pre class="programlisting">Alabama
|
|||
|
Alaska
|
|||
|
Arizona</pre>
|
|||
|
<p>
|
|||
|
Then providing a search key of <code class="literal">Alaska</code> moves the
|
|||
|
cursor to the second key noted above. Providing a key of
|
|||
|
<code class="literal">Al</code> moves the cursor to the first key (<code class="literal">Alabama</code>), providing
|
|||
|
a search key of <code class="literal">Alas</code> moves the cursor to the second key
|
|||
|
(<code class="literal">Alaska</code>), and providing a key of <code class="literal">Ar</code> moves the
|
|||
|
cursor to the last key (<code class="literal">Arizona</code>).
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<code class="methodname">Cursor.getSearchBoth()</code>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Moves the cursor to the first record in the database that uses
|
|||
|
the specified key and data.
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<code class="methodname">Cursor.getSearchBothRange()</code>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Moves the cursor to the first record in the database whose key matches the specified
|
|||
|
key and whose data is
|
|||
|
greater than or equal to the specified data. If the database supports
|
|||
|
duplicate records, then on matching the key, the cursor is moved to
|
|||
|
the duplicate record with the smallest data that is greater than or
|
|||
|
equal to the specified data.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
For example,
|
|||
|
<span>suppose you have</span>
|
|||
|
|
|||
|
database records that use the following key/data pairs:
|
|||
|
</p>
|
|||
|
<pre class="programlisting">Alabama/Athens
|
|||
|
Alabama/Florence
|
|||
|
Alaska/Anchorage
|
|||
|
Alaska/Fairbanks
|
|||
|
Arizona/Avondale
|
|||
|
Arizona/Florence </pre>
|
|||
|
<p>then providing:</p>
|
|||
|
<div class="informaltable">
|
|||
|
<table border="1" width="80%">
|
|||
|
<colgroup>
|
|||
|
<col />
|
|||
|
<col />
|
|||
|
<col />
|
|||
|
</colgroup>
|
|||
|
<thead>
|
|||
|
<tr>
|
|||
|
<th>a search key of ...</th>
|
|||
|
<th>and a search data of ...</th>
|
|||
|
<th>moves the cursor to ...</th>
|
|||
|
</tr>
|
|||
|
</thead>
|
|||
|
<tbody>
|
|||
|
<tr>
|
|||
|
<td>Alaska</td>
|
|||
|
<td>Fa</td>
|
|||
|
<td>Alaska/Fairbanks</td>
|
|||
|
</tr>
|
|||
|
<tr>
|
|||
|
<td>Arizona</td>
|
|||
|
<td>Fl</td>
|
|||
|
<td>Arizona/Florence</td>
|
|||
|
</tr>
|
|||
|
<tr>
|
|||
|
<td>Alaska</td>
|
|||
|
<td>An</td>
|
|||
|
<td>Alaska/Anchorage</td>
|
|||
|
</tr>
|
|||
|
</tbody>
|
|||
|
</table>
|
|||
|
</div>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<p>
|
|||
|
For example, assuming a database containing sorted duplicate records of
|
|||
|
U.S. States/U.S Cities key/data pairs (both as
|
|||
|
<span>Strings),</span>
|
|||
|
|
|||
|
then the following code fragment can be used to position the cursor
|
|||
|
to any record in the database and print its key/data values:
|
|||
|
<span>
|
|||
|
|
|||
|
</span>
|
|||
|
</p>
|
|||
|
<a id="je_cursor5"></a>
|
|||
|
<pre class="programlisting">package je.gettingStarted;
|
|||
|
|
|||
|
import com.sleepycat.je.Cursor;
|
|||
|
import com.sleepycat.je.Database;
|
|||
|
import com.sleepycat.je.DatabaseEntry;
|
|||
|
import com.sleepycat.je.DatabaseException;
|
|||
|
import com.sleepycat.je.LockMode;
|
|||
|
import com.sleepycat.je.OperationStatus;
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
// For this example, hard code the search key and data
|
|||
|
String searchKey = "Alaska";
|
|||
|
String searchData = "Fa";
|
|||
|
|
|||
|
Cursor cursor = null;
|
|||
|
try {
|
|||
|
...
|
|||
|
// Database and environment open omitted for brevity
|
|||
|
...
|
|||
|
|
|||
|
// Open the cursor.
|
|||
|
cursor = myDatabase.openCursor(null, null);
|
|||
|
|
|||
|
DatabaseEntry theKey =
|
|||
|
new DatabaseEntry(searchKey.getBytes("UTF-8"));
|
|||
|
DatabaseEntry theData =
|
|||
|
new DatabaseEntry(searchData.getBytes("UTF-8"));
|
|||
|
|
|||
|
// Open a cursor using a database handle
|
|||
|
cursor = myDatabase.openCursor(null, null);
|
|||
|
|
|||
|
// Perform the search
|
|||
|
OperationStatus retVal = cursor.getSearchBothRange(theKey, theData,
|
|||
|
LockMode.DEFAULT);
|
|||
|
// NOTFOUND is returned if a record cannot be found whose key
|
|||
|
// matches the search key AND whose data begins with the search data.
|
|||
|
if (retVal == OperationStatus.NOTFOUND) {
|
|||
|
System.out.println(searchKey + "/" + searchData +
|
|||
|
" not matched in database " +
|
|||
|
myDatabase.getDatabaseName());
|
|||
|
} else {
|
|||
|
// Upon completing a search, the key and data DatabaseEntry
|
|||
|
// parameters for getSearchBothRange() are populated with the
|
|||
|
// key/data values of the found record.
|
|||
|
String foundKey = new String(theKey.getData(), "UTF-8");
|
|||
|
String foundData = new String(theData.getData(), "UTF-8");
|
|||
|
System.out.println("Found record " + foundKey + "/" + foundData +
|
|||
|
"for search key/data: " + searchKey +
|
|||
|
"/" + searchData);
|
|||
|
}
|
|||
|
|
|||
|
} catch (Exception e) {
|
|||
|
// Exception handling goes here
|
|||
|
} finally {
|
|||
|
// Make sure to close the cursor
|
|||
|
cursor.close();
|
|||
|
}</pre>
|
|||
|
</div>
|
|||
|
<div class="sect2" lang="en" xml:lang="en">
|
|||
|
<div class="titlepage">
|
|||
|
<div>
|
|||
|
<div>
|
|||
|
<h3 class="title"><a id="getdups"></a>Working with Duplicate Records</h3>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<p>
|
|||
|
If your database supports duplicate records, then it can potentially
|
|||
|
contain multiple records that share the same key.
|
|||
|
|
|||
|
<span>
|
|||
|
Using normal database get operations, you can only ever obtain the
|
|||
|
first such record in a set of duplicate records. To access subsequent
|
|||
|
duplicates, use a cursor.
|
|||
|
</span>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
The following
|
|||
|
<span><code class="methodname">Cursor</code> methods</span>
|
|||
|
|
|||
|
|
|||
|
are interesting when working with databases that support duplicate records:
|
|||
|
</p>
|
|||
|
<div class="itemizedlist">
|
|||
|
<ul type="disc">
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<span>
|
|||
|
<code class="methodname">Cursor.getNext()</code>,
|
|||
|
<code class="methodname">Cursor.getPrev()</code>
|
|||
|
</span>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Shows the next/previous record in the database, regardless of
|
|||
|
whether it is a duplicate of the current record. For an example of
|
|||
|
using these methods, see <a class="xref" href="Positioning.html" title="Getting Records Using the Cursor">Getting Records Using the Cursor</a>.
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<code class="methodname">Cursor.getSearchBothRange()</code>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Useful for seeking the cursor to a specific record, regardless of
|
|||
|
whether it is a duplicate record. See <a class="xref" href="Positioning.html#cursorsearch" title="Searching for Records">Searching for Records</a> for more
|
|||
|
information.
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<span>
|
|||
|
<code class="methodname">Cursor.getNextNoDup()</code>,
|
|||
|
<code class="methodname">Cursor.getPrevNoDup()</code>
|
|||
|
</span>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
Gets the next/previous non-duplicate record in the database. This
|
|||
|
allows you to skip over all the duplicates in a set of duplicate
|
|||
|
records. If you call
|
|||
|
<span><code class="methodname">Cursor.getPrevNoDup()</code>,</span>
|
|||
|
|
|||
|
then the cursor is positioned to the last record for the previous
|
|||
|
key in the database. For example, if you have the following records
|
|||
|
in your database:
|
|||
|
</p>
|
|||
|
<pre class="programlisting">Alabama/Athens
|
|||
|
Alabama/Florence
|
|||
|
Alaska/Anchorage
|
|||
|
Alaska/Fairbanks
|
|||
|
Arizona/Avondale
|
|||
|
Arizona/Florence</pre>
|
|||
|
<p>
|
|||
|
and your cursor is positioned to <code class="literal">Alaska/Fairbanks</code>,
|
|||
|
and you then call
|
|||
|
<span><code class="methodname">Cursor.getPrevNoDup()</code>,</span>
|
|||
|
|
|||
|
then the cursor is positioned to Alabama/Florence. Similarly, if
|
|||
|
you call
|
|||
|
<span><code class="methodname">Cursor.getNextNoDup()</code>,</span>
|
|||
|
|
|||
|
|
|||
|
then the cursor is positioned to the first record corresponding to
|
|||
|
the next key in the database.
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
If there is no next/previous key in the database, then
|
|||
|
<code class="literal">OperationStatus.NOTFOUND</code>
|
|||
|
|
|||
|
is returned, and the cursor is left unchanged.
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<span>
|
|||
|
<code class="methodname">Cursor.getNextDup()</code>,
|
|||
|
<code class="methodname">Cursor.getPrevDup()</code>
|
|||
|
</span>
|
|||
|
|
|||
|
</p>
|
|||
|
<p>
|
|||
|
|
|||
|
Gets the
|
|||
|
<span>next/previous</span>
|
|||
|
|
|||
|
record that shares the current key. If the
|
|||
|
cursor is positioned at the last record in the duplicate set and
|
|||
|
you call
|
|||
|
<span><code class="methodname">Cursor.getNextDup()</code>,</span>
|
|||
|
|
|||
|
|
|||
|
then
|
|||
|
<code class="literal">OperationStatus.NOTFOUND</code>
|
|||
|
|
|||
|
is returned and the cursor is left unchanged.
|
|||
|
<span>
|
|||
|
Likewise, if you call
|
|||
|
<code class="methodname">getPrevDup()</code> and the
|
|||
|
cursor is positioned at the first record in the duplicate set, then
|
|||
|
<code class="literal">OperationStatus.NOTFOUND</code> is returned and the
|
|||
|
cursor is left unchanged.
|
|||
|
</span>
|
|||
|
</p>
|
|||
|
</li>
|
|||
|
<li>
|
|||
|
<p>
|
|||
|
<code class="methodname">Cursor.count()</code>
|
|||
|
</p>
|
|||
|
<p>Returns the total number of records that share the current key.</p>
|
|||
|
</li>
|
|||
|
</ul>
|
|||
|
</div>
|
|||
|
<p>
|
|||
|
For example, the following code fragment positions a cursor to a key
|
|||
|
|
|||
|
<span>and, if the key contains duplicate records,
|
|||
|
displays all the duplicates.</span>
|
|||
|
|
|||
|
|
|||
|
|
|||
|
<span>Note that the following code fragment assumes that the database contains
|
|||
|
only String objects for the keys and data.</span>
|
|||
|
</p>
|
|||
|
<a id="je_cursor6"></a>
|
|||
|
<pre class="programlisting">package je.gettingStarted;
|
|||
|
|
|||
|
import com.sleepycat.je.Cursor;
|
|||
|
import com.sleepycat.je.Database;
|
|||
|
import com.sleepycat.je.DatabaseEntry;
|
|||
|
import com.sleepycat.je.DatabaseException;
|
|||
|
import com.sleepycat.je.LockMode;
|
|||
|
import com.sleepycat.je.OperationStatus;
|
|||
|
|
|||
|
...
|
|||
|
|
|||
|
Cursor cursor = null;
|
|||
|
try {
|
|||
|
...
|
|||
|
// Database and environment open omitted for brevity
|
|||
|
...
|
|||
|
|
|||
|
// Create DatabaseEntry objects
|
|||
|
// searchKey is some String.
|
|||
|
DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8"));
|
|||
|
DatabaseEntry theData = new DatabaseEntry();
|
|||
|
|
|||
|
// Open a cursor using a database handle
|
|||
|
cursor = myDatabase.openCursor(null, null);
|
|||
|
|
|||
|
// Position the cursor
|
|||
|
// Ignoring the return value for clarity
|
|||
|
OperationStatus retVal = cursor.getSearchKey(theKey, theData,
|
|||
|
LockMode.DEFAULT);
|
|||
|
|
|||
|
// Count the number of duplicates. If the count is greater than 1,
|
|||
|
// print the duplicates.
|
|||
|
if (cursor.count() > 1) {
|
|||
|
while (retVal == OperationStatus.SUCCESS) {
|
|||
|
String keyString = new String(theKey.getData(), "UTF-8");
|
|||
|
String dataString = new String(theData.getData(), "UTF-8");
|
|||
|
System.out.println("Key | Data : " + keyString + " | " +
|
|||
|
dataString + "");
|
|||
|
|
|||
|
retVal = cursor.getNextDup(theKey, theData, LockMode.DEFAULT);
|
|||
|
}
|
|||
|
}
|
|||
|
} catch (Exception e) {
|
|||
|
// Exception handling goes here
|
|||
|
} finally {
|
|||
|
// Make sure to close the cursor
|
|||
|
cursor.close();
|
|||
|
}</pre>
|
|||
|
</div>
|
|||
|
</div>
|
|||
|
<div class="navfooter">
|
|||
|
<hr />
|
|||
|
<table width="100%" summary="Navigation footer">
|
|||
|
<tr>
|
|||
|
<td width="40%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td>
|
|||
|
<td width="20%" align="center">
|
|||
|
<a accesskey="u" href="Cursors.html">Up</a>
|
|||
|
</td>
|
|||
|
<td width="40%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td>
|
|||
|
</tr>
|
|||
|
<tr>
|
|||
|
<td width="40%" align="left" valign="top">Chapter 9. Using Cursors </td>
|
|||
|
<td width="20%" align="center">
|
|||
|
<a accesskey="h" href="index.html">Home</a>
|
|||
|
</td>
|
|||
|
<td width="40%" align="right" valign="top"> Putting Records Using Cursors</td>
|
|||
|
</tr>
|
|||
|
</table>
|
|||
|
</div>
|
|||
|
</body>
|
|||
|
</html>
|