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