1<?xml version="1.0" encoding="UTF-8" standalone="no"?> 2<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 3<html xmlns="http://www.w3.org/1999/xhtml"> 4 <head> 5 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6 <title>Getting Records Using the Cursor</title> 7 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 8 <meta name="generator" content="DocBook XSL Stylesheets V1.73.2" /> 9 <link rel="start" href="index.html" title="Getting Started with Berkeley DB" /> 10 <link rel="up" href="Cursors.html" title="Chapter 9. Using Cursors" /> 11 <link rel="prev" href="Cursors.html" title="Chapter 9. Using Cursors" /> 12 <link rel="next" href="PutEntryWCursor.html" title="Putting Records Using Cursors" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Getting Records Using the Cursor</th> 19 </tr> 20 <tr> 21 <td width="20%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td> 22 <th width="60%" align="center">Chapter 9. Using Cursors</th> 23 <td width="20%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td> 24 </tr> 25 </table> 26 <hr /> 27 </div> 28 <div class="sect1" lang="en" xml:lang="en"> 29 <div class="titlepage"> 30 <div> 31 <div> 32 <h2 class="title" style="clear: both"><a id="Positioning"></a>Getting Records Using the Cursor</h2> 33 </div> 34 </div> 35 </div> 36 <div class="toc"> 37 <dl> 38 <dt> 39 <span class="sect2"> 40 <a href="Positioning.html#cursorsearch">Searching for Records</a> 41 </span> 42 </dt> 43 <dt> 44 <span class="sect2"> 45 <a href="Positioning.html#getdups">Working with Duplicate Records</a> 46 </span> 47 </dt> 48 </dl> 49 </div> 50 <p> 51 To iterate over database records, from the first record to 52 the last, simply open the cursor and then use the 53 <code class="methodname">Cursor.getNext()</code> 54 55 56 method. 57 58 For example: 59 </p> 60 <a id="java_cursor3"></a> 61 <pre class="programlisting">package db.GettingStarted; 62 63import com.sleepycat.db.Database; 64import com.sleepycat.db.DatabaseEntry; 65import com.sleepycat.db.DatabaseException; 66import com.sleepycat.db.Cursor; 67import com.sleepycat.db.LockMode; 68import com.sleepycat.db.OperationStatus; 69 70... 71 72Cursor cursor = null; 73try { 74 ... 75 Database myDatabase = null; 76 // Database open omitted for brevity 77 ... 78 79 // Open the cursor. 80 cursor = myDatabase.openCursor(null, null); 81 82 // Cursors need a pair of DatabaseEntry objects to operate. These hold 83 // the key and data found at any given position in the database. 84 DatabaseEntry foundKey = new DatabaseEntry(); 85 DatabaseEntry foundData = new DatabaseEntry(); 86 87 // To iterate, just call getNext() until the last database record has been 88 // read. All cursor operations return an OperationStatus, so just read 89 // until we no longer see OperationStatus.SUCCESS 90 while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) == 91 OperationStatus.SUCCESS) { 92 // getData() on the DatabaseEntry objects returns the byte array 93 // held by that object. We use this to get a String value. If the 94 // DatabaseEntry held a byte array representation of some other data 95 // type (such as a complex object) then this operation would look 96 // considerably different. 97 String keyString = new String(foundKey.getData(), "UTF-8"); 98 String dataString = new String(foundData.getData(), "UTF-8"); 99 System.out.println("Key | Data : " + keyString + " | " + 100 dataString + ""); 101 } 102} catch (DatabaseException de) { 103 System.err.println("Error accessing database." + de); 104} finally { 105 // Cursors must be closed. 106 cursor.close(); 107}</pre> 108 <p> 109 To iterate over the database from the last record to the first, 110 instantiate the cursor, and then 111 use <code class="methodname">Cursor.getPrev()</code> until you read the first record in 112 the database. For example: 113 </p> 114 <a id="java_cursor4"></a> 115 <pre class="programlisting">package db.GettingStarted; 116 117import com.sleepycat.db.Cursor; 118import com.sleepycat.db.Database; 119import com.sleepycat.db.DatabaseEntry; 120import com.sleepycat.db.DatabaseException; 121import com.sleepycat.db.LockMode; 122import com.sleepycat.db.OperationStatus; 123 124... 125 126Cursor cursor = null; 127Database myDatabase = null; 128try { 129 ... 130 // Database open omitted for brevity 131 ... 132 133 // Open the cursor. 134 cursor = myDatabase.openCursor(null, null); 135 136 // Get the DatabaseEntry objects that the cursor will use. 137 DatabaseEntry foundKey = new DatabaseEntry(); 138 DatabaseEntry foundData = new DatabaseEntry(); 139 140 // Iterate from the last record to the first in the database 141 while (cursor.getPrev(foundKey, foundData, LockMode.DEFAULT) == 142 OperationStatus.SUCCESS) { 143 144 String theKey = new String(foundKey.getData(), "UTF-8"); 145 String theData = new String(foundData.getData(), "UTF-8"); 146 System.out.println("Key | Data : " + theKey + " | " + theData + ""); 147 } 148} catch (DatabaseException de) { 149 System.err.println("Error accessing database." + de); 150} finally { 151 // Cursors must be closed. 152 cursor.close(); 153}</pre> 154 <div class="sect2" lang="en" xml:lang="en"> 155 <div class="titlepage"> 156 <div> 157 <div> 158 <h3 class="title"><a id="cursorsearch"></a>Searching for Records</h3> 159 </div> 160 </div> 161 </div> 162 <p> 163 You can use cursors to search for database records. You can search based 164 on just a key, or you can search based on both the key and the data. 165 You can also perform partial matches if your database supports sorted 166 duplicate sets. In all cases, the key and data parameters of these 167 methods are filled with the key and data values of the database record 168 to which the cursor is positioned as a result of the search. 169 </p> 170 <p> 171 Also, if the search fails, then cursor's state is left unchanged 172 and 173 <code class="literal">OperationStatus.NOTFOUND</code> 174 175 is returned. 176 177 178 </p> 179 <p> 180 The following <code class="classname">Cursor</code> methods allow you to 181 perform database searches: 182 </p> 183 <div class="itemizedlist"> 184 <ul type="disc"> 185 <li> 186 <p> 187 <code class="methodname">Cursor.getSearchKey()</code> 188 189 </p> 190 <p> 191 Moves the cursor to the first record in the database with 192 the specified key. 193 </p> 194 </li> 195 <li> 196 <p> 197 <code class="methodname">Cursor.getSearchKeyRange()</code> 198 199 </p> 200 <p> 201 <span>Identical to 202 203 <code class="methodname">Cursor.getSearchKey()</code> 204 unless you are using the BTree access. In this case, the cursor 205 moves</span> 206 207 208 to the first record in the database whose 209 key is greater than or equal to the specified key. This comparison 210 is determined by the 211 <span>comparator</span> 212 213 that you provide for the database. If no 214 <span>comparator</span> 215 216 is provided, then the default 217 218 lexicographical sorting is used. 219 </p> 220 <p> 221 For example, suppose you have database records that use the 222 following 223 <span>Strings</span> 224 225 as keys: 226 </p> 227 <pre class="programlisting">Alabama 228Alaska 229Arizona</pre> 230 <p> 231 Then providing a search key of <code class="literal">Alaska</code> moves the 232 cursor to the second key noted above. Providing a key of 233 <code class="literal">Al</code> moves the cursor to the first key (<code class="literal">Alabama</code>), providing 234 a search key of <code class="literal">Alas</code> moves the cursor to the second key 235 (<code class="literal">Alaska</code>), and providing a key of <code class="literal">Ar</code> moves the 236 cursor to the last key (<code class="literal">Arizona</code>). 237 </p> 238 </li> 239 <li> 240 <p> 241 <code class="methodname">Cursor.getSearchBoth()</code> 242 243 </p> 244 <p> 245 Moves the cursor to the first record in the database that uses 246 the specified key and data. 247 </p> 248 </li> 249 <li> 250 <p> 251 <code class="methodname">Cursor.getSearchBothRange()</code> 252 253 </p> 254 <p> 255 Moves the cursor to the first record in the database whose key matches the specified 256 key and whose data is 257 greater than or equal to the specified data. If the database supports 258 duplicate records, then on matching the key, the cursor is moved to 259 the duplicate record with the smallest data that is greater than or 260 equal to the specified data. 261 </p> 262 <p> 263 For example, 264 265 <span>suppose your database uses BTree 266 and it has </span> 267 database records that use the following key/data pairs: 268 </p> 269 <pre class="programlisting">Alabama/Athens 270Alabama/Florence 271Alaska/Anchorage 272Alaska/Fairbanks 273Arizona/Avondale 274Arizona/Florence </pre> 275 <p>then providing:</p> 276 <div class="informaltable"> 277 <table border="1" width="80%"> 278 <colgroup> 279 <col /> 280 <col /> 281 <col /> 282 </colgroup> 283 <thead> 284 <tr> 285 <th>a search key of ...</th> 286 <th>and a search data of ...</th> 287 <th>moves the cursor to ...</th> 288 </tr> 289 </thead> 290 <tbody> 291 <tr> 292 <td>Alaska</td> 293 <td>Fa</td> 294 <td>Alaska/Fairbanks</td> 295 </tr> 296 <tr> 297 <td>Arizona</td> 298 <td>Fl</td> 299 <td>Arizona/Florence</td> 300 </tr> 301 <tr> 302 <td>Alaska</td> 303 <td>An</td> 304 <td>Alaska/Anchorage</td> 305 </tr> 306 </tbody> 307 </table> 308 </div> 309 </li> 310 </ul> 311 </div> 312 <p> 313 For example, assuming a database containing sorted duplicate records of 314 U.S. States/U.S Cities key/data pairs (both as 315 <span>Strings),</span> 316 317 then the following code fragment can be used to position the cursor 318 to any record in the database and print its key/data values: 319 320 </p> 321 <a id="java_cursor5"></a> 322 <pre class="programlisting">package db.GettingStarted; 323 324import com.sleepycat.db.Cursor; 325import com.sleepycat.db.Database; 326import com.sleepycat.db.DatabaseEntry; 327import com.sleepycat.db.DatabaseException; 328import com.sleepycat.db.LockMode; 329import com.sleepycat.db.OperationStatus; 330 331... 332 333// For this example, hard code the search key and data 334String searchKey = "Alaska"; 335String searchData = "Fa"; 336 337Cursor cursor = null; 338Database myDatabase = null; 339try { 340 ... 341 // Database open omitted for brevity 342 ... 343 344 // Open the cursor. 345 cursor = myDatabase.openCursor(null, null); 346 347 DatabaseEntry theKey = 348 new DatabaseEntry(searchKey.getBytes("UTF-8")); 349 DatabaseEntry theData = 350 new DatabaseEntry(searchData.getBytes("UTF-8")); 351 352 // Open a cursor using a database handle 353 cursor = myDatabase.openCursor(null, null); 354 355 // Perform the search 356 OperationStatus retVal = cursor.getSearchBothRange(theKey, theData, 357 LockMode.DEFAULT); 358 // NOTFOUND is returned if a record cannot be found whose key 359 // matches the search key AND whose data begins with the search data. 360 if (retVal == OperationStatus.NOTFOUND) { 361 System.out.println(searchKey + "/" + searchData + 362 " not matched in database " + 363 myDatabase.getDatabaseName()); 364 } else { 365 // Upon completing a search, the key and data DatabaseEntry 366 // parameters for getSearchBothRange() are populated with the 367 // key/data values of the found record. 368 String foundKey = new String(theKey.getData(), "UTF-8"); 369 String foundData = new String(theData.getData(), "UTF-8"); 370 System.out.println("Found record " + foundKey + "/" + foundData + 371 "for search key/data: " + searchKey + 372 "/" + searchData); 373 } 374 375} catch (Exception e) { 376 // Exception handling goes here 377} finally { 378 // Make sure to close the cursor 379 cursor.close(); 380}</pre> 381 </div> 382 <div class="sect2" lang="en" xml:lang="en"> 383 <div class="titlepage"> 384 <div> 385 <div> 386 <h3 class="title"><a id="getdups"></a>Working with Duplicate Records</h3> 387 </div> 388 </div> 389 </div> 390 <p> 391 A record is a duplicate of another record if the two records share the 392 same key. For duplicate records, only the data portion of the record is unique. 393 </p> 394 <p> 395 Duplicate records are supported only for the BTree or Hash access methods. 396 For information on configuring your database to use duplicate records, 397 see <a class="xref" href="btree.html#duplicateRecords" title="Allowing Duplicate Records">Allowing Duplicate Records</a>. 398 </p> 399 <p> 400 If your database supports duplicate records, then it can potentially 401 contain multiple records that share the same key. 402 403 404 405 <span>By default, normal database 406 get operations will only return the first such record in a set 407 of duplicate records. Typically, subsequent duplicate records are 408 accessed using a cursor. 409 </span> 410 411 The following 412 <span><code class="methodname">Cursor</code> methods</span> 413 414 415 are interesting when working with databases that support duplicate records: 416 </p> 417 <div class="itemizedlist"> 418 <ul type="disc"> 419 <li> 420 <p> 421 <span> 422 <code class="methodname">Cursor.getNext()</code>, 423 <code class="methodname">Cursor.getPrev()</code> 424 </span> 425 426 </p> 427 <p> 428 Shows the next/previous record in the database, regardless of 429 whether it is a duplicate of the current record. For an example of 430 using these methods, see <a class="xref" href="Positioning.html" title="Getting Records Using the Cursor">Getting Records Using the Cursor</a>. 431 </p> 432 </li> 433 <li> 434 <p> 435 <code class="methodname">Cursor.getSearchBothRange()</code> 436 437 </p> 438 <p> 439 Useful for seeking the cursor to a specific record, regardless of 440 whether it is a duplicate record. See <a class="xref" href="Positioning.html#cursorsearch" title="Searching for Records">Searching for Records</a> for more 441 information. 442 </p> 443 </li> 444 <li> 445 <p> 446 <span> 447 <code class="methodname">Cursor.getNextNoDup()</code>, 448 <code class="methodname">Cursor.getPrevNoDup()</code> 449 </span> 450 451 </p> 452 <p> 453 Gets the next/previous non-duplicate record in the database. This 454 allows you to skip over all the duplicates in a set of duplicate 455 records. If you call 456 <span><code class="methodname">Cursor.getPrevNoDup()</code>,</span> 457 458 then the cursor is positioned to the last record for the previous 459 key in the database. For example, if you have the following records 460 in your database: 461 </p> 462 <pre class="programlisting">Alabama/Athens 463Alabama/Florence 464Alaska/Anchorage 465Alaska/Fairbanks 466Arizona/Avondale 467Arizona/Florence</pre> 468 <p> 469 and your cursor is positioned to <code class="literal">Alaska/Fairbanks</code>, 470 and you then call 471 <span><code class="methodname">Cursor.getPrevNoDup()</code>,</span> 472 473 then the cursor is positioned to Alabama/Florence. Similarly, if 474 you call 475 <span><code class="methodname">Cursor.getNextNoDup()</code>,</span> 476 477 478 then the cursor is positioned to the first record corresponding to 479 the next key in the database. 480 </p> 481 <p> 482 If there is no next/previous key in the database, then 483 <code class="literal">OperationStatus.NOTFOUND</code> 484 485 is returned, and the cursor is left unchanged. 486 </p> 487 </li> 488 <li> 489 <p> 490 491 492 </p> 493 <p> 494 495 Gets the 496 497 <span>next</span> 498 record that shares the current key. If the 499 cursor is positioned at the last record in the duplicate set and 500 you call 501 <span><code class="methodname">Cursor.getNextDup()</code>,</span> 502 503 504 then 505 <code class="literal">OperationStatus.NOTFOUND</code> 506 507 is returned and the cursor is left unchanged. 508 <span> 509 Likewise, if you call 510 <code class="methodname">getPrevDup()</code> and the 511 cursor is positioned at the first record in the duplicate set, then 512 <code class="literal">OperationStatus.NOTFOUND</code> is returned and the 513 cursor is left unchanged. 514 </span> 515 </p> 516 </li> 517 <li> 518 <p> 519 <code class="methodname">Cursor.count()</code> 520 </p> 521 <p>Returns the total number of records that share the current key.</p> 522 </li> 523 </ul> 524 </div> 525 <p> 526 For example, the following code fragment positions a cursor to a key 527 528 529 530 <span>and displays it and all its 531 duplicates.</span> 532 533 <span>Note that the following code fragment assumes that the database contains 534 only String objects for the keys and data.</span> 535 </p> 536 <a id="java_cursor6"></a> 537 <pre class="programlisting">package db.GettingStarted; 538 539import com.sleepycat.db.Cursor; 540import com.sleepycat.db.Database; 541import com.sleepycat.db.DatabaseEntry; 542import com.sleepycat.db.DatabaseException; 543import com.sleepycat.db.LockMode; 544import com.sleepycat.db.OperationStatus; 545 546... 547 548Cursor cursor = null; 549Database myDatabase = null; 550try { 551 ... 552 // Database open omitted for brevity 553 ... 554 555 // Create DatabaseEntry objects 556 // searchKey is some String. 557 DatabaseEntry theKey = new DatabaseEntry(searchKey.getBytes("UTF-8")); 558 DatabaseEntry theData = new DatabaseEntry(); 559 560 // Open a cursor using a database handle 561 cursor = myDatabase.openCursor(null, null); 562 563 // Position the cursor 564 // Ignoring the return value for clarity 565 OperationStatus retVal = cursor.getSearchKey(theKey, theData, 566 LockMode.DEFAULT); 567 568 // Count the number of duplicates. If the count is greater than 1, 569 // print the duplicates. 570 if (cursor.count() > 1) { 571 while (retVal == OperationStatus.SUCCESS) { 572 String keyString = new String(theKey.getData(), "UTF-8"); 573 String dataString = new String(theData.getData(), "UTF-8"); 574 System.out.println("Key | Data : " + keyString + " | " + 575 dataString + ""); 576 577 retVal = cursor.getNextDup(theKey, theData, LockMode.DEFAULT); 578 } 579 } 580} catch (Exception e) { 581 // Exception handling goes here 582} finally { 583 // Make sure to close the cursor 584 cursor.close(); 585}</pre> 586 </div> 587 </div> 588 <div class="navfooter"> 589 <hr /> 590 <table width="100%" summary="Navigation footer"> 591 <tr> 592 <td width="40%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td> 593 <td width="20%" align="center"> 594 <a accesskey="u" href="Cursors.html">Up</a> 595 </td> 596 <td width="40%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td> 597 </tr> 598 <tr> 599 <td width="40%" align="left" valign="top">Chapter 9. Using Cursors </td> 600 <td width="20%" align="center"> 601 <a accesskey="h" href="index.html">Home</a> 602 </td> 603 <td width="40%" align="right" valign="top"> Putting Records Using Cursors</td> 604 </tr> 605 </table> 606 </div> 607 </body> 608</html> 609