Internally, JE databases are organized as BTrees. This means that most database operations (inserts, deletes, reads, and so forth) involve BTree node comparisons. This comparison most frequently occurs based on database keys, but if your database supports duplicate records then comparisons can also occur based on the database data.
By default, JE performs all such comparisons using a byte-by-byte lexicographic comparison. This mechanism works well for most data. However, in some cases you may need to specify your own comparison routine. One frequent reason for this is to perform a language sensitive lexical ordering of string keys.
You override the default comparison function by providing a Java
Comparator
class to the database.
The Java Comparator
interface requires you to implement the
Comparator.compare()
method
(see http://java.sun.com/j2se/1.4.2/docs/api/java/util/Comparator.html for details).
JE passes your Comparator.compare()
method
the byte
arrays that you stored in the database. If
you know how your data is organized in the byte
array, then you can write a comparison routine that directly examines
the contents of the arrays. Otherwise, you have to reconstruct your
original objects, and then perform the comparison.
For example, suppose you want to perform unicode lexical comparisons
instead of UTF-8 byte-by-byte comparisons. Then you could provide a
comparator that uses String.compareTo()
,
which performs a Unicode comparison of two strings (note that for
single-byte roman characters, Unicode comparison and UTF-8
byte-by-byte comparisons are identical – this is something you
would only want to do if you were using multibyte unicode characters
with JE). In this case, your comparator would look like the
following:
package je.gettingStarted; import java.util.Comparator; public class MyDataComparator implements Comparator { public MyDataComparator() {} public int compare(Object d1, Object d2) { byte[] b1 = (byte[])d1; byte[] b2 = (byte[])d2; String s1 = new String(b1, "UTF-8"); String s2 = new String(b2, "UTF-8"); return s1.compareTo(s2); } }
You specify a Comparator
using the following
methods. Note that by default these methods can only be used at database
creation time, and they are ignored for normal database opens. Also,
note that JE uses the no-argument constructor for these comparators.
Further, it is not allowable for there to be a mutable state in these
comparators or else unpredictable results will occur.
DatabaseConfig.setBtreeComparator()
Sets the Java Comparator
class used
to compare two keys in the database.
DatabaseConfig.setDuplicateComparator()
Sets the Java Comparator
class used to compare the
data on two duplicate records in the database. This comparator is
used only if the database supports duplicate records.
You can use the above methods to set a database's comparator after database creation time if you explicitly indicate that the comparator is to be overridden. You do this by using the following methods:
If you override your comparator, the new comparator must preserve the sort order implemented by your original comparator. That is, the new comparator and the old comparator must return the same value for the comparison of any two valid objects. Failure to observe this constraint will cause unpredictable results for your application.
If you want to change the fundamental sort order for your database, back up the contents of the database, delete the database, recreate it, and then reload its data.
DatabaseConfig.setOverrideBtreeComparator()
If set to true
, causes the database's Btree
comparator to be overridden with the
Comparator
specified on
DatabaseConfig.setBtreeComparator()
. This
method can be used to change the comparator post-environment
creation.
DatabaseConfig.setOverrideDuplicateComparator()
If set to true
, causes the database's
duplicates comparator to be overridden with the
Comparator
specified on
DatabaseConfig.setDuplicateComparator()
.
For example, to use the Comparator
described in the previous section:
package je.gettingStarted; import com.sleepycat.je.Database; import com.sleepycat.je.DatabaseConfig; import com.sleepycat.je.DatabaseException; import java.util.Comparator; ... // Environment open omitted for brevity try { // Get the database configuration object DatabaseConfig myDbConfig = new DatabaseConfig(); myDbConfig.setAllowCreate(true); // Set the duplicate comparator class myDbConfig.setDuplicateComparator(MyDataComparator.class); // Open the database that you will use to store your data myDbConfig.setSortedDuplicates(true); Database myDatabase = myDbEnv.openDatabase(null, "myDb", myDbConfig); } catch (DatabaseException dbe) { // Exception handling goes here }