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