else to do with the DPL API) comes out
of the com.sleepycat.persist package.
For future tests, this code is moved
to an @Before-annotated openDatabase
method and an @After-annotated
closeDatabase method, as shown in
Listing 2.
Notice that I deliberately chose to
delete the directory and re-create it each
time just to ensure that no data files are
lingering after each test. Obviously, for
a production system, the logic would
be different.
Entities
Just as with the JPA or any other object-based storage system, when working
with the DPL API, we store and retrieve
instances of objects.
Oracle Berkeley DB Java Edition knows
that these objects are to be persisted
because the class is annotated with
the @Entity annotation. In addition, at
least one field on the class must also be
annotated with the @PrimaryKey annotation, whose purpose seems obvious,
but whose actual use is different than in
some other ORM systems.
For this example, let’s assume the
system is a blog engine (see Listing 3).
While it might appear that we could
store a new blog post to the EntityStore
through some kind of “store” method
on the EntityStore, it’s not that simple.
The Oracle Berkeley DB Java Edition
engine insists that we pay closer attention to the indexes defined within the
store. The most obvious index is the
one that keys off the @PrimaryKey for a
given type.
To store or retrieve an object by its
primary key, we first have to obtain that
index (a PrimaryIndex<K,V> type, where K
is the PrimaryKey-annotated type and V
is the Entity-annotated type that owns it)
from the EntityStore.
Once that’s done, we can use the
PrimaryIndex to put objects into the
EntityStore and use get to retrieve objects
from the EntityStore by the PrimaryKey, as
shown in Listing 4.
Nary an SQL statement is found,
which is great, assuming that the exact
object (or at least its primary key value)
is known to the code doing the lookup
for the object. Sometimes, though, the
entire list of objects (such as a list of the
last 10 blog posts) must be looked at, in
which case an entity iterator is needed,
which is, again, retrieved from the
PrimaryIndex<> object (see Listing 5).
Take very careful note of the close() call
on the cursor at finish—failing to do so
will yield an exception from the database runtime when the database itself is
closed. (This is best dropped into a finally
block, but because these are just exploration tests, we can live with it the way it
is for now.)
For those cases where the primary
key needs to be an artificial key, such as
in a monotonically increasing numeric
sequence, Oracle Berkeley DB Java
Edition’s API can generate that key automatically by modifying the @PrimaryKey
annotation to use a “sequence,” for
example:
public class BDBTest
{
// ...
File dbDir = new File("./data");
Environment dbEnv;
EntityStore dbStore;
@Before public void openDatabase()
{
if (!dbDir.exists())
dbDir.mkdir();
JAVA IN ACTION
EnvironmentConfig config = new EnvironmentConfig();
config.setAllowCreate(true);
dbEnv = new Environment(dbDir, config);
StoreConfig storeConfig = new StoreConfig();
storeConfig.setAllowCreate(true);
dbStore = new EntityStore(dbEnv, "EntityStore", storeConfig);
}
@After public void closeDatabase()
{
dbStore.close();
dbEnv.close();
dbDir.delete();
}
}
ABOUT US
Download all listings in this issue as text
private @PrimaryKey(sequence=
"Sequence_Namespace") int id;
This is equivalent to using globally unique identifiers (GUIDs) as your
primary key—keys that are entirely
opaque and for which the value is
irrelevant to the actual contents of the
object. Any ability to browse objects
and fetch them directly by primary key
is lost, but nasty business problems are
avoided when using mutable state for
primary keys.
Secondary Keys
While this is great, sometimes we need
to fetch objects by a criterion other
than the primary key. For example, in
a blog system, the blog often needs to
show the blog entries for a given day,
rather than by their title. This means
that the database has to pony up the
objects via a lookup scheme other than
the primary key.