Import BSDDB 4.7.25 (as of svn r89086)
This commit is contained in:
597
docs/gsg/JAVA/Positioning.html
Normal file
597
docs/gsg/JAVA/Positioning.html
Normal file
@@ -0,0 +1,597 @@
|
||||
<?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.62.4" />
|
||||
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
|
||||
<link rel="up" href="Cursors.html" title="Chapter 9. Using Cursors" />
|
||||
<link rel="previous" href="Cursors.html" title="Chapter 9. Using Cursors" />
|
||||
<link rel="next" href="PutEntryWCursor.html" title="Putting Records Using Cursors" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<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>
|
||||
</div>
|
||||
<p>
|
||||
To iterate over database records, from the first record to
|
||||
the last, simply open the cursor and then use the
|
||||
<tt class="methodname">Cursor.getNext()</tt>
|
||||
|
||||
|
||||
method.
|
||||
|
||||
For example:
|
||||
</p>
|
||||
<a id="java_cursor3"></a>
|
||||
<pre class="programlisting">package db.GettingStarted;
|
||||
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
|
||||
...
|
||||
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
...
|
||||
Database myDatabase = null;
|
||||
// Database 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 <tt class="methodname">Cursor.getPrev()</tt> until you read the first record in
|
||||
the database. For example:
|
||||
</p>
|
||||
<a id="java_cursor4"></a>
|
||||
<pre class="programlisting">package db.GettingStarted;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
|
||||
...
|
||||
|
||||
Cursor cursor = null;
|
||||
Database myDatabase = null;
|
||||
try {
|
||||
...
|
||||
// Database 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="cursorsearch"></a>Searching for Records</h3>
|
||||
</div>
|
||||
</div>
|
||||
<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
|
||||
<tt class="literal">OperationStatus.NOTFOUND</tt>
|
||||
|
||||
is returned.
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
The following <tt class="classname">Cursor</tt> methods allow you to
|
||||
perform database searches:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">Cursor.getSearchKey()</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Moves the cursor to the first record in the database with
|
||||
the specified key.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">Cursor.getSearchKeyRange()</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
<span>Identical to
|
||||
|
||||
<tt class="methodname">Cursor.getSearchKey()</tt>
|
||||
unless you are using the BTree access. In this case, the cursor
|
||||
moves</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
|
||||
|
||||
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 <tt class="literal">Alaska</tt> moves the
|
||||
cursor to the second key noted above. Providing a key of
|
||||
<tt class="literal">Al</tt> moves the cursor to the first key (<tt class="literal">Alabama</tt>), providing
|
||||
a search key of <tt class="literal">Alas</tt> moves the cursor to the second key
|
||||
(<tt class="literal">Alaska</tt>), and providing a key of <tt class="literal">Ar</tt> moves the
|
||||
cursor to the last key (<tt class="literal">Arizona</tt>).
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">Cursor.getSearchBoth()</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Moves the cursor to the first record in the database that uses
|
||||
the specified key and data.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">Cursor.getSearchBothRange()</tt>
|
||||
|
||||
</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 your database uses BTree
|
||||
and it has </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:
|
||||
|
||||
</p>
|
||||
<a id="java_cursor5"></a>
|
||||
<pre class="programlisting">package db.GettingStarted;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
|
||||
...
|
||||
|
||||
// For this example, hard code the search key and data
|
||||
String searchKey = "Alaska";
|
||||
String searchData = "Fa";
|
||||
|
||||
Cursor cursor = null;
|
||||
Database myDatabase = null;
|
||||
try {
|
||||
...
|
||||
// Database 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></div>
|
||||
</div>
|
||||
<p>
|
||||
A record is a duplicate of another record if the two records share the
|
||||
same key. For duplicate records, only the data portion of the record is unique.
|
||||
</p>
|
||||
<p>
|
||||
Duplicate records are supported only for the BTree or Hash access methods.
|
||||
For information on configuring your database to use duplicate records,
|
||||
see <a href="btree.html#duplicateRecords">Allowing Duplicate Records</a>.
|
||||
</p>
|
||||
<p>
|
||||
If your database supports duplicate records, then it can potentially
|
||||
contain multiple records that share the same key.
|
||||
|
||||
|
||||
|
||||
<span>By default, normal database
|
||||
get operations will only return the first such record in a set
|
||||
of duplicate records. Typically, subsequent duplicate records are
|
||||
accessed using a cursor.
|
||||
</span>
|
||||
|
||||
The following
|
||||
<span><tt class="methodname">Cursor</tt> methods</span>
|
||||
|
||||
|
||||
are interesting when working with databases that support duplicate records:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<span>
|
||||
<tt class="methodname">Cursor.getNext()</tt>,
|
||||
<tt class="methodname">Cursor.getPrev()</tt>
|
||||
</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 href="Positioning.html">Getting Records Using the Cursor</a>.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">Cursor.getSearchBothRange()</tt>
|
||||
|
||||
</p>
|
||||
<p>
|
||||
Useful for seeking the cursor to a specific record, regardless of
|
||||
whether it is a duplicate record. See <a href="Positioning.html#cursorsearch">Searching for Records</a> for more
|
||||
information.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<span>
|
||||
<tt class="methodname">Cursor.getNextNoDup()</tt>,
|
||||
<tt class="methodname">Cursor.getPrevNoDup()</tt>
|
||||
</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><tt class="methodname">Cursor.getPrevNoDup()</tt>,</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 <tt class="literal">Alaska/Fairbanks</tt>,
|
||||
and you then call
|
||||
<span><tt class="methodname">Cursor.getPrevNoDup()</tt>,</span>
|
||||
|
||||
then the cursor is positioned to Alabama/Florence. Similarly, if
|
||||
you call
|
||||
<span><tt class="methodname">Cursor.getNextNoDup()</tt>,</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
|
||||
<tt class="literal">OperationStatus.NOTFOUND</tt>
|
||||
|
||||
is returned, and the cursor is left unchanged.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
|
||||
|
||||
</p>
|
||||
<p>
|
||||
|
||||
Gets the
|
||||
|
||||
<span>next</span>
|
||||
record that shares the current key. If the
|
||||
cursor is positioned at the last record in the duplicate set and
|
||||
you call
|
||||
<span><tt class="methodname">Cursor.getNextDup()</tt>,</span>
|
||||
|
||||
|
||||
then
|
||||
<tt class="literal">OperationStatus.NOTFOUND</tt>
|
||||
|
||||
is returned and the cursor is left unchanged.
|
||||
<span>
|
||||
Likewise, if you call
|
||||
<tt class="methodname">getPrevDup()</tt> and the
|
||||
cursor is positioned at the first record in the duplicate set, then
|
||||
<tt class="literal">OperationStatus.NOTFOUND</tt> is returned and the
|
||||
cursor is left unchanged.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">Cursor.count()</tt>
|
||||
</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 displays it and all its
|
||||
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="java_cursor6"></a>
|
||||
<pre class="programlisting">package db.GettingStarted;
|
||||
|
||||
import com.sleepycat.db.Cursor;
|
||||
import com.sleepycat.db.Database;
|
||||
import com.sleepycat.db.DatabaseEntry;
|
||||
import com.sleepycat.db.DatabaseException;
|
||||
import com.sleepycat.db.LockMode;
|
||||
import com.sleepycat.db.OperationStatus;
|
||||
|
||||
...
|
||||
|
||||
Cursor cursor = null;
|
||||
Database myDatabase = null;
|
||||
try {
|
||||
...
|
||||
// Database 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>
|
||||
Reference in New Issue
Block a user