795 lines
33 KiB
HTML
795 lines
33 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
|
|
<!--NewPage-->
|
|
<HTML>
|
|
<HEAD>
|
|
<!-- Generated by javadoc (build 1.5.0) on Thu May 15 17:17:33 EDT 2008 -->
|
|
<TITLE>
|
|
com.sleepycat.persist (Oracle - Berkeley DB Java API)
|
|
</TITLE>
|
|
|
|
<META NAME="keywords" CONTENT="com.sleepycat.persist package">
|
|
|
|
<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../style.css" TITLE="Style">
|
|
|
|
<SCRIPT type="text/javascript">
|
|
function windowTitle()
|
|
{
|
|
parent.document.title="com.sleepycat.persist (Oracle - Berkeley DB Java API)";
|
|
}
|
|
</SCRIPT>
|
|
<NOSCRIPT>
|
|
</NOSCRIPT>
|
|
|
|
</HEAD>
|
|
|
|
<BODY BGCOLOR="white" onload="windowTitle();">
|
|
|
|
|
|
<!-- ========= START OF TOP NAVBAR ======= -->
|
|
<A NAME="navbar_top"><!-- --></A>
|
|
<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
|
|
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
|
|
<TR>
|
|
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
|
|
<A NAME="navbar_top_firstrow"><!-- --></A>
|
|
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
|
|
<TR ALIGN="center" VALIGN="top">
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Package</B></FONT> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-use.html"><FONT CLASS="NavBarFont1"><B>Use</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
|
|
</TR>
|
|
</TABLE>
|
|
</TD>
|
|
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
|
|
<b>Berkeley DB</b><br><font size="-1"> version 4.7.25</font></EM>
|
|
</TD>
|
|
</TR>
|
|
|
|
<TR>
|
|
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
|
<A HREF="../../../com/sleepycat/db/package-summary.html"><B>PREV PACKAGE</B></A>
|
|
<A HREF="../../../com/sleepycat/persist/evolve/package-summary.html"><B>NEXT PACKAGE</B></A></FONT></TD>
|
|
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
|
<A HREF="../../../index.html?com/sleepycat/persist/package-summary.html" target="_top"><B>FRAMES</B></A>
|
|
<A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A>
|
|
<SCRIPT type="text/javascript">
|
|
<!--
|
|
if(window==top) {
|
|
document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
|
|
}
|
|
//-->
|
|
</SCRIPT>
|
|
<NOSCRIPT>
|
|
<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
|
|
</NOSCRIPT>
|
|
|
|
|
|
</FONT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
<A NAME="skip-navbar_top"></A>
|
|
<!-- ========= END OF TOP NAVBAR ========= -->
|
|
|
|
<HR>
|
|
<H2>
|
|
Package com.sleepycat.persist
|
|
</H2>
|
|
The Direct Persistence Layer (DPL) adds a persistent object model to the
|
|
Berkeley DB transactional engine.
|
|
<P>
|
|
<B>See:</B>
|
|
<BR>
|
|
<A HREF="#package_description"><B>Description</B></A>
|
|
<P>
|
|
|
|
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
|
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
|
|
<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
|
|
<B>Interface Summary</B></FONT></TH>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/DatabaseNamer.html" title="interface in com.sleepycat.persist">DatabaseNamer</A></B></TD>
|
|
<TD>Determines the file names to use for primary and secondary databases.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/EntityCursor.html" title="interface in com.sleepycat.persist">EntityCursor<V></A></B></TD>
|
|
<TD>Traverses entity values or key values and allows deleting or updating the
|
|
entity at the current cursor position.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/EntityIndex.html" title="interface in com.sleepycat.persist">EntityIndex<K,V></A></B></TD>
|
|
<TD>The interface for accessing keys and entities via a primary or secondary
|
|
index.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/ForwardCursor.html" title="interface in com.sleepycat.persist">ForwardCursor<V></A></B></TD>
|
|
<TD>Cursor operations limited to traversing forward.</TD>
|
|
</TR>
|
|
</TABLE>
|
|
|
|
|
|
<P>
|
|
|
|
<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
|
|
<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
|
|
<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
|
|
<B>Class Summary</B></FONT></TH>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/EntityJoin.html" title="class in com.sleepycat.persist">EntityJoin<PK,E></A></B></TD>
|
|
<TD>Performs an equality join on two or more secondary keys.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/EntityStore.html" title="class in com.sleepycat.persist">EntityStore</A></B></TD>
|
|
<TD>A store for managing persistent entity objects.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/PrimaryIndex.html" title="class in com.sleepycat.persist">PrimaryIndex<PK,E></A></B></TD>
|
|
<TD>The primary index for an entity class and its primary key.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/SecondaryIndex.html" title="class in com.sleepycat.persist">SecondaryIndex<SK,PK,E></A></B></TD>
|
|
<TD>The secondary index for an entity class and a secondary key.</TD>
|
|
</TR>
|
|
<TR BGCOLOR="white" CLASS="TableRowColor">
|
|
<TD WIDTH="15%"><B><A HREF="../../../com/sleepycat/persist/StoreConfig.html" title="class in com.sleepycat.persist">StoreConfig</A></B></TD>
|
|
<TD>Configuration properties used with an <A HREF="../../../com/sleepycat/persist/EntityStore.html" title="class in com.sleepycat.persist"><CODE>EntityStore</CODE></A> or <A HREF="../../../com/sleepycat/persist/raw/RawStore.html" title="class in com.sleepycat.persist.raw"><CODE>RawStore</CODE></A>.</TD>
|
|
</TR>
|
|
</TABLE>
|
|
|
|
|
|
<P>
|
|
<A NAME="package_description"><!-- --></A><H2>
|
|
Package com.sleepycat.persist Description
|
|
</H2>
|
|
|
|
<P>
|
|
The Direct Persistence Layer (DPL) adds a persistent object model to the
|
|
Berkeley DB transactional engine.
|
|
|
|
<h1>Package Specification</h1>
|
|
|
|
<ul>
|
|
<li><a href="#intro">Introduction</a></li>
|
|
<li><a href="#model">The Entity Model</a></li>
|
|
<li><a href="#example">A brief example</a></li>
|
|
<li><a href="#whichAPI">Which API to use?</a></li>
|
|
<li><a href="#java14and15">Java 1.5 dependencies</a>
|
|
<ul>
|
|
<li><a href="#genericTypes">Generic Types</a></li>
|
|
<li><a href="#annotations">Annotations</a></li>
|
|
</ul>
|
|
</li>
|
|
<li><a href="#bytecode">Bytecode Enhancement</a></li>
|
|
</ul>
|
|
|
|
<a name="intro"><h2>Introduction</h2></a>
|
|
|
|
<p>The Direct Persistence Layer (DPL) was designed to meet the following
|
|
requirements.</p>
|
|
<ul>
|
|
<li>A type safe and convenient API is provided for accessing persistent
|
|
objects. The use of Java generic types, although optional, is fully exploited
|
|
to provide type safety. For example:
|
|
<pre class="code">
|
|
PrimaryIndex<Long,Employer> employerById = ...;
|
|
long employerId = ...;
|
|
Employer employer = employerById.get(employerId);</pre>
|
|
</li>
|
|
<li>All Java types are allowed to be persistent without requiring that they
|
|
implement special interfaces. Persistent fields may be <code>private</code>,
|
|
package-private (default access), <code>protected</code>, or <code>public</code>. No
|
|
hand-coding of bindings is required. However, each persistent class must have
|
|
a default constructor. For example:
|
|
<pre class="code">
|
|
@Persistent
|
|
class Address {
|
|
String street;
|
|
String city;
|
|
String state;
|
|
int zipCode;
|
|
private Address() {}
|
|
}</pre>
|
|
</li>
|
|
<li>Bytecode enhancement provides fully optimized bindings that do not use Java
|
|
reflection.</li>
|
|
<li>It is easy to define primary and secondary keys. No external schema is
|
|
required and Java annotations may be used for defining all metadata.
|
|
Extensions may derive metadata from other sources. For example, the following
|
|
Employer class is defined as a persistent entity with a primary key field
|
|
<code>id</code> and the secondary key field <code>name</code>:</li>
|
|
<pre class="code">
|
|
@Entity
|
|
class Employer {
|
|
|
|
@PrimaryKey(sequence="ID")
|
|
long id;
|
|
|
|
@SecondaryKey(relate=ONE_TO_ONE)
|
|
String name;
|
|
|
|
Address address;
|
|
|
|
private Employer() {}
|
|
}</pre>
|
|
<li>Interoperability with external components is supported via the Java
|
|
collections framework. Any primary or secondary index can be accessed using a
|
|
standard <code>java.util</code> collection. For example:
|
|
<pre class="code">java.util.SortedMap<String,Employer> map = employerByName.sortedMap();</pre>
|
|
</li>
|
|
<li>Class evolution is explicitly supported. Compatible changes (adding fields
|
|
and type widening) are performed automatically and transparently. For example,
|
|
without any special configuration a <code>street2</code> field may be added to the
|
|
<code>Address</code> class and the type of the <code>zipCode</code> field may be changed
|
|
from <code>int</code> to <code>long</code>:
|
|
<pre class="code">
|
|
@Persistent
|
|
class Address {
|
|
String street;
|
|
String street2;
|
|
String city;
|
|
String state;
|
|
long zipCode;
|
|
private Address() {}
|
|
}</pre>
|
|
Many incompatible class changes, such as renaming fields or refactoring a
|
|
single class, can be performed using <A HREF="../../../com/sleepycat/persist/evolve/Mutations.html" title="class in com.sleepycat.persist.evolve"><CODE>Mutations</CODE></A>. Mutations are automatically
|
|
applied lazily as data is accessed, avoiding downtime to convert large
|
|
databases during a software upgrade.
|
|
<p>Complex refactoring involving multiple classes may be performed using the a
|
|
<a href="package-summary.html#storeConversion">store conversion</a>. The DPL
|
|
always provides access to your data via a <code>RawStore</code>, no matter what
|
|
changes have been made to persistent classes.</p>
|
|
</li>
|
|
<br>
|
|
<li>The performance of the Berkeley DB transactional engine is not compromised.
|
|
Operations are internally mapped directly to the engine API, object bindings
|
|
are lightweight, and all engine tuning parameters are available. For example,
|
|
a "dirty read" may be performed using an optional <A HREF="../../../com/sleepycat/db/LockMode.html" title="class in com.sleepycat.db"><CODE>LockMode</CODE></A> parameter:
|
|
<pre class="code">Employer employer = employerByName.get(null, "Gizmo Inc", LockMode.READ_UNCOMMITTED);</pre>
|
|
For high performance applications, <A HREF="../../../com/sleepycat/db/DatabaseConfig.html" title="class in com.sleepycat.db"><CODE>DatabaseConfig</CODE></A> parameters may be used to tune the performance of the Berkeley
|
|
DB engine. For example, the size of an internal Btree node can be specified
|
|
as follows:
|
|
<pre class="code">
|
|
DatabaseConfig config = store.getPrimaryConfig(Employer.class);
|
|
config.setNodeMaxEntries(64);
|
|
store.setPrimaryConfig(config);</pre>
|
|
</li>
|
|
</ul>
|
|
|
|
<a name="model"><h2>The Entity Model</h2></a>
|
|
|
|
<p>The DPL is intended for applications that represent persistent domain
|
|
objects using Java classes. An <em>entity class</em> is an ordinary Java class
|
|
that has a primary key and is stored and accessed using a primary index. It
|
|
may also have any number of secondary keys, and entities may be accessed by
|
|
secondary key using a secondary index.</p>
|
|
|
|
<p>An entity class may be defined with the <A HREF="../../../com/sleepycat/persist/model/Entity.html" title="annotation in com.sleepycat.persist.model"><CODE>Entity</CODE></A> annotation. For each entity class,
|
|
its primary key may be defined using the <A HREF="../../../com/sleepycat/persist/model/PrimaryKey.html" title="annotation in com.sleepycat.persist.model"><CODE>PrimaryKey</CODE></A> annotation and any number of
|
|
secondary keys may be defined using the <A HREF="../../../com/sleepycat/persist/model/SecondaryKey.html" title="annotation in com.sleepycat.persist.model"><CODE>SecondaryKey</CODE></A> annotation.</p>
|
|
|
|
<p>In the following example, the <code>Person.ssn</code> (social security number)
|
|
field is the primary key and the <code>Person.employerIds</code> field is a
|
|
many-to-many secondary key.</p>
|
|
<pre class="code">
|
|
@Entity
|
|
class Person {
|
|
|
|
@PrimaryKey
|
|
String ssn;
|
|
|
|
String name;
|
|
Address address;
|
|
|
|
@SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Employer.class)
|
|
Set<Long> employerIds = new HashSet<Long>();
|
|
|
|
private Person() {} // For bindings
|
|
}</pre>
|
|
|
|
<p>A set of entity classes constitutes an <em>entity model</em>. In addition
|
|
to isolated entity classes, an entity model may contain relationships between
|
|
entities. Relationships may be defined using the <A HREF="../../../com/sleepycat/persist/model/SecondaryKey.html" title="annotation in com.sleepycat.persist.model"><CODE>SecondaryKey</CODE></A> annotation.
|
|
Many-to-one, one-to-many, many-to-many and one-to-one relationships are
|
|
supported, as well as foreign key constraints.</p>
|
|
|
|
<p>In the example above, a relationship between the <code>Person</code> and <code>Employer</code> entities is defined via the <code>Person.employerIds</code> field. The
|
|
<code>relatedEntity=Employer.class</code> annotation property establishes foreign
|
|
key constraints to guarantee that every element of the <code>employerIds</code> set
|
|
is a valid <code>Employer</code> primary key.</p>
|
|
|
|
<p>For more information on the entity model, see the <A HREF="../../../com/sleepycat/persist/model/AnnotationModel.html" title="class in com.sleepycat.persist.model"><CODE>AnnotationModel</CODE></A> and the <A HREF="../../../com/sleepycat/persist/model/Entity.html" title="annotation in com.sleepycat.persist.model"><CODE>Entity</CODE></A> annotation.</p>
|
|
|
|
<p>The root object in the DPL is the <A HREF="../../../com/sleepycat/persist/EntityStore.html" title="class in com.sleepycat.persist"><CODE>EntityStore</CODE></A>. An entity store manages any number of objects for each entity
|
|
class defined in the model. The store provides access to the primary and
|
|
secondary indices for each entity class, for example:</p>
|
|
|
|
<pre class="code">
|
|
EntityStore store = new EntityStore(...);
|
|
|
|
PrimaryIndex<String,Person> personBySsn =
|
|
store.getPrimaryIndex(String.class, Person.class);</pre>
|
|
|
|
<a name="example"><h2>A brief example</h2></a>
|
|
|
|
<p>The following example shows how to define an entity model and how to store
|
|
and access persistent objects. Exception handling is omitted for brevity.</p>
|
|
|
|
<pre class="code">
|
|
import java.io.File;
|
|
import java.util.HashSet;
|
|
import java.util.Set;
|
|
|
|
import com.sleepycat.db.DatabaseException;
|
|
import com.sleepycat.db.Environment;
|
|
import com.sleepycat.db.EnvironmentConfig;
|
|
import com.sleepycat.persist.EntityCursor;
|
|
import com.sleepycat.persist.EntityIndex;
|
|
import com.sleepycat.persist.EntityStore;
|
|
import com.sleepycat.persist.PrimaryIndex;
|
|
import com.sleepycat.persist.SecondaryIndex;
|
|
import com.sleepycat.persist.StoreConfig;
|
|
import com.sleepycat.persist.model.Entity;
|
|
import com.sleepycat.persist.model.Persistent;
|
|
import com.sleepycat.persist.model.PrimaryKey;
|
|
import com.sleepycat.persist.model.SecondaryKey;
|
|
import static com.sleepycat.persist.model.DeleteAction.NULLIFY;
|
|
import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
|
|
import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
|
|
import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
|
|
import static com.sleepycat.persist.model.Relationship.MANY_TO_MANY;
|
|
|
|
// An entity class.
|
|
//
|
|
@Entity
|
|
class Person {
|
|
|
|
@PrimaryKey
|
|
String ssn;
|
|
|
|
String name;
|
|
Address address;
|
|
|
|
@SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class)
|
|
String parentSsn;
|
|
|
|
@SecondaryKey(relate=ONE_TO_MANY)
|
|
Set<String> emailAddresses = new HashSet<String>();
|
|
|
|
<code>@SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Employer.class,
|
|
onRelatedEntityDelete=NULLIFY)</code>
|
|
<code>Set<Long> employerIds = new HashSet<Long>();</code>
|
|
|
|
Person(String name, String ssn, String parentSsn) {
|
|
this.name = name;
|
|
this.ssn = ssn;
|
|
this.parentSsn = parentSsn;
|
|
}
|
|
|
|
private Person() {} // For bindings
|
|
}
|
|
|
|
// Another entity class.
|
|
//
|
|
@Entity
|
|
class Employer {
|
|
|
|
@PrimaryKey(sequence="ID")
|
|
long id;
|
|
|
|
@SecondaryKey(relate=ONE_TO_ONE)
|
|
String name;
|
|
|
|
Address address;
|
|
|
|
Employer(String name) {
|
|
this.name = name;
|
|
}
|
|
|
|
private Employer() {} // For bindings
|
|
}
|
|
|
|
// A persistent class used in other classes.
|
|
//
|
|
@Persistent
|
|
class Address {
|
|
String street;
|
|
String city;
|
|
String state;
|
|
int zipCode;
|
|
private Address() {} // For bindings
|
|
}
|
|
|
|
// The data accessor class for the entity model.
|
|
//
|
|
class PersonAccessor {
|
|
|
|
// Person accessors
|
|
//
|
|
PrimaryIndex<String,Person> personBySsn;
|
|
SecondaryIndex<String,String,Person> personByParentSsn;
|
|
SecondaryIndex<String,String,Person> personByEmailAddresses;
|
|
SecondaryIndex<Long,String,Person> personByEmployerIds;
|
|
|
|
// Employer accessors
|
|
//
|
|
PrimaryIndex<Long,Employer> employerById;
|
|
SecondaryIndex<String,Long,Employer> employerByName;
|
|
|
|
// Opens all primary and secondary indices.
|
|
//
|
|
public PersonAccessor(EntityStore store)
|
|
throws DatabaseException {
|
|
|
|
personBySsn = store.getPrimaryIndex(
|
|
String.class, Person.class);
|
|
|
|
personByParentSsn = store.getSecondaryIndex(
|
|
personBySsn, String.class, "parentSsn");
|
|
|
|
personByEmailAddresses = store.getSecondaryIndex(
|
|
personBySsn, String.class, "emailAddresses");
|
|
|
|
personByEmployerIds = store.getSecondaryIndex(
|
|
personBySsn, Long.class, "employerIds");
|
|
|
|
employerById = store.getPrimaryIndex(
|
|
Long.class, Employer.class);
|
|
|
|
employerByName = store.getSecondaryIndex(
|
|
employerById, String.class, "name");
|
|
}
|
|
}
|
|
|
|
// Open a transactional Berkeley DB engine environment.
|
|
//
|
|
EnvironmentConfig envConfig = new EnvironmentConfig();
|
|
envConfig.setAllowCreate(true);
|
|
envConfig.setTransactional(true);
|
|
Environment env = new Environment(new File("/my/data"), envConfig);
|
|
|
|
// Open a transactional entity store.
|
|
//
|
|
StoreConfig storeConfig = new StoreConfig();
|
|
storeConfig.setAllowCreate(true);
|
|
storeConfig.setTransactional(true);
|
|
EntityStore store = new EntityStore(env, "PersonStore", storeConfig);
|
|
|
|
// Initialize the data access object.
|
|
//
|
|
PersonAccessor dao = new PersonAccessor(store);
|
|
|
|
// Add a parent and two children using the Person primary index. Specifying a
|
|
// non-null parentSsn adds the child Person to the sub-index of children for
|
|
// that parent key.
|
|
//
|
|
dao.personBySsn.put(new Person("Bob Smith", "111-11-1111", null));
|
|
dao.personBySsn.put(new Person("Mary Smith", "333-33-3333", "111-11-1111"));
|
|
dao.personBySsn.put(new Person("Jack Smith", "222-22-2222", "111-11-1111"));
|
|
|
|
// Print the children of a parent using a sub-index and a cursor.
|
|
//
|
|
EntityCursor<Person> children =
|
|
dao.personByParentSsn.subIndex("111-11-1111").entities();
|
|
try {
|
|
for (Person child : children) {
|
|
System.out.println(child.ssn + ' ' + child.name);
|
|
}
|
|
} finally {
|
|
children.close();
|
|
}
|
|
|
|
// Get Bob by primary key using the primary index.
|
|
//
|
|
Person bob = dao.personBySsn.get("111-11-1111");
|
|
assert bob != null;
|
|
|
|
// Create two employers. Their primary keys are assigned from a sequence.
|
|
//
|
|
Employer gizmoInc = new Employer("Gizmo Inc");
|
|
Employer gadgetInc = new Employer("Gadget Inc");
|
|
dao.employerById.put(gizmoInc);
|
|
dao.employerById.put(gadgetInc);
|
|
|
|
// Bob has two jobs and two email addresses.
|
|
//
|
|
bob.employerIds.add(gizmoInc.id);
|
|
bob.employerIds.add(gadgetInc.id);
|
|
bob.emailAddresses.add("bob@bob.com");
|
|
bob.emailAddresses.add("bob@gmail.com");
|
|
|
|
// Update Bob's record.
|
|
//
|
|
dao.personBySsn.put(bob);
|
|
|
|
// Bob can now be found by both email addresses.
|
|
//
|
|
bob = dao.personByEmailAddresses.get("bob@bob.com");
|
|
assert bob != null;
|
|
bob = dao.personByEmailAddresses.get("bob@gmail.com");
|
|
assert bob != null;
|
|
|
|
// Bob can also be found as an employee of both employers.
|
|
//
|
|
EntityIndex<String,Person> employees;
|
|
employees = dao.personByEmployerIds.subIndex(gizmoInc.id);
|
|
assert employees.contains("111-11-1111");
|
|
employees = dao.personByEmployerIds.subIndex(gadgetInc.id);
|
|
assert employees.contains("111-11-1111");
|
|
|
|
// When an employer is deleted, the onRelatedEntityDelete=NULLIFY for the
|
|
// employerIds key causes the deleted ID to be removed from Bob's employerIds.
|
|
//
|
|
dao.employerById.delete(gizmoInc.id);
|
|
bob = dao.personBySsn.get("111-11-1111");
|
|
assert !bob.employerIds.contains(gizmoInc.id);
|
|
|
|
store.close();
|
|
env.close();
|
|
</pre>
|
|
<p>The example illustrates several characteristics of the DPL:</p>
|
|
<ul>
|
|
<li>Persistent data and keys are defined in terms of instance fields. For
|
|
brevity the example does not show getter and setter methods, although these
|
|
would normally exist to provide encapsulation. The DPL accesses fields during
|
|
object serialization and deserialization, rather than calling getter/setter
|
|
methods, leaving business methods free to enforce arbitrary validation rules.
|
|
For example:
|
|
<pre class="code">
|
|
@Persistent
|
|
public class ConstrainedValue {
|
|
|
|
private int min;
|
|
private int max;
|
|
private int value;
|
|
|
|
private ConstrainedValue() {} // For bindings
|
|
|
|
public ConstrainedValue(int min, int max) {
|
|
this.min = min;
|
|
this.max = max;
|
|
value = min;
|
|
}
|
|
|
|
public setValue(int value) {
|
|
if (value < min || value > max) {
|
|
throw new IllegalArgumentException("out of range");
|
|
}
|
|
this.value = value;
|
|
}
|
|
}
|
|
</pre>
|
|
The above <code>setValue</code> method would not work if it were called during
|
|
object deserialization, since the order of setting fields is arbitrary. The
|
|
<code>min</code> and <code>max</code> fields may not be set before the <code>value</code> is
|
|
set.
|
|
</li>
|
|
<br>
|
|
<li>The example creates a transactional store and therefore all operations are
|
|
transaction protected. Because no explicit transactions are used, auto-commit
|
|
is used implicitly.
|
|
|
|
<p>Explicit transactions may also be used to group multiple operations in a
|
|
single transaction, and all access methods have optional transaction
|
|
parameters. For example, the following two operations are performed atomically
|
|
in a transaction:
|
|
<pre class="code">
|
|
Transaction txn = env.beginTransaction(null, null);
|
|
dao.employerById.put(txn, gizmoInc);
|
|
dao.employerById.put(txn, gadgetInc);
|
|
txn.commit();
|
|
</pre>
|
|
</li>
|
|
<li>To provide maximum performance, the DPL operations map directly to the
|
|
Btree operations of the Berkeley DB engine. Unlike other persistence
|
|
approaches, keys and indices are exposed for direct access and performance
|
|
tuning.
|
|
<p>Queries are implemented by calling methods of the primary and secondary
|
|
indices. An <A HREF="../../../com/sleepycat/persist/EntityJoin.html" title="class in com.sleepycat.persist"><CODE>EntityJoin</CODE></A> class is also
|
|
available for performing equality joins. For example, the following code
|
|
queries all of Bob's children that work for Gizmo Inc:
|
|
<pre class="code">
|
|
EntityJoin<String,Person> join = new EntityJoin(dao.personBySsn);
|
|
|
|
join.addCondition(dao.personByParentSsn, "111-11-1111");
|
|
join.addCondition(dao.personByEmployerIds, gizmoInc.id);
|
|
|
|
ForwardCursor<Person> results = join.entities();
|
|
try {
|
|
for (Person person : results) {
|
|
System.out.println(person.ssn + ' ' + person.name);
|
|
}
|
|
} finally {
|
|
results.close();
|
|
}
|
|
</li>
|
|
<li>Object relationships are based on keys. When a <code>Person</code> with a given
|
|
employer ID in its <code>employerIds</code> set is stored, the <code>Person</code> object
|
|
becomes part of the collection of employees for that employer. This collection
|
|
of employees is accessed using a <A HREF="../../../com/sleepycat/persist/SecondaryIndex.html#subIndex(SK)"><CODE>SecondaryIndex.subIndex</CODE></A> for the
|
|
employer ID, as shown below:
|
|
<pre class="code">
|
|
EntityCursor<Person> employees =
|
|
dao.personByEmployerIds.subIndex(gizmoInc.id).entities();
|
|
try {
|
|
for (Person employee : employees) {
|
|
System.out.println(employee.ssn + ' ' + employee.name);
|
|
}
|
|
} finally {
|
|
employees.close();
|
|
}
|
|
</pre></li>
|
|
<li>Note that when Bob's employer is deleted in the example, the <code>Person</code>
|
|
object for Bob is refetched to see the change to its <code>employerIds</code>. This
|
|
is because objects are accessed by value, not by reference. In other words, no
|
|
object cache or "persistence context" is maintained by the DPL. The low level
|
|
caching of the embedded Berkeley DB engine, combined with lightweight object
|
|
bindings, provides maximum performance.</li>
|
|
</ul>
|
|
|
|
<a name="whichAPI"><h2>Which API to use?</h2></a>
|
|
|
|
<p>The Berkeley DB engine has a <A HREF="../../../com/sleepycat/db/package-summary.html"><CODE>Base API</CODE></A>, a <A HREF="../../../com/sleepycat/collections/package-summary.html"><CODE>Collections API</CODE></A> and a <A HREF="../../../com/sleepycat/persist/package-summary.html"><CODE>Direct Persistence Layer (DPL)</CODE></A>. Follow these guidelines if you are not sure
|
|
which API to use:</p>
|
|
<ul>
|
|
<li>When Java classes are used to represent domain objects in an application,
|
|
the DPL is recommended. The more domain classes, the more value there is in
|
|
using annotations to define your schema.</li>
|
|
<br>
|
|
<li>When porting an application between Berkeley DB and Berkeley DB Java
|
|
Edition, or when you've chosen not to use Java classes to represent domain
|
|
objects, then the Base API is recommended. You may also prefer to use this API
|
|
if you have very few domain classes.</li>
|
|
<br>
|
|
<li>The Collections API is useful for interoperating with external components
|
|
because it conforms to the standard Java Collections Framework. It is
|
|
therefore useful in combination with both the Base API and the DPL. You may
|
|
prefer this API because it provides the familiar Java Collections
|
|
interface.</li>
|
|
</ul>
|
|
|
|
<a name="java14and15"><h2>Java 1.5 dependencies</h2></a>
|
|
|
|
<p><em>NOTE:</em> The current release of the DPL requires compiling and
|
|
deploying with Java 1.5 or greater. Support for Java 1.4 may be added in a
|
|
future release, based on user demand.</p>
|
|
|
|
<p>The DPL uses two features of Java 1.5: generic types and annotations. If
|
|
you wish to avoid using these two Java 1.5 features, the DPL provides options
|
|
for doing so.</p>
|
|
|
|
<a name="genericTypes"><h3>Generic Types</h3></a>
|
|
|
|
<p>Generic types are used to provide type safety, especially for the <A HREF="../../../com/sleepycat/persist/PrimaryIndex.html" title="class in com.sleepycat.persist"><CODE>PrimaryIndex</CODE></A>, <A HREF="../../../com/sleepycat/persist/SecondaryIndex.html" title="class in com.sleepycat.persist"><CODE>SecondaryIndex</CODE></A>, and <A HREF="../../../com/sleepycat/persist/EntityCursor.html" title="interface in com.sleepycat.persist"><CODE>EntityCursor</CODE></A> classes. If you don't wish to
|
|
use generic types, you can simply not declare your index and cursor objects
|
|
using generic type parameters. This is the same as using the Java 1.5
|
|
Collections Framework without using generic types.</p>
|
|
|
|
<a name="annotations"><h3>Annotations</h3></a>
|
|
|
|
<p>If you don't wish to use annotations, you can provide another source of
|
|
metadata by implementing an <A HREF="../../../com/sleepycat/persist/model/EntityModel.html" title="class in com.sleepycat.persist.model"><CODE>EntityModel</CODE></A> class. For example, naming conventions, static members, or an XML
|
|
configuration file might be used as a source of metadata. However, if you
|
|
don't use annotations then you won't be able to use bytecode enhancement, which
|
|
is described next.</p>
|
|
|
|
<a name="bytecode"><h2>Bytecode Enhancement</h2></a>
|
|
|
|
<p>The persistent fields of a class may be private, package-private, protected
|
|
or public. The DPL can access persistent fields either by bytecode enhancement
|
|
or by reflection.</p>
|
|
|
|
<p>Bytecode enhancement may be used to fully optimize binding performance and
|
|
to avoid the use of Java reflection. In applications that are CPU bound,
|
|
avoiding Java reflection can have a significant performance impact.</p>
|
|
|
|
<p>Bytecode enhancement may be performed either at runtime or at build time
|
|
(offline). When enhancement is performed at runtime, persistent classes are
|
|
enhanced as they are loaded. When enhancement is performed offline, class
|
|
files are enhanced during a post-compilation step.
|
|
Enhanced classes are used to efficiently access all fields and default
|
|
constructors, including non-public members.</p>
|
|
|
|
<p>See <A HREF="../../../com/sleepycat/persist/model/ClassEnhancer.html" title="class in com.sleepycat.persist.model"><CODE>ClassEnhancer</CODE></A> for
|
|
bytecode enhancement configuration details.</p>
|
|
|
|
<p>If bytecode enhancement is not used as described above, the DPL will use
|
|
reflection for accessing persistent fields and the default constructor. The
|
|
<A HREF="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/AccessibleObject.html#setAccessible(java.lang.reflect.AccessibleObject[], boolean)" title="class or interface in java.lang.reflect"><CODE>AccessibleObject.setAccessible</CODE></A> method is called by the DPL to enable access to
|
|
non-public fields and constructors. If you are running under a Java security
|
|
manager you must configure your security policy to allow the following
|
|
permission:</p>
|
|
|
|
<p><code>permission java.lang.reflect.ReflectPermission "suppressAccessChecks";</code>
|
|
|
|
<p>There are three cases where setting the above permission is <em>not</em>
|
|
required:</p>
|
|
<ol>
|
|
<li>If you are not running under a Java Security Manager, then access to
|
|
non-public members via reflection is not restricted. This is the default for
|
|
J2SE.</li>
|
|
<br>
|
|
<li>If all persistent fields and default constructors are <code>public</code> then
|
|
they can be accessed via reflection without special permissions, even when
|
|
running under a Java Security Manager. However, declaring <code>public</code>
|
|
instance fields is not recommended because it discourages encapsulation.</li>
|
|
<br>
|
|
<li>If bytecode enhancement is used as described above, then reflection will
|
|
not be used.</li>
|
|
</ol>
|
|
|
|
<p>It is well known that executing generated code is faster than reflection.
|
|
However, this performance difference may or may not impact a given application
|
|
since it may be overshadowed by other factors. Performance testing in a
|
|
realistic usage scenario is the best way to determine the impact. If you are
|
|
determined to avoid the use of reflection then option 3 above is
|
|
recommended.</p>
|
|
<P>
|
|
|
|
<P>
|
|
<DL>
|
|
</DL>
|
|
<HR>
|
|
|
|
|
|
<!-- ======= START OF BOTTOM NAVBAR ====== -->
|
|
<A NAME="navbar_bottom"><!-- --></A>
|
|
<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
|
|
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
|
|
<TR>
|
|
<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
|
|
<A NAME="navbar_bottom_firstrow"><!-- --></A>
|
|
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
|
|
<TR ALIGN="center" VALIGN="top">
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Package</B></FONT> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-use.html"><FONT CLASS="NavBarFont1"><B>Use</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
|
|
<TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
|
|
</TR>
|
|
</TABLE>
|
|
</TD>
|
|
<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
|
|
<b>Berkeley DB</b><br><font size="-1"> version 4.7.25</font></EM>
|
|
</TD>
|
|
</TR>
|
|
|
|
<TR>
|
|
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
|
<A HREF="../../../com/sleepycat/db/package-summary.html"><B>PREV PACKAGE</B></A>
|
|
<A HREF="../../../com/sleepycat/persist/evolve/package-summary.html"><B>NEXT PACKAGE</B></A></FONT></TD>
|
|
<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
|
|
<A HREF="../../../index.html?com/sleepycat/persist/package-summary.html" target="_top"><B>FRAMES</B></A>
|
|
<A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A>
|
|
<SCRIPT type="text/javascript">
|
|
<!--
|
|
if(window==top) {
|
|
document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
|
|
}
|
|
//-->
|
|
</SCRIPT>
|
|
<NOSCRIPT>
|
|
<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
|
|
</NOSCRIPT>
|
|
|
|
|
|
</FONT></TD>
|
|
</TR>
|
|
</TABLE>
|
|
<A NAME="skip-navbar_bottom"></A>
|
|
<!-- ======== END OF BOTTOM NAVBAR ======= -->
|
|
|
|
<HR>
|
|
<font size=1>Copyright (c) 1996,2008 Oracle. All rights reserved.</font>
|
|
</BODY>
|
|
</HTML>
|