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