Import BSDDB 4.7.25 (as of svn r89086)
This commit is contained in:
457
docs/collections/tutorial/UsingSecondaries.html
Normal file
457
docs/collections/tutorial/UsingSecondaries.html
Normal file
@@ -0,0 +1,457 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<title>Chapter 3.
|
||||
Using Secondary Indices
|
||||
</title>
|
||||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
|
||||
<link rel="home" href="index.html" title="Berkeley DB Collections Tutorial" />
|
||||
<link rel="up" href="index.html" title="Berkeley DB Collections Tutorial" />
|
||||
<link rel="previous" href="handlingexceptions.html" title=" 		Handling Exceptions 	" />
|
||||
<link rel="next" href="openingforeignkeys.html" title=" 		 		More Secondary Key Indices 	" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="navheader">
|
||||
<table width="100%" summary="Navigation header">
|
||||
<tr>
|
||||
<th colspan="3" align="center">Chapter 3.
|
||||
Using Secondary Indices
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="20%" align="left"><a accesskey="p" href="handlingexceptions.html">Prev</a> </td>
|
||||
<th width="60%" align="center"> </th>
|
||||
<td width="20%" align="right"> <a accesskey="n" href="openingforeignkeys.html">Next</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
</div>
|
||||
<div class="chapter" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title"><a id="UsingSecondaries"></a>Chapter 3.
|
||||
Using Secondary Indices
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="toc">
|
||||
<p>
|
||||
<b>Table of Contents</b>
|
||||
</p>
|
||||
<dl>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="UsingSecondaries.html#opensecondaryindices">
|
||||
Opening Secondary Key Indices
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="openingforeignkeys.html">
|
||||
|
||||
More Secondary Key Indices
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="indexedcollections.html">
|
||||
Creating Indexed Collections
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
<dt>
|
||||
<span class="sect1">
|
||||
<a href="retrievingbyindexkey.html">
|
||||
Retrieving Items by Index Key
|
||||
</a>
|
||||
</span>
|
||||
</dt>
|
||||
</dl>
|
||||
</div>
|
||||
<p>
|
||||
In the Basic example, each store has a single <span class="emphasis"><em>primary
|
||||
key</em></span>. The Index example extends the Basic example to add the use of
|
||||
<span class="emphasis"><em>secondary keys</em></span>.
|
||||
</p>
|
||||
<p>
|
||||
The complete source of the final version of the example program
|
||||
is included in the Berkeley DB distribution.
|
||||
</p>
|
||||
<div class="sect1" lang="en" xml:lang="en">
|
||||
<div class="titlepage">
|
||||
<div>
|
||||
<div>
|
||||
<h2 class="title" style="clear: both"><a id="opensecondaryindices"></a>
|
||||
Opening Secondary Key Indices
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
<p>
|
||||
<span class="emphasis"><em>Secondary indices</em></span> or <span class="emphasis"><em>secondary databases</em></span> are used
|
||||
to access a primary database by a key other than the primary key.
|
||||
Recall that the Supplier Number field is the primary key of the
|
||||
Supplier database. In this section, the Supplier City field will be
|
||||
used as a secondary lookup key. Given a city value, we would like
|
||||
to be able to find the Suppliers in that city. Note that more than
|
||||
one Supplier may be in the same city.
|
||||
</p>
|
||||
<p>
|
||||
Both primary and secondary databases contain key-value records.
|
||||
The key of an index record is the secondary key, and its value is
|
||||
the key of the associated record in the primary database. When lookups by
|
||||
secondary key are performed, the associated record in the primary
|
||||
database is transparently retrieved by its primary key and returned
|
||||
to the caller.
|
||||
</p>
|
||||
<p>
|
||||
Secondary indices are maintained automatically when index key
|
||||
fields (the City field in this case) are added, modified or removed
|
||||
in the records of the primary database. However, the application
|
||||
must implement a
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>
|
||||
|
||||
that extracts the index key from the database record.
|
||||
</p>
|
||||
<p>
|
||||
It is useful to contrast opening an secondary index with opening
|
||||
a primary database (as described earlier in
|
||||
<a href="opendatabases.html">
|
||||
Opening and Closing Databases
|
||||
</a>.
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
A primary database may be associated with one or more secondary
|
||||
indices. A secondary index is always associated with exactly one
|
||||
primary database.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
For a secondary index, a
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>
|
||||
|
||||
must be implemented by the application to extract the index key
|
||||
from the record of its associated primary database.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
A primary database is represented by a
|
||||
|
||||
<a href="../../java/com/sleepycat/db/Database.html" target="_top">Database</a>
|
||||
|
||||
object and a secondary index is represented by a
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a>
|
||||
|
||||
object. The
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a>
|
||||
|
||||
class extends the
|
||||
|
||||
<a href="../../java/com/sleepycat/db/Database.html" target="_top">Database</a>
|
||||
|
||||
class.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
When a
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a>
|
||||
|
||||
is created it is associated with a primary
|
||||
|
||||
<a href="../../java/com/sleepycat/db/Database.html" target="_top">Database</a>
|
||||
|
||||
object and a
|
||||
|
||||
<span>
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>.
|
||||
</span>
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
The <tt class="classname">SampleDatabase</tt> class is extended to open the
|
||||
Supplier-by-City secondary key index.
|
||||
</p>
|
||||
<a id="index_java_sampledatabase"></a>
|
||||
<pre class="programlisting"><b class="userinput"><tt>import com.sleepycat.bind.serial.SerialSerialKeyCreator;
|
||||
import com.sleepycat.db.SecondaryConfig;
|
||||
import com.sleepycat.db.SecondaryDatabase;</tt></b>
|
||||
...
|
||||
public class SampleDatabase
|
||||
{
|
||||
...
|
||||
<b class="userinput"><tt> private static final String SUPPLIER_CITY_INDEX = "supplier_city_index";
|
||||
...
|
||||
private SecondaryDatabase supplierByCityDb;
|
||||
...</tt></b>
|
||||
public SampleDatabase(String homeDirectory)
|
||||
throws DatabaseException, FileNotFoundException
|
||||
{
|
||||
...
|
||||
<b class="userinput"><tt> SecondaryConfig secConfig = new SecondaryConfig();
|
||||
secConfig.setTransactional(true);
|
||||
secConfig.setAllowCreate(true);
|
||||
secConfig.setType(DatabaseType.BTREE);
|
||||
secConfig.setSortedDuplicates(true);
|
||||
|
||||
secConfig.setKeyCreator(
|
||||
new SupplierByCityKeyCreator(javaCatalog,
|
||||
SupplierKey.class,
|
||||
SupplierData.class,
|
||||
String.class));
|
||||
|
||||
supplierByCityDb = env.openSecondaryDatabase(null,
|
||||
SUPPLIER_CITY_INDEX,
|
||||
null,
|
||||
supplierDb,
|
||||
secConfig);</tt></b>
|
||||
...
|
||||
}
|
||||
} </pre>
|
||||
<p>
|
||||
A
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryConfig.html" target="_top">SecondaryConfig</a>
|
||||
|
||||
object is used to configure the secondary database. The
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryConfig.html" target="_top">SecondaryConfig</a>
|
||||
|
||||
class extends the
|
||||
|
||||
<a href="../../java/com/sleepycat/db/DatabaseConfig.html" target="_top">DatabaseConfig</a>
|
||||
|
||||
class, and most steps for configuring a secondary database are the
|
||||
same as for configuring a primary database. The main difference in
|
||||
the example above is that the
|
||||
<tt class="methodname">SecondaryConfig.setSortedDuplicates()</tt> method is called to
|
||||
allow duplicate index keys. This is how more than one Supplier may
|
||||
be in the same City. If this property is not specified, the default is
|
||||
that the index keys of all records must be unique.
|
||||
</p>
|
||||
<p>
|
||||
For a primary database, duplicate keys are not normally used
|
||||
since a primary database with duplicate keys may not have any
|
||||
associated secondary indices. If primary database keys are not
|
||||
unique, there is no way for a secondary key to reference a specific
|
||||
record in the primary database.
|
||||
</p>
|
||||
<p>
|
||||
Note that <tt class="methodname">setSortedDuplicates()</tt> and not
|
||||
<tt class="methodname">setUnsortedDuplicates()</tt> was called. Sorted
|
||||
duplicates are always used for indices rather than unsorted duplicates,
|
||||
since sorting enables optimized equality joins.
|
||||
</p>
|
||||
<p>
|
||||
Opening a secondary key index requires creating a
|
||||
|
||||
<span>
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>.
|
||||
</span>
|
||||
The <tt class="classname">SupplierByCityKeyCreator</tt> class implements the
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>
|
||||
|
||||
interface and will be defined below.
|
||||
</p>
|
||||
<p>
|
||||
The
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryDatabase.html" target="_top">SecondaryDatabase</a>
|
||||
|
||||
object is opened last. If you compare the
|
||||
<tt class="methodname">openSecondaryDatabase()</tt> and <tt class="methodname">openDatabase()</tt> methods you'll
|
||||
notice only two differences:
|
||||
</p>
|
||||
<div class="itemizedlist">
|
||||
<ul type="disc">
|
||||
<li>
|
||||
<p>
|
||||
<tt class="methodname">openSecondaryDatabase()</tt> has an extra parameter for
|
||||
specifying the associated primary database. The primary database is
|
||||
<tt class="literal">supplierDb</tt> in this case.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
The last parameter of <tt class="methodname">openSecondaryDatabase()</tt> is a
|
||||
<tt class="literal">SecondaryConfig</tt> instead of a <tt class="literal">DatabaseConfig</tt>.
|
||||
</p>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<p>
|
||||
How to use the secondary index to access records will be shown
|
||||
in a later section.
|
||||
</p>
|
||||
<p>
|
||||
The application-defined <tt class="classname">SupplierByCityKeyCreator</tt> class is
|
||||
shown below. It was used above to configure the secondary
|
||||
database.
|
||||
</p>
|
||||
<a id="index_supplierbycitykeycreator"></a>
|
||||
<pre class="programlisting">public class SampleDatabase
|
||||
{
|
||||
...
|
||||
<b class="userinput"><tt> private static class SupplierByCityKeyCreator
|
||||
extends SerialSerialKeyCreator
|
||||
{
|
||||
private SupplierByCityKeyCreator(StoredClassCatalog catalog,
|
||||
Class primaryKeyClass,
|
||||
Class valueClass,
|
||||
Class indexKeyClass)
|
||||
{
|
||||
super(catalog, primaryKeyClass, valueClass, indexKeyClass);
|
||||
}
|
||||
|
||||
public Object createSecondaryKey(Object primaryKeyInput,
|
||||
Object valueInput)
|
||||
{
|
||||
SupplierData supplierData = (SupplierData) valueInput;
|
||||
return supplierData.getCity();
|
||||
}
|
||||
}</tt></b>
|
||||
...
|
||||
} </pre>
|
||||
<p>
|
||||
In general, a key creator class must implement the
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>
|
||||
|
||||
interface. This interface has methods that operate on the record
|
||||
data as raw bytes. In practice, it is easiest to use an abstract
|
||||
base class that performs the conversion of record data to and from
|
||||
the format defined for the database's key and value. The base class
|
||||
implements the
|
||||
|
||||
<a href="../../java/com/sleepycat/db/SecondaryKeyCreator.html" target="_top">SecondaryKeyCreator</a>
|
||||
|
||||
interface and has abstract methods that must be implemented in turn
|
||||
by the application.
|
||||
</p>
|
||||
<p>
|
||||
In this example the
|
||||
<a href="../../java/com/sleepycat/bind/serial/SerialSerialKeyCreator.html" target="_top">SerialSerialKeyCreator</a>
|
||||
|
||||
base class is used because the database record uses the serial
|
||||
format for both its key and its value. The abstract methods of this
|
||||
class have key and value parameters of type
|
||||
<a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html" target="_top">Object</a>
|
||||
|
||||
which are automatically converted to and from the raw record data
|
||||
by the base class.
|
||||
</p>
|
||||
<p>
|
||||
To perform the conversions properly, the key creator must be
|
||||
aware of all three formats involved: the key format of the primary
|
||||
database record, the value format of the primary database record,
|
||||
and the key format of the index record. The
|
||||
<a href="../../java/com/sleepycat/bind/serial/SerialSerialKeyCreator.html" target="_top">SerialSerialKeyCreator</a>
|
||||
|
||||
constructor is given the base classes for these three formats as
|
||||
parameters.
|
||||
</p>
|
||||
<p>
|
||||
The <tt class="methodname">SerialSerialKeyCreator.createSecondaryKey</tt> method is
|
||||
given the key and value of the primary database record as
|
||||
parameters, and it returns the key of the index record. In this
|
||||
example, the index key is a field in the primary database record
|
||||
value. Since the record value is known to be a <tt class="classname">SupplierData</tt>
|
||||
object, it is cast to that class and the city field is
|
||||
returned.
|
||||
</p>
|
||||
<p>
|
||||
Note that the <tt class="literal">primaryKeyInput</tt> parameter is not used in
|
||||
the example. This parameter is needed only when an index key is
|
||||
derived from the key of the primary database record. Normally an
|
||||
index key is derived only from the primary database record value,
|
||||
but it may be derived from the key, value or both.
|
||||
</p>
|
||||
<p>
|
||||
The following getter methods return the secondary database
|
||||
object for use by other classes in the example program. The
|
||||
secondary database object is used to create Java collections for
|
||||
accessing records via their secondary keys.
|
||||
</p>
|
||||
<a id="index_getsupplierbycitydatabase"></a>
|
||||
<pre class="programlisting">public class SampleDatabase
|
||||
{
|
||||
...
|
||||
<b class="userinput"><tt> public final SecondaryDatabase getSupplierByCityDatabase()
|
||||
{
|
||||
return supplierByCityDb;
|
||||
}</tt></b>
|
||||
...
|
||||
} </pre>
|
||||
<p>
|
||||
The following statement closes the secondary database.
|
||||
</p>
|
||||
<a id="index_close"></a>
|
||||
<pre class="programlisting">public class SampleDatabase
|
||||
{
|
||||
...
|
||||
public void close()
|
||||
throws DatabaseException {
|
||||
|
||||
<b class="userinput"><tt> supplierByCityDb.close();</tt></b>
|
||||
partDb.close();
|
||||
supplierDb.close();
|
||||
shipmentDb.close();
|
||||
javaCatalog.close();
|
||||
env.close();
|
||||
}
|
||||
...
|
||||
} </pre>
|
||||
<p>
|
||||
Secondary databases must be closed before closing their
|
||||
associated primary database.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="navfooter">
|
||||
<hr />
|
||||
<table width="100%" summary="Navigation footer">
|
||||
<tr>
|
||||
<td width="40%" align="left"><a accesskey="p" href="handlingexceptions.html">Prev</a> </td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="u" href="index.html">Up</a>
|
||||
</td>
|
||||
<td width="40%" align="right"> <a accesskey="n" href="openingforeignkeys.html">Next</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="40%" align="left" valign="top">
|
||||
Handling Exceptions
|
||||
</td>
|
||||
<td width="20%" align="center">
|
||||
<a accesskey="h" href="index.html">Home</a>
|
||||
</td>
|
||||
<td width="40%" align="right" valign="top">
|
||||
|
||||
More Secondary Key Indices
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user