mirror of
https://github.com/berkeleydb/je.git
synced 2024-11-15 01:46:24 +00:00
792 lines
30 KiB
HTML
792 lines
30 KiB
HTML
<?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>Using the BIND APIs</title>
|
||
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
|
||
<meta name="generator" content="DocBook XSL Stylesheets V1.73.2" />
|
||
<link rel="start" href="index.html" title="Getting Started with Berkeley DB Java Edition" />
|
||
<link rel="up" href="DBEntry.html" title="Chapter 8. Database Records" />
|
||
<link rel="prev" href="timetolive.html" title="Using Time to Live" />
|
||
<link rel="next" href="comparator.html" title="Using Comparators" />
|
||
</head>
|
||
<body>
|
||
<div xmlns="" class="navheader">
|
||
<div class="libver">
|
||
<p>Library Version 12.2.7.5</p>
|
||
</div>
|
||
<table width="100%" summary="Navigation header">
|
||
<tr>
|
||
<th colspan="3" align="center">Using the BIND APIs</th>
|
||
</tr>
|
||
<tr>
|
||
<td width="20%" align="left"><a accesskey="p" href="timetolive.html">Prev</a> </td>
|
||
<th width="60%" align="center">Chapter 8. Database Records</th>
|
||
<td width="20%" align="right"> <a accesskey="n" href="comparator.html">Next</a></td>
|
||
</tr>
|
||
</table>
|
||
<hr />
|
||
</div>
|
||
<div class="sect1" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h2 class="title" style="clear: both"><a id="bindAPI"></a>Using the BIND APIs</h2>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="toc">
|
||
<dl>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="bindAPI.html#bindPrimitive">Numerical and String Objects</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="bindAPI.html#object2dbt">Serializable Complex Objects</a>
|
||
</span>
|
||
</dt>
|
||
<dt>
|
||
<span class="sect2">
|
||
<a href="bindAPI.html#customTuple">Custom Tuple Bindings</a>
|
||
</span>
|
||
</dt>
|
||
</dl>
|
||
</div>
|
||
<p>Except for Java String and boolean types, efficiently moving data in
|
||
and out of Java byte arrays for storage in a database can be a nontrivial
|
||
operation. To help you with this problem, JE provides the Bind APIs.
|
||
While these APIs are described in detail in the
|
||
<span>
|
||
<em class="citetitle">Berkeley DB, Java Edition Collections Tutorial</em>,
|
||
</span>
|
||
|
||
|
||
|
||
this section provides a brief introduction to using the Bind APIs with:</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p>Single field numerical and string objects</p>
|
||
<p>Use this if you want to store a single numerical or string object,
|
||
such as <code class="classname">Long</code>, <code class="classname">Double</code>, or
|
||
<code class="classname">String</code>.</p>
|
||
</li>
|
||
<li>
|
||
<p>Complex objects that implement Java serialization.</p>
|
||
<p>Use this if you are storing objects that implement
|
||
<code class="classname">Serializable</code> and if you do not need to sort them.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>Non-serialized complex objects.</p>
|
||
<p>If you are storing objects that do not implement serialization,
|
||
you can create your own custom tuple bindings. Note that you should
|
||
use custom tuple bindings even if your objects are serializable if
|
||
you want to sort on that data.</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="bindPrimitive"></a>Numerical and String Objects</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>You can use the Bind APIs to store primitive data in a <code class="classname">DatabaseEntry</code>
|
||
object. That is, you can store a single field containing one of the following types:</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p>
|
||
<code class="classname">String</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Character</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Boolean</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Byte</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Short</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Integer</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Long</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Float</code>
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
<code class="classname">Double</code>
|
||
</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<p>
|
||
To store primitive data using the Bind APIs:
|
||
</p>
|
||
<div class="orderedlist">
|
||
<ol type="1">
|
||
<li>
|
||
<p>Create an <code class="classname">EntryBinding</code> object.</p>
|
||
<p>When you do this, you use <code class="classname">TupleBinding.getPrimitiveBinding()</code>
|
||
to return an appropriate binding for the conversion.</p>
|
||
</li>
|
||
<li>
|
||
<p>Use the <code class="classname">EntryBinding</code> object to place
|
||
the numerical object on the <code class="classname">DatabaseEntry</code>.</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<p>Once the data is stored in the DatabaseEntry, you can put it to
|
||
the database in whatever manner you wish. For example:</p>
|
||
<a id="je_dbt6"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import com.sleepycat.bind.EntryBinding;
|
||
import com.sleepycat.bind.tuple.TupleBinding;
|
||
import com.sleepycat.je.DatabaseEntry;
|
||
|
||
...
|
||
|
||
// Need a key for the put.
|
||
try {
|
||
String aKey = "myLong";
|
||
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
|
||
|
||
// Now build the DatabaseEntry using a TupleBinding
|
||
Long myLong = new Long(123456789l);
|
||
DatabaseEntry theData = new DatabaseEntry();
|
||
EntryBinding myBinding = TupleBinding.getPrimitiveBinding(Long.class);
|
||
myBinding.objectToEntry(myLong, theData);
|
||
|
||
// Now store it
|
||
myDatabase.put(null, theKey, theData);
|
||
} catch (Exception e) {
|
||
// Exception handling goes here
|
||
}</pre>
|
||
<p>Retrieval from the <code class="classname">DatabaseEntry</code> object is
|
||
performed in much the same way:</p>
|
||
<a id="je_dbt7"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import com.sleepycat.bind.EntryBinding;
|
||
import com.sleepycat.bind.tuple.TupleBinding;
|
||
|
||
import com.sleepycat.je.Database;
|
||
import com.sleepycat.je.DatabaseEntry;
|
||
import com.sleepycat.je.LockMode;
|
||
import com.sleepycat.je.OperationStatus;
|
||
|
||
...
|
||
|
||
Database myDatabase = null;
|
||
// Database open omitted for clarity
|
||
|
||
try {
|
||
// Need a key for the get
|
||
String aKey = "myLong";
|
||
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
|
||
|
||
// Need a DatabaseEntry to hold the associated data.
|
||
DatabaseEntry theData = new DatabaseEntry();
|
||
|
||
// Bindings need only be created once for a given scope
|
||
EntryBinding myBinding = TupleBinding.getPrimitiveBinding(Long.class);
|
||
|
||
// Get it
|
||
OperationStatus retVal = myDatabase.get(null, theKey, theData,
|
||
LockMode.DEFAULT);
|
||
String retKey = null;
|
||
if (retVal == OperationStatus.SUCCESS) {
|
||
// Recreate the data.
|
||
// Use the binding to convert the byte array contained in theData
|
||
// to a Long type.
|
||
Long theLong = (Long) myBinding.entryToObject(theData);
|
||
retKey = new String(theKey.getData(), "UTF-8");
|
||
System.out.println("For key: '" + retKey + "' found Long: '" +
|
||
theLong + "'.");
|
||
} else {
|
||
System.out.println("No record found for key '" + retKey + "'.");
|
||
}
|
||
} catch (Exception e) {
|
||
// Exception handling goes here
|
||
} </pre>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="object2dbt"></a>Serializable Complex Objects</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>Frequently your application requires you to store and manage
|
||
objects for your record data and/or keys. You may need to do this if you
|
||
are caching objects created by another process. You may also want to do
|
||
this if you want to store multiple data values on a record. When used
|
||
with just primitive data, or with objects containing a single data member,
|
||
JE database records effectively represent a single row in a two-column table.
|
||
By storing a complex object in the record, you can turn each record into
|
||
a single row in an <span class="emphasis"><em>n</em></span>-column table, where
|
||
<span class="emphasis"><em>n</em></span> is the number of data members contained by the
|
||
stored object(s).</p>
|
||
<p>In order to store objects in a
|
||
JE database, you must convert them to and from a <code class="literal">byte</code> array.
|
||
The first instinct for many Java programmers is to do this using Java
|
||
serialization. While this is functionally a correct solution, the result
|
||
is poor space-performance because this causes the class information
|
||
to be stored on every such database record. This information can be quite large
|
||
and it is redundant — the class information does not vary for serialized objects of the same type.
|
||
</p>
|
||
<p>
|
||
In other words, directly using serialization to place your objects into byte
|
||
arrays means that you will be storing a great deal of unnecessary information in
|
||
your database, which ultimately leads to larger databases and more expensive disk
|
||
I/O.
|
||
</p>
|
||
<p>The easiest way for you to solve this problem is to use the Bind
|
||
APIs to perform the serialization for you. Doing so causes the extra
|
||
object information to be saved off to a unique <code class="classname">Database</code>
|
||
dedicated for that purpose. This means that you do not have to duplicate
|
||
that information on each record in the <code class="classname">Database</code>
|
||
that your application is using to store its information.</p>
|
||
<p>
|
||
Note that when you use the Bind APIs to perform serialization, you still
|
||
receive all the benefits of serialization. You can still use arbitrarily
|
||
complex object graphs, and you still receive built-in class evolution
|
||
through the serialVersionUID (SUID) scheme. All of the Java
|
||
serialization rules apply without modification. For example, you can
|
||
implement Externalizable instead of Serializable.
|
||
</p>
|
||
<div class="sect3" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h4 class="title"><a id="bindCaveats"></a>Usage Caveats</h4>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>Before using the Bind APIs to perform serialization, you may
|
||
want to consider writing your own custom tuple bindings. Specifically,
|
||
avoid serialization if:
|
||
</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p>
|
||
If you need to sort based on the objects your are storing.
|
||
The sort order is meaningless for the byte arrays that you
|
||
obtain through serialization. Consequently, you should not use serialization for keys if you
|
||
care about their sort order. You should
|
||
also not use serialization for record data if your
|
||
<code class="classname">Database</code> supports duplicate records and you care about sort order.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
You want to minimize the size of your byte arrays. Even when using the Bind APIs to perform the
|
||
serialization the resulting <code class="literal">byte</code> array may be larger than necessary. You can achieve
|
||
more compact results by building your own custom tuple binding.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
You want to optimize for speed. In general, custom tuple bindings are faster than serialization at
|
||
moving data in and out of <code class="literal">byte</code> arrays.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>
|
||
You are using custom comparators. In JE, comparators are instantiated and called internally whenever
|
||
databases are not accessible. Because serial bindings depend on the class catalog, a serial binding
|
||
binding cannot be used during these times. As a result, attempting to use a serial binding with a
|
||
custom comparator will result in a <code class="literal">NullPointerException</code> during environment open or
|
||
close.
|
||
</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<p>
|
||
For information on building your own custom tuple binding, see <a class="xref" href="bindAPI.html#customTuple" title="Custom Tuple Bindings">Custom Tuple Bindings</a>.
|
||
</p>
|
||
</div>
|
||
<div class="sect3" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h4 class="title"><a id="objectSerial"></a>Serializing Objects</h4>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>To store a serializable complex object using the
|
||
Bind APIs:</p>
|
||
<div class="orderedlist">
|
||
<ol type="1">
|
||
<li>
|
||
<p>
|
||
Implement java.io.Serializable in the class whose instances that
|
||
you want to store.
|
||
</p>
|
||
</li>
|
||
<li>
|
||
<p>Open (create) your databases. You need two. The first is the
|
||
database that you use to store your data. The second is used to
|
||
store the class information.</p>
|
||
</li>
|
||
<li>
|
||
<p>Instantiate a class catalog. You do this with
|
||
<code class="classname">com.sleepycat.bind.serial.StoredClassCatalog</code>,
|
||
and at that time you must provide a handle to an open database
|
||
that is used to store the class information.</p>
|
||
</li>
|
||
<li>
|
||
<p>Create an entry binding that uses <code class="methodname">com.sleepycat.bind.serial.SerialBinding</code>.</p>
|
||
</li>
|
||
<li>
|
||
<p>Instantiate an instance of the object that you want to
|
||
store, and place it in a <code class="classname">DatabaseEntry</code>
|
||
using the entry binding that you created in the previous step.</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<p>
|
||
For example, suppose you want to store a long, double, and a
|
||
String as a record's data. Then you might create a class that
|
||
looks something like this:
|
||
</p>
|
||
<a id="je_dbt8"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import java.io.Serializable;
|
||
|
||
public class MyData implements Serializable {
|
||
private long longData;
|
||
private double doubleData;
|
||
private String description;
|
||
|
||
MyData() {
|
||
longData = 0;
|
||
doubleData = 0.0;
|
||
description = null;
|
||
}
|
||
|
||
public void setLong(long data) {
|
||
longData = data;
|
||
}
|
||
|
||
public void setDouble(double data) {
|
||
doubleData = data;
|
||
}
|
||
|
||
public void setDescription(String data) {
|
||
description = data;
|
||
}
|
||
|
||
public long getLong() {
|
||
return longData;
|
||
}
|
||
|
||
public double getDouble() {
|
||
return doubleData;
|
||
}
|
||
|
||
public String getDescription() {
|
||
return description;
|
||
}
|
||
}</pre>
|
||
<p>You can then store instances of this class as follows:</p>
|
||
<a id="je_dbt9"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import com.sleepycat.bind.EntryBinding;
|
||
import com.sleepycat.bind.serial.StoredClassCatalog;
|
||
import com.sleepycat.bind.serial.SerialBinding;
|
||
|
||
import com.sleepycat.je.Database;
|
||
import com.sleepycat.je.DatabaseConfig;
|
||
import com.sleepycat.je.DatabaseEntry;
|
||
|
||
...
|
||
|
||
// The key data.
|
||
String aKey = "myData";
|
||
|
||
// The data data
|
||
MyData data2Store = new MyData();
|
||
data2Store.setLong(123456789l);
|
||
data2Store.setDouble(1234.9876543);
|
||
data2Store.setDescription("A test instance of this class");
|
||
|
||
try {
|
||
// Environment open omitted for brevity
|
||
|
||
// Open the database that you will use to store your data
|
||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||
myDbConfig.setAllowCreate(true);
|
||
myDbConfig.setSortedDuplicates(true);
|
||
Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);
|
||
|
||
// Open the database that you use to store your class information.
|
||
// The db used to store class information does not require duplicates
|
||
// support.
|
||
myDbConfig.setSortedDuplicates(false);
|
||
Database myClassDb = myDbEnv.openDatabase(null, "classDb",
|
||
myDbConfig);
|
||
|
||
// Instantiate the class catalog
|
||
StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);
|
||
|
||
// Create the binding
|
||
EntryBinding dataBinding = new SerialBinding(classCatalog,
|
||
MyData.class);
|
||
|
||
// Create the DatabaseEntry for the key
|
||
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
|
||
|
||
// Create the DatabaseEntry for the data. Use the EntryBinding object
|
||
// that was just created to populate the DatabaseEntry
|
||
DatabaseEntry theData = new DatabaseEntry();
|
||
dataBinding.objectToEntry(data2Store, theData);
|
||
|
||
// Put it as normal
|
||
myDatabase.put(null, theKey, theData);
|
||
|
||
// Database and environment close omitted for brevity
|
||
} catch (Exception e) {
|
||
// Exception handling goes here
|
||
}</pre>
|
||
</div>
|
||
<div class="sect3" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h4 class="title"><a id="objectDeserial"></a>Deserializing Objects</h4>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>Once an object is stored in the database, you can retrieve the
|
||
<code class="classname">MyData</code> objects from the retrieved
|
||
<code class="classname">DatabaseEntry</code> using the Bind APIs in much the
|
||
same way as is described above. For example:</p>
|
||
<a id="je_dbt10"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import com.sleepycat.bind.EntryBinding;
|
||
import com.sleepycat.bind.serial.StoredClassCatalog;
|
||
import com.sleepycat.bind.serial.SerialBinding;
|
||
|
||
import com.sleepycat.je.Database;
|
||
import com.sleepycat.je.DatabaseConfig;
|
||
import com.sleepycat.je.DatabaseEntry;
|
||
import com.sleepycat.je.LockMode;
|
||
|
||
...
|
||
|
||
// The key data.
|
||
String aKey = "myData";
|
||
|
||
try {
|
||
// Environment open omitted for brevity.
|
||
|
||
// Open the database that stores your data
|
||
DatabaseConfig myDbConfig = new DatabaseConfig();
|
||
myDbConfig.setAllowCreate(false);
|
||
Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig);
|
||
|
||
// Open the database that stores your class information.
|
||
Database myClassDb = myDbEnv.openDatabase(null, "classDb",
|
||
myDbConfig);
|
||
|
||
// Instantiate the class catalog
|
||
StoredClassCatalog classCatalog = new StoredClassCatalog(myClassDb);
|
||
|
||
// Create the binding
|
||
EntryBinding dataBinding = new SerialBinding(classCatalog,
|
||
MyData.class);
|
||
|
||
// Create DatabaseEntry objects for the key and data
|
||
DatabaseEntry theKey = new DatabaseEntry(aKey.getBytes("UTF-8"));
|
||
DatabaseEntry theData = new DatabaseEntry();
|
||
|
||
// Do the get as normal
|
||
myDatabase.get(null, theKey, theData, LockMode.DEFAULT);
|
||
|
||
// Recreate the MyData object from the retrieved DatabaseEntry using
|
||
// the EntryBinding created above
|
||
MyData retrievedData = (MyData) dataBinding.entryToObject(theData);
|
||
|
||
// Database and environment close omitted for brevity
|
||
} catch (Exception e) {
|
||
// Exception handling goes here
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
<div class="sect2" lang="en" xml:lang="en">
|
||
<div class="titlepage">
|
||
<div>
|
||
<div>
|
||
<h3 class="title"><a id="customTuple"></a>Custom Tuple Bindings</h3>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p>
|
||
If you want to store complex objects in your database, then you can use
|
||
tuple bindings to do this. While they are more work to write and
|
||
maintain than if you were to use serialization, the
|
||
<code class="literal">byte</code> array conversion is faster. In addition, custom
|
||
tuple bindings should allow you to create <code class="literal">byte</code> arrays
|
||
that are smaller than those created by serialization. Custom tuple
|
||
bindings also allow you to optimize your BTree comparisons, whereas
|
||
serialization does not.
|
||
</p>
|
||
<p>
|
||
For information on using serialization to store complex objects, see
|
||
<a class="xref" href="bindAPI.html#object2dbt" title="Serializable Complex Objects">Serializable Complex Objects</a>.
|
||
</p>
|
||
<p>To store complex objects using a custom tuple binding:</p>
|
||
<div class="orderedlist">
|
||
<ol type="1">
|
||
<li>
|
||
<p>Implement the class whose instances that you want to store.
|
||
Note that you do not have to implement the Serializable interface.</p>
|
||
</li>
|
||
<li>
|
||
<p>Write a tuple binding using the <code class="classname">com.sleepycat.bind.tuple.TupleBinding</code>
|
||
class.</p>
|
||
</li>
|
||
<li>
|
||
<p>Open (create) your database. Unlike serialization, you only
|
||
need one.</p>
|
||
</li>
|
||
<li>
|
||
<p>Create an entry binding that uses the tuple binding that you
|
||
implemented in step 2.</p>
|
||
</li>
|
||
<li>
|
||
<p>Instantiate an instance of the object that you want to store,
|
||
and place it in a <code class="classname">DatabaseEntry</code> using the
|
||
entry binding that you created in the previous step.</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
<p>
|
||
For example, suppose you want to your keys to be instances of the
|
||
following class:
|
||
</p>
|
||
<a id="je_dbt11"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
public class MyData2 {
|
||
private long longData;
|
||
private Double doubleData;
|
||
private String description;
|
||
|
||
public MyData2() {
|
||
longData = 0;
|
||
doubleData = new Double(0.0);
|
||
description = "";
|
||
}
|
||
|
||
public void setLong(long data) {
|
||
longData = data;
|
||
}
|
||
|
||
public void setDouble(Double data) {
|
||
doubleData = data;
|
||
}
|
||
|
||
public void setString(String data) {
|
||
description = data;
|
||
}
|
||
|
||
public long getLong() {
|
||
return longData;
|
||
}
|
||
|
||
public Double getDouble() {
|
||
return doubleData;
|
||
}
|
||
|
||
public String getString() {
|
||
return description;
|
||
}
|
||
} </pre>
|
||
<p>In this case, you need to write a tuple binding for the
|
||
<code class="classname">MyData2</code> class. When you do this, you must
|
||
implement the <code class="methodname">TupleBinding.objectToEntry()</code>
|
||
and <code class="methodname">TupleBinding.entryToObject()</code> abstract methods.
|
||
Remember the following as you implement these methods:</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p>You use <code class="methodname">TupleBinding.objectToEntry()</code> to convert
|
||
objects to <code class="literal">byte</code> arrays. You use
|
||
<code class="classname">com.sleepycat.bind.tuple.TupleOutput</code> to write
|
||
primitive data types to the <code class="literal">byte</code> array. Note that
|
||
<code class="classname">TupleOutput</code> provides methods that allows
|
||
you to work with numerical types (<code class="literal">long</code>,
|
||
<code class="literal">double</code>, <code class="literal">int</code>, and so forth) and
|
||
not the corresponding <code class="literal">java.lang</code> numerical
|
||
classes.</p>
|
||
</li>
|
||
<li>
|
||
<p>The order that you write data to the <code class="literal">byte</code>
|
||
array in <code class="methodname">TupleBinding.objectToEntry()</code> is the order that
|
||
it appears in the array. So given the <code class="classname">MyData2</code>
|
||
class as an example, if you write <code class="literal">description</code>,
|
||
<code class="literal">doubleData</code>, and then <code class="literal">longData</code>,
|
||
then the resulting byte array will contain these data elements in
|
||
that order. This means that your records will sort based on the
|
||
value of the <code class="literal">description</code> data member and then
|
||
the <code class="literal">doubleData</code> member, and so forth. If you
|
||
prefer to sort based on, say, the <code class="literal">longData</code> data
|
||
member, write it to the byte array first.</p>
|
||
</li>
|
||
<li>
|
||
<p>You use <code class="methodname">TupleBinding.entryToObject()</code> to convert
|
||
the <code class="literal">byte</code> array back into an instance of your
|
||
original class. You use <code class="classname">com.sleepycat.bind.tuple.TupleInput</code>
|
||
to get data from the <code class="literal">byte</code> array.</p>
|
||
</li>
|
||
<li>
|
||
<p>The order that you read data from the <code class="literal">byte</code>
|
||
array must be exactly the same as the order in which it was written.</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<p>For example:</p>
|
||
<a id="je_dbt12"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import com.sleepycat.bind.tuple.TupleBinding;
|
||
import com.sleepycat.bind.tuple.TupleInput;
|
||
import com.sleepycat.bind.tuple.TupleOutput;
|
||
|
||
public class MyTupleBinding extends TupleBinding {
|
||
|
||
// Write a MyData2 object to a TupleOutput
|
||
public void objectToEntry(Object object, TupleOutput to) {
|
||
|
||
MyData2 myData = (MyData2)object;
|
||
|
||
// Write the data to the TupleOutput (a DatabaseEntry).
|
||
// Order is important. The first data written will be
|
||
// the first bytes used by the default comparison routines.
|
||
to.writeDouble(myData.getDouble().doubleValue());
|
||
to.writeLong(myData.getLong());
|
||
to.writeString(myData.getString());
|
||
}
|
||
|
||
// Convert a TupleInput to a MyData2 object
|
||
public Object entryToObject(TupleInput ti) {
|
||
|
||
// Data must be read in the same order that it was
|
||
// originally written.
|
||
Double theDouble = new Double(ti.readDouble());
|
||
long theLong = ti.readLong();
|
||
String theString = ti.readString();
|
||
|
||
MyData2 myData = new MyData2();
|
||
myData.setDouble(theDouble);
|
||
myData.setLong(theLong);
|
||
myData.setString(theString);
|
||
|
||
return myData;
|
||
}
|
||
} </pre>
|
||
<p>In order to use the tuple binding, instantiate the binding and
|
||
then use:</p>
|
||
<div class="itemizedlist">
|
||
<ul type="disc">
|
||
<li>
|
||
<p><code class="methodname">MyTupleBinding.objectToEntry()</code> to
|
||
convert a MyData2 object to a <code class="classname">DatabaseEntry</code>.</p>
|
||
</li>
|
||
<li>
|
||
<p><code class="methodname">MyTupleBinding.entryToObject()</code> to convert
|
||
a <code class="classname">DatabaseEntry</code> to a <code class="classname">MyData2</code>
|
||
object.</p>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<p>For example:</p>
|
||
<a id="je_dbt13"></a>
|
||
<pre class="programlisting">package je.gettingStarted;
|
||
|
||
import com.sleepycat.bind.tuple.TupleBinding;
|
||
import com.sleepycat.je.DatabaseEntry;
|
||
|
||
...
|
||
|
||
TupleBinding keyBinding = new MyTupleBinding();
|
||
|
||
MyData2 theKeyData = new MyData2();
|
||
theKeyData.setLong(123456789l);
|
||
theKeyData.setDouble(new Double(12345.6789));
|
||
theKeyData.setString("My key data");
|
||
|
||
DatabaseEntry myKey = new DatabaseEntry();
|
||
|
||
try {
|
||
// Store theKeyData in the DatabaseEntry
|
||
keyBinding.objectToEntry(theKeyData, myKey);
|
||
|
||
...
|
||
// Database put and get activity omitted for clarity
|
||
...
|
||
|
||
// Retrieve the key data
|
||
theKeyData = (MyData2) keyBinding.entryToObject(myKey);
|
||
} catch (Exception e) {
|
||
// Exception handling goes here
|
||
}</pre>
|
||
</div>
|
||
</div>
|
||
<div class="navfooter">
|
||
<hr />
|
||
<table width="100%" summary="Navigation footer">
|
||
<tr>
|
||
<td width="40%" align="left"><a accesskey="p" href="timetolive.html">Prev</a> </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="u" href="DBEntry.html">Up</a>
|
||
</td>
|
||
<td width="40%" align="right"> <a accesskey="n" href="comparator.html">Next</a></td>
|
||
</tr>
|
||
<tr>
|
||
<td width="40%" align="left" valign="top">Using Time to Live </td>
|
||
<td width="20%" align="center">
|
||
<a accesskey="h" href="index.html">Home</a>
|
||
</td>
|
||
<td width="40%" align="right" valign="top"> Using Comparators</td>
|
||
</tr>
|
||
</table>
|
||
</div>
|
||
</body>
|
||
</html>
|