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>Implementing Key Creators</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="indexes.html" title="Chapter 10. Secondary Databases" /> 11 <link rel="prev" href="indexes.html" title="Chapter 10. Secondary Databases" /> 12 <link rel="next" href="secondaryProps.html" title="Secondary Database Properties" /> 13 </head> 14 <body> 15 <div class="navheader"> 16 <table width="100%" summary="Navigation header"> 17 <tr> 18 <th colspan="3" align="center">Implementing Key 19 <span>Creators</span> 20 21 </th> 22 </tr> 23 <tr> 24 <td width="20%" align="left"><a accesskey="p" href="indexes.html">Prev</a> </td> 25 <th width="60%" align="center">Chapter 10. Secondary Databases</th> 26 <td width="20%" align="right"> <a accesskey="n" href="secondaryProps.html">Next</a></td> 27 </tr> 28 </table> 29 <hr /> 30 </div> 31 <div class="sect1" lang="en" xml:lang="en"> 32 <div class="titlepage"> 33 <div> 34 <div> 35 <h2 class="title" style="clear: both"><a id="keyCreator"></a>Implementing Key 36 <span>Creators</span> 37 38 </h2> 39 </div> 40 </div> 41 </div> 42 <div class="toc"> 43 <dl> 44 <dt> 45 <span class="sect2"> 46 <a href="keyCreator.html#multikeys">Working with Multiple Keys</a> 47 </span> 48 </dt> 49 </dl> 50 </div> 51 <p> 52 You must provide every secondary database with a 53 <span>class</span> 54 55 that creates keys from primary records. You identify this 56 <span>class</span> 57 58 59 <span> 60 using the <code class="methodname">SecondaryConfig.setKeyCreator()</code> 61 method. 62 </span> 63 64 </p> 65 <p> 66 You can create keys using whatever data you want. Typically you will 67 base your key on some information found in a record's data, but you 68 can also use information found in the primary record's key. How you build 69 your keys is entirely dependent upon the nature of the index that you 70 want to maintain. 71 </p> 72 <p> 73 You implement a key creator by writing a class that implements the 74 <code class="classname">SecondaryKeyCreator</code> interface. This interface 75 requires you to implement the <code class="methodname">SecondaryKeyCreator.createSecondaryKey()</code> 76 method. 77 </p> 78 <p> 79 One thing to remember when implementing this method is that you will 80 need a way to extract the necessary information from the data's 81 <code class="classname">DatabaseEntry</code> and/or the key's 82 <code class="classname">DatabaseEntry</code> that are provided on calls to this 83 method. If you are using complex objects, then you are probably using the 84 Bind APIs to perform this conversion. The easiest thing to do is to 85 instantiate the <code class="classname">EntryBinding</code> or 86 <code class="classname">TupleBinding</code> that you need to perform the 87 conversion, and then provide this to your key creator's constructor. 88 The Bind APIs are introduced in <a class="xref" href="bindAPI.html" title="Using the BIND APIs">Using the BIND APIs</a>. 89 </p> 90 <p> 91 <code class="methodname">SecondaryKeyCreator.createSecondaryKey()</code> returns a 92 boolean. A return value of <code class="literal">false</code> indicates that 93 no secondary key exists, and therefore no record should be added to the secondary database for that primary record. 94 If a record already exists in the secondary database, it is deleted. 95 </p> 96 <p> 97 For example, suppose your primary database uses the following class 98 for its record data: 99 </p> 100 <a id="java_index3"></a> 101 <pre class="programlisting">package db.GettingStarted; 102 103public class PersonData { 104 private String userID; 105 private String surname; 106 private String familiarName; 107 108 public PersonData(String userID, String surname, String familiarName) { 109 this.userID = userID; 110 this.surname = surname; 111 this.familiarName = familiarName; 112 } 113 114 public String getUserID() { 115 return userID; 116 } 117 118 public String getSurname() { 119 return surname; 120 } 121 122 public String getFamiliarName() { 123 return familiarName; 124 } 125} </pre> 126 <p> 127 Also, suppose that you have created a custom tuple binding, 128 <code class="classname">PersonDataBinding</code>, that you use to convert 129 <code class="classname">PersonData</code> objects to and from 130 <code class="classname">DatabaseEntry</code> objects. (Custom tuple bindings are 131 described in <a class="xref" href="bindAPI.html#customTuple" title="Custom Tuple Bindings">Custom Tuple Bindings</a>.) 132 </p> 133 <p> 134 Finally, suppose you want a secondary database that is keyed based 135 on the person's full name. 136 </p> 137 <p> 138 Then in this case you might create a key creator as follows: 139 </p> 140 <a id="java_index4"></a> 141 <pre class="programlisting">package db.GettingStarted; 142 143import com.sleepycat.bind.tuple.TupleBinding; 144import com.sleepycat.db.SecondaryKeyCreator; 145import com.sleepycat.db.DatabaseEntry; 146import com.sleepycat.db.DatabaseException; 147import com.sleepycat.db.SecondaryDatabase; 148 149import java.io.IOException; 150 151public class FullNameKeyCreator implements SecondaryKeyCreator { 152 153 private TupleBinding theBinding; 154 155 public FullNameKeyCreator(TupleBinding theBinding1) { 156 theBinding = theBinding1; 157 } 158 159 public boolean createSecondaryKey(SecondaryDatabase secDb, 160 DatabaseEntry keyEntry, 161 DatabaseEntry dataEntry, 162 DatabaseEntry resultEntry) { 163 164 try { 165 PersonData pd = 166 (PersonData) theBinding.entryToObject(dataEntry); 167 String fullName = pd.getFamiliarName() + " " + 168 pd.getSurname(); 169 resultEntry.setData(fullName.getBytes("UTF-8")); 170 } catch (IOException willNeverOccur) {} 171 return true; 172 } 173} </pre> 174 <p>Finally, you use this key creator as follows:</p> 175 <a id="java_index5"></a> 176 <pre class="programlisting">package db.GettingStarted; 177 178import com.sleepycat.bind.tuple.TupleBinding; 179 180import com.sleepycat.db.Database; 181import com.sleepycat.db.DatabaseException; 182import com.sleepycat.db.DatabaseType; 183import com.sleepycat.db.SecondaryDatabase; 184import com.sleepycat.db.SecondaryConfig; 185 186import java.io.FileNotFoundException; 187 188... 189Database myDb = null; 190SecondaryDatabase mySecDb = null; 191try { 192 // Primary database open omitted for brevity 193... 194 195 TupleBinding myDataBinding = new MyTupleBinding(); 196 FullNameKeyCreator fnkc = new FullNameKeyCreator(myDataBinding); 197 198 SecondaryConfig mySecConfig = new SecondaryConfig(); 199 mySecConfig.setKeyCreator(fnkc); 200 mySecConfig.setType(DatabaseType.BTREE); 201 202 //Perform the actual open 203 String secDbName = "mySecondaryDatabase"; 204 mySecDb = new SecondaryDatabase(secDbName, null, myDb, mySecConfig); 205} catch (DatabaseException de) { 206 // Exception handling goes here 207} catch (FileNotFoundException fnfe) { 208 // Exception handling goes here 209} finally { 210 try { 211 if (mySecDb != null) { 212 mySecDb.close(); 213 } 214 215 if (myDb != null) { 216 myDb.close(); 217 } 218 } catch (DatabaseException dbe) { 219 // Exception handling goes here 220 } 221}</pre> 222 <div class="sect2" lang="en" xml:lang="en"> 223 <div class="titlepage"> 224 <div> 225 <div> 226 <h3 class="title"><a id="multikeys"></a>Working with Multiple Keys</h3> 227 </div> 228 </div> 229 </div> 230 <p> 231 Until now we have only discussed indexes as if there is 232 a one-to-one relationship between the secondary key and 233 the primary database record. In fact, it is possible to 234 generate multiple keys for any given record, provided 235 that you take appropriate steps in your key creator 236 to do so. 237 </p> 238 <p> 239 For example, suppose you had a database that contained 240 information about books. Suppose further that you 241 sometimes want to look up books by author. Because 242 sometimes books have multiple authors, you may want to 243 return multiple secondary keys for every book that you 244 index. 245 </p> 246 <p> 247 To do this, you write a key creator that implements 248 <code class="classname">SecondaryMultiKeyCreator</code> 249 instead of 250 <code class="classname">SecondaryKeyCreator</code>. The key 251 difference between the two is that 252 <code class="classname">SecondaryKeyCreator</code> 253 uses a single <code class="classname">DatabaseEntry</code> 254 object as the result, while 255 <code class="classname">SecondaryMultiKeyCreator</code> 256 returns a set of <code class="classname">DatabaseEntry</code> 257 objects (using <code class="classname">java.util.Set</code>). 258 Also, you assign the 259 <code class="classname">SecondaryMultiKeyCreator</code> 260 implementation using 261 <code class="methodname">SecondaryConfig.setMultiKeyCreator()</code> 262 instead of 263 <code class="methodname">SecondaryConfig.setKeyCreator()</code>. 264 </p> 265 <p> 266 For example: 267 </p> 268 <pre class="programlisting">package db.GettingStarted; 269 270import com.sleepycat.db.DatabaseEntry; 271import com.sleepycat.db.DatabaseException; 272import com.sleepycat.db.SecondaryDatabase; 273import com.sleepycat.db.SecondaryMultiKeyCreator; 274 275import java.util.HashSet; 276import java.util.Set; 277 278public class MyMultiKeyCreator implements SecondaryMultiKeyCreator { 279 280 // Constructor not implemented. How this is implemented depends on 281 // how you want to extract the data for your keys. 282 MyMultiKeyCreator() { 283 ... 284 } 285 286 // Abstract method that we must implement 287 public void createSecondaryKeys(SecondaryDatabase secDb, 288 DatabaseEntry keyEntry, // From the primary 289 DatabaseEntry dataEntry, // From the primary 290 Set results) // Results set 291 throws DatabaseException { 292 293 try { 294 // Create your keys, adding each to the set 295 296 // Creation of key 'a' not shown 297 results.add(a) 298 299 // Creation of key 'b' not shown 300 results.add(b) 301 302 } catch (IOException willNeverOccur) {} 303 } 304} </pre> 305 </div> 306 </div> 307 <div class="navfooter"> 308 <hr /> 309 <table width="100%" summary="Navigation footer"> 310 <tr> 311 <td width="40%" align="left"><a accesskey="p" href="indexes.html">Prev</a> </td> 312 <td width="20%" align="center"> 313 <a accesskey="u" href="indexes.html">Up</a> 314 </td> 315 <td width="40%" align="right"> <a accesskey="n" href="secondaryProps.html">Next</a></td> 316 </tr> 317 <tr> 318 <td width="40%" align="left" valign="top">Chapter 10. Secondary Databases </td> 319 <td width="20%" align="center"> 320 <a accesskey="h" href="index.html">Home</a> 321 </td> 322 <td width="40%" align="right" valign="top"> Secondary Database Properties</td> 323 </tr> 324 </table> 325 </div> 326 </body> 327</html> 328