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>Chapter��3.�� 7 Using Secondary Indices 8 </title> 9 <link rel="stylesheet" href="gettingStarted.css" type="text/css" /> 10 <meta name="generator" content="DocBook XSL Stylesheets V1.62.4" /> 11 <link rel="home" href="index.html" title="Berkeley DB Collections Tutorial" /> 12 <link rel="up" href="index.html" title="Berkeley DB Collections Tutorial" /> 13 <link rel="previous" href="handlingexceptions.html" title=" 		Handling Exceptions 	" /> 14 <link rel="next" href="openingforeignkeys.html" title=" 		 		More Secondary Key Indices 	" /> 15 </head> 16 <body> 17 <div class="navheader"> 18 <table width="100%" summary="Navigation header"> 19 <tr> 20 <th colspan="3" align="center">Chapter��3.�� 21 Using Secondary Indices 22 </th> 23 </tr> 24 <tr> 25 <td width="20%" align="left"><a accesskey="p" href="handlingexceptions.html">Prev</a>��</td> 26 <th width="60%" align="center">��</th> 27 <td width="20%" align="right">��<a accesskey="n" href="openingforeignkeys.html">Next</a></td> 28 </tr> 29 </table> 30 <hr /> 31 </div> 32 <div class="chapter" lang="en" xml:lang="en"> 33 <div class="titlepage"> 34 <div> 35 <div> 36 <h2 class="title"><a id="UsingSecondaries"></a>Chapter��3.�� 37 Using Secondary Indices 38 </h2> 39 </div> 40 </div> 41 <div></div> 42 </div> 43 <div class="toc"> 44 <p> 45 <b>Table of Contents</b> 46 </p> 47 <dl> 48 <dt> 49 <span class="sect1"> 50 <a href="UsingSecondaries.html#opensecondaryindices"> 51 Opening Secondary Key Indices 52 </a> 53 </span> 54 </dt> 55 <dt> 56 <span class="sect1"> 57 <a href="openingforeignkeys.html"> 58 59 More Secondary Key Indices 60 </a> 61 </span> 62 </dt> 63 <dt> 64 <span class="sect1"> 65 <a href="indexedcollections.html"> 66 Creating Indexed Collections 67 </a> 68 </span> 69 </dt> 70 <dt> 71 <span class="sect1"> 72 <a href="retrievingbyindexkey.html"> 73 Retrieving Items by Index Key 74 </a> 75 </span> 76 </dt> 77 </dl> 78 </div> 79 <p> 80 In the Basic example, each store has a single <span class="emphasis"><em>primary 81 key</em></span>. The Index example extends the Basic example to add the use of 82 <span class="emphasis"><em>secondary keys</em></span>. 83</p> 84 <p> 85 The complete source of the final version of the example program 86 is included in the Berkeley DB distribution. 87</p> 88 <div class="sect1" lang="en" xml:lang="en"> 89 <div class="titlepage"> 90 <div> 91 <div> 92 <h2 class="title" style="clear: both"><a id="opensecondaryindices"></a> 93 Opening Secondary Key Indices 94 </h2> 95 </div> 96 </div> 97 <div></div> 98 </div> 99 <p> 100 <span class="emphasis"><em>Secondary indices</em></span> or <span class="emphasis"><em>secondary databases</em></span> are used 101 to access a primary database by a key other than the primary key. 102 Recall that the Supplier Number field is the primary key of the 103 Supplier database. In this section, the Supplier City field will be 104 used as a secondary lookup key. Given a city value, we would like 105 to be able to find the Suppliers in that city. Note that more than 106 one Supplier may be in the same city. 107</p> 108 <p> 109 Both primary and secondary databases contain key-value records. 110 The key of an index record is the secondary key, and its value is 111 the key of the associated record in the primary database. When lookups by 112 secondary key are performed, the associated record in the primary 113 database is transparently retrieved by its primary key and returned 114 to the caller. 115</p> 116 <p> 117 Secondary indices are maintained automatically when index key 118 fields (the City field in this case) are added, modified or removed 119 in the records of the primary database. However, the application 120 must implement a 121 122 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a> 123 124 that extracts the index key from the database record. 125</p> 126 <p> 127 It is useful to contrast opening an secondary index with opening 128 a primary database (as described earlier in 129 <a href="opendatabases.html"> 130 Opening and Closing Databases 131 </a>. 132</p> 133 <div class="itemizedlist"> 134 <ul type="disc"> 135 <li> 136 <p> 137 A primary database may be associated with one or more secondary 138 indices. A secondary index is always associated with exactly one 139 primary database. 140 </p> 141 </li> 142 <li> 143 <p> 144 For a secondary index, a 145 146 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a> 147 148 must be implemented by the application to extract the index key 149 from the record of its associated primary database. 150 </p> 151 </li> 152 <li> 153 <p> 154 A primary database is represented by a 155 156 <a href="../../java/com/sleepycat/db/Database.html" target="_top">Database</a> 157 158 object and a secondary index is represented by a 159 160 <a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a> 161 162 object. The 163 164 <a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a> 165 166 class extends the 167 168 <a href="../../java/com/sleepycat/db/Database.html" target="_top">Database</a> 169 170 class. 171 </p> 172 </li> 173 <li> 174 <p> 175 When a 176 177 <a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a> 178 179 is created it is associated with a primary 180 181 <a href="../../java/com/sleepycat/db/Database.html" target="_top">Database</a> 182 183 object and a 184 185 <span> 186 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>. 187 </span> 188 </p> 189 </li> 190 </ul> 191 </div> 192 <p> 193 The <tt class="classname">SampleDatabase</tt> class is extended to open the 194 Supplier-by-City secondary key index. 195</p> 196 <a id="index_java_sampledatabase"></a> 197 <pre class="programlisting"><b class="userinput"><tt>import com.sleepycat.bind.serial.SerialSerialKeyCreator; 198import com.sleepycat.db.SecondaryConfig; 199import com.sleepycat.db.SecondaryDatabase;</tt></b> 200... 201public class SampleDatabase 202{ 203 ... 204<b class="userinput"><tt> private static final String SUPPLIER_CITY_INDEX = "supplier_city_index"; 205 ... 206 private SecondaryDatabase supplierByCityDb; 207 ...</tt></b> 208 public SampleDatabase(String homeDirectory) 209 throws DatabaseException, FileNotFoundException 210 { 211 ... 212<b class="userinput"><tt> SecondaryConfig secConfig = new SecondaryConfig(); 213 secConfig.setTransactional(true); 214 secConfig.setAllowCreate(true); 215 secConfig.setType(DatabaseType.BTREE); 216 secConfig.setSortedDuplicates(true); 217 218 secConfig.setKeyCreator( 219 new SupplierByCityKeyCreator(javaCatalog, 220 SupplierKey.class, 221 SupplierData.class, 222 String.class)); 223 224 supplierByCityDb = env.openSecondaryDatabase(null, 225 SUPPLIER_CITY_INDEX, 226 null, 227 supplierDb, 228 secConfig);</tt></b> 229 ... 230 } 231} </pre> 232 <p> 233 A 234 235 <a href="../../java/com/sleepycat/db/SecondaryConfig.html" target="_top">SecondaryConfig</a> 236 237 object is used to configure the secondary database. The 238 239 <a href="../../java/com/sleepycat/db/SecondaryConfig.html" target="_top">SecondaryConfig</a> 240 241 class extends the 242 243 <a href="../../java/com/sleepycat/db/DatabaseConfig.html" target="_top">DatabaseConfig</a> 244 245 class, and most steps for configuring a secondary database are the 246 same as for configuring a primary database. The main difference in 247 the example above is that the 248 <tt class="methodname">SecondaryConfig.setSortedDuplicates()</tt> method is called to 249 allow duplicate index keys. This is how more than one Supplier may 250 be in the same City. If this property is not specified, the default is 251 that the index keys of all records must be unique. 252</p> 253 <p> 254 For a primary database, duplicate keys are not normally used 255 since a primary database with duplicate keys may not have any 256 associated secondary indices. If primary database keys are not 257 unique, there is no way for a secondary key to reference a specific 258 record in the primary database. 259</p> 260 <p> 261 Note that <tt class="methodname">setSortedDuplicates()</tt> and not 262 <tt class="methodname">setUnsortedDuplicates()</tt> was called. Sorted 263 duplicates are always used for indices rather than unsorted duplicates, 264 since sorting enables optimized equality joins. 265</p> 266 <p> 267 Opening a secondary key index requires creating a 268 269 <span> 270 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>. 271 </span> 272 The <tt class="classname">SupplierByCityKeyCreator</tt> class implements the 273 274 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a> 275 276 interface and will be defined below. 277</p> 278 <p> 279 The 280 281 <a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a> 282 283 object is opened last. If you compare the 284 <tt class="methodname">openSecondaryDatabase()</tt> and <tt class="methodname">openDatabase()</tt> methods you'll 285 notice only two differences: 286</p> 287 <div class="itemizedlist"> 288 <ul type="disc"> 289 <li> 290 <p> 291 <tt class="methodname">openSecondaryDatabase()</tt> has an extra parameter for 292 specifying the associated primary database. The primary database is 293 <tt class="literal">supplierDb</tt> in this case. 294 </p> 295 </li> 296 <li> 297 <p> 298 The last parameter of <tt class="methodname">openSecondaryDatabase()</tt> is a 299 <tt class="literal">SecondaryConfig</tt> instead of a <tt class="literal">DatabaseConfig</tt>. 300 </p> 301 </li> 302 </ul> 303 </div> 304 <p> 305 How to use the secondary index to access records will be shown 306 in a later section. 307</p> 308 <p> 309 The application-defined <tt class="classname">SupplierByCityKeyCreator</tt> class is 310 shown below. It was used above to configure the secondary 311 database. 312</p> 313 <a id="index_supplierbycitykeycreator"></a> 314 <pre class="programlisting">public class SampleDatabase 315{ 316... 317<b class="userinput"><tt> private static class SupplierByCityKeyCreator 318 extends SerialSerialKeyCreator 319 { 320 private SupplierByCityKeyCreator(StoredClassCatalog catalog, 321 Class primaryKeyClass, 322 Class valueClass, 323 Class indexKeyClass) 324 { 325 super(catalog, primaryKeyClass, valueClass, indexKeyClass); 326 } 327 328 public Object createSecondaryKey(Object primaryKeyInput, 329 Object valueInput) 330 { 331 SupplierData supplierData = (SupplierData) valueInput; 332 return supplierData.getCity(); 333 } 334 }</tt></b> 335... 336} </pre> 337 <p> 338 In general, a key creator class must implement the 339 340 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a> 341 342 interface. This interface has methods that operate on the record 343 data as raw bytes. In practice, it is easiest to use an abstract 344 base class that performs the conversion of record data to and from 345 the format defined for the database's key and value. The base class 346 implements the 347 348 <a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a> 349 350 interface and has abstract methods that must be implemented in turn 351 by the application. 352</p> 353 <p> 354 In this example the 355 <a href="../../java/com/sleepycat/bind/serial/SerialSerialKeyCreator.html" target="_top">SerialSerialKeyCreator</a> 356 357 base class is used because the database record uses the serial 358 format for both its key and its value. The abstract methods of this 359 class have key and value parameters of type 360 <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html" target="_top">Object</a> 361 362 which are automatically converted to and from the raw record data 363 by the base class. 364</p> 365 <p> 366 To perform the conversions properly, the key creator must be 367 aware of all three formats involved: the key format of the primary 368 database record, the value format of the primary database record, 369 and the key format of the index record. The 370 <a href="../../java/com/sleepycat/bind/serial/SerialSerialKeyCreator.html" target="_top">SerialSerialKeyCreator</a> 371 372 constructor is given the base classes for these three formats as 373 parameters. 374</p> 375 <p> 376 The <tt class="methodname">SerialSerialKeyCreator.createSecondaryKey</tt> method is 377 given the key and value of the primary database record as 378 parameters, and it returns the key of the index record. In this 379 example, the index key is a field in the primary database record 380 value. Since the record value is known to be a <tt class="classname">SupplierData</tt> 381 object, it is cast to that class and the city field is 382 returned. 383</p> 384 <p> 385 Note that the <tt class="literal">primaryKeyInput</tt> parameter is not used in 386 the example. This parameter is needed only when an index key is 387 derived from the key of the primary database record. Normally an 388 index key is derived only from the primary database record value, 389 but it may be derived from the key, value or both. 390</p> 391 <p> 392 The following getter methods return the secondary database 393 object for use by other classes in the example program. The 394 secondary database object is used to create Java collections for 395 accessing records via their secondary keys. 396</p> 397 <a id="index_getsupplierbycitydatabase"></a> 398 <pre class="programlisting">public class SampleDatabase 399{ 400 ... 401<b class="userinput"><tt> public final SecondaryDatabase getSupplierByCityDatabase() 402 { 403 return supplierByCityDb; 404 }</tt></b> 405 ... 406} </pre> 407 <p> 408 The following statement closes the secondary database. 409</p> 410 <a id="index_close"></a> 411 <pre class="programlisting">public class SampleDatabase 412{ 413 ... 414 public void close() 415 throws DatabaseException { 416 417<b class="userinput"><tt> supplierByCityDb.close();</tt></b> 418 partDb.close(); 419 supplierDb.close(); 420 shipmentDb.close(); 421 javaCatalog.close(); 422 env.close(); 423 } 424 ... 425} </pre> 426 <p> 427 Secondary databases must be closed before closing their 428 associated primary database. 429</p> 430 </div> 431 </div> 432 <div class="navfooter"> 433 <hr /> 434 <table width="100%" summary="Navigation footer"> 435 <tr> 436 <td width="40%" align="left"><a accesskey="p" href="handlingexceptions.html">Prev</a>��</td> 437 <td width="20%" align="center"> 438 <a accesskey="u" href="index.html">Up</a> 439 </td> 440 <td width="40%" align="right">��<a accesskey="n" href="openingforeignkeys.html">Next</a></td> 441 </tr> 442 <tr> 443 <td width="40%" align="left" valign="top"> 444 Handling Exceptions 445 ��</td> 446 <td width="20%" align="center"> 447 <a accesskey="h" href="index.html">Home</a> 448 </td> 449 <td width="40%" align="right" valign="top">�� 450 451 More Secondary Key Indices 452 </td> 453 </tr> 454 </table> 455 </div> 456 </body> 457</html> 458