1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2<!--NewPage-->
3<HTML>
4<HEAD>
5<!-- Generated by javadoc (build 1.5.0) on Thu May 15 17:17:33 EDT 2008 -->
6<TITLE>
7com.sleepycat.persist (Oracle - Berkeley DB Java API)
8</TITLE>
9
10<META NAME="keywords" CONTENT="com.sleepycat.persist package">
11
12<LINK REL ="stylesheet" TYPE="text/css" HREF="/style.css" TITLE="Style">
13
14<SCRIPT type="text/javascript">
15function windowTitle()
16{
17    parent.document.title="com.sleepycat.persist (Oracle - Berkeley DB Java API)";
18}
19</SCRIPT>
20<NOSCRIPT>
21</NOSCRIPT>
22
23</HEAD>
24
25<BODY BGCOLOR="white" onload="windowTitle();">
26
27
28<!-- ========= START OF TOP NAVBAR ======= -->
29<A NAME="navbar_top"><!-- --></A>
30<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
31<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
32<TR>
33<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
34<A NAME="navbar_top_firstrow"><!-- --></A>
35<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
36  <TR ALIGN="center" VALIGN="top">
37  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
38  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Package</B></FONT>&nbsp;</TD>
39  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
40  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-use.html"><FONT CLASS="NavBarFont1"><B>Use</B></FONT></A>&nbsp;</TD>
41  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
42  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
43  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
44  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
45  </TR>
46</TABLE>
47</TD>
48<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
49<b>Berkeley DB</b><br><font size="-1"> version 4.7.25</font></EM>
50</TD>
51</TR>
52
53<TR>
54<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
55&nbsp;<A HREF="/com/sleepycat/db/package-summary.html"><B>PREV PACKAGE</B></A>&nbsp;
56&nbsp;<A HREF="/com/sleepycat/persist/evolve/package-summary.html"><B>NEXT PACKAGE</B></A></FONT></TD>
57<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
58  <A HREF="/index.html?com/sleepycat/persist/package-summary.html" target="_top"><B>FRAMES</B></A>  &nbsp;
59&nbsp;<A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
60&nbsp;<SCRIPT type="text/javascript">
61  <!--
62  if(window==top) {
63    document.writeln('<A HREF="/allclasses-noframe.html"><B>All Classes</B></A>');
64  }
65  //-->
66</SCRIPT>
67<NOSCRIPT>
68  <A HREF="/allclasses-noframe.html"><B>All Classes</B></A>
69</NOSCRIPT>
70
71
72</FONT></TD>
73</TR>
74</TABLE>
75<A NAME="skip-navbar_top"></A>
76<!-- ========= END OF TOP NAVBAR ========= -->
77
78<HR>
79<H2>
80Package com.sleepycat.persist
81</H2>
82The Direct Persistence Layer (DPL) adds a persistent object model to the
83Berkeley DB transactional engine.
84<P>
85<B>See:</B>
86<BR>
87&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="#package_description"><B>Description</B></A>
88<P>
89
90<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
91<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
92<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
93<B>Interface Summary</B></FONT></TH>
94</TR>
95<TR BGCOLOR="white" CLASS="TableRowColor">
96<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/DatabaseNamer.html" title="interface in com.sleepycat.persist">DatabaseNamer</A></B></TD>
97<TD>Determines the file names to use for primary and secondary databases.</TD>
98</TR>
99<TR BGCOLOR="white" CLASS="TableRowColor">
100<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/EntityCursor.html" title="interface in com.sleepycat.persist">EntityCursor&lt;V&gt;</A></B></TD>
101<TD>Traverses entity values or key values and allows deleting or updating the
102 entity at the current cursor position.</TD>
103</TR>
104<TR BGCOLOR="white" CLASS="TableRowColor">
105<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/EntityIndex.html" title="interface in com.sleepycat.persist">EntityIndex&lt;K,V&gt;</A></B></TD>
106<TD>The interface for accessing keys and entities via a primary or secondary
107 index.</TD>
108</TR>
109<TR BGCOLOR="white" CLASS="TableRowColor">
110<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/ForwardCursor.html" title="interface in com.sleepycat.persist">ForwardCursor&lt;V&gt;</A></B></TD>
111<TD>Cursor operations limited to traversing forward.</TD>
112</TR>
113</TABLE>
114&nbsp;
115
116<P>
117
118<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
119<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
120<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
121<B>Class Summary</B></FONT></TH>
122</TR>
123<TR BGCOLOR="white" CLASS="TableRowColor">
124<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/EntityJoin.html" title="class in com.sleepycat.persist">EntityJoin&lt;PK,E&gt;</A></B></TD>
125<TD>Performs an equality join on two or more secondary keys.</TD>
126</TR>
127<TR BGCOLOR="white" CLASS="TableRowColor">
128<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/EntityStore.html" title="class in com.sleepycat.persist">EntityStore</A></B></TD>
129<TD>A store for managing persistent entity objects.</TD>
130</TR>
131<TR BGCOLOR="white" CLASS="TableRowColor">
132<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/PrimaryIndex.html" title="class in com.sleepycat.persist">PrimaryIndex&lt;PK,E&gt;</A></B></TD>
133<TD>The primary index for an entity class and its primary key.</TD>
134</TR>
135<TR BGCOLOR="white" CLASS="TableRowColor">
136<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/SecondaryIndex.html" title="class in com.sleepycat.persist">SecondaryIndex&lt;SK,PK,E&gt;</A></B></TD>
137<TD>The secondary index for an entity class and a secondary key.</TD>
138</TR>
139<TR BGCOLOR="white" CLASS="TableRowColor">
140<TD WIDTH="15%"><B><A HREF="/com/sleepycat/persist/StoreConfig.html" title="class in com.sleepycat.persist">StoreConfig</A></B></TD>
141<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>
142</TR>
143</TABLE>
144&nbsp;
145
146<P>
147<A NAME="package_description"><!-- --></A><H2>
148Package com.sleepycat.persist Description
149</H2>
150
151<P>
152The Direct Persistence Layer (DPL) adds a persistent object model to the
153Berkeley DB transactional engine.
154
155<h1>Package Specification</h1>
156
157<ul>
158<li><a href="#intro">Introduction</a></li>
159<li><a href="#model">The Entity Model</a></li>
160<li><a href="#example">A brief example</a></li>
161<li><a href="#whichAPI">Which API to use?</a></li>
162<li><a href="#java14and15">Java 1.5 dependencies</a>
163    <ul>
164    <li><a href="#genericTypes">Generic Types</a></li>
165    <li><a href="#annotations">Annotations</a></li>
166    </ul>
167</li>
168<li><a href="#bytecode">Bytecode Enhancement</a></li>
169</ul>
170
171<a name="intro"><h2>Introduction</h2></a>
172
173<p>The Direct Persistence Layer (DPL) was designed to meet the following
174requirements.</p>
175<ul>
176<li>A type safe and convenient API is provided for accessing persistent
177objects.  The use of Java generic types, although optional, is fully exploited
178to provide type safety.  For example:
179<pre class="code">
180PrimaryIndex&lt;Long,Employer&gt; employerById = ...;
181long employerId = ...;
182Employer employer = employerById.get(employerId);</pre>
183</li>
184<li>All Java types are allowed to be persistent without requiring that they
185implement special interfaces.  Persistent fields may be <code>private</code>,
186package-private (default access), <code>protected</code>, or <code>public</code>.  No
187hand-coding of bindings is required.  However, each persistent class must have
188a default constructor.  For example:
189<pre class="code">
190@Persistent
191class Address {
192    String street;
193    String city;
194    String state;
195    int zipCode;
196    private Address() {}
197}</pre>
198</li>
199<li>Bytecode enhancement provides fully optimized bindings that do not use Java
200reflection.</li>
201<li>It is easy to define primary and secondary keys.  No external schema is
202required and Java annotations may be used for defining all metadata.
203Extensions may derive metadata from other sources.  For example, the following
204Employer class is defined as a persistent entity with a primary key field
205<code>id</code> and the secondary key field <code>name</code>:</li>
206<pre class="code">
207@Entity
208class Employer {
209
210    @PrimaryKey(sequence="ID")
211    long id;
212
213    @SecondaryKey(relate=ONE_TO_ONE)
214    String name;
215
216    Address address;
217
218    private Employer() {}
219}</pre>
220<li>Interoperability with external components is supported via the Java
221collections framework.  Any primary or secondary index can be accessed using a
222standard <code>java.util</code> collection.  For example:
223<pre class="code">java.util.SortedMap&lt;String,Employer&gt; map = employerByName.sortedMap();</pre>
224</li>
225<li>Class evolution is explicitly supported.  Compatible changes (adding fields
226and type widening) are performed automatically and transparently.  For example,
227without any special configuration a <code>street2</code> field may be added to the
228<code>Address</code> class and the type of the <code>zipCode</code> field may be changed
229from <code>int</code> to <code>long</code>:
230<pre class="code">
231@Persistent
232class Address {
233    String street;
234    String street2;
235    String city;
236    String state;
237    long zipCode;
238    private Address() {}
239}</pre>
240Many incompatible class changes, such as renaming fields or refactoring a
241single 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
242applied lazily as data is accessed, avoiding downtime to convert large
243databases during a software upgrade.
244<p>Complex refactoring involving multiple classes may be performed using the a
245<a href="package-summary.html#storeConversion">store conversion</a>.  The DPL
246always provides access to your data via a <code>RawStore</code>, no matter what
247changes have been made to persistent classes.</p>
248</li>
249<br>
250<li>The performance of the Berkeley DB transactional engine is not compromised.
251Operations are internally mapped directly to the engine API, object bindings
252are lightweight, and all engine tuning parameters are available.  For example,
253a "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:
254<pre class="code">Employer employer = employerByName.get(null, "Gizmo Inc", LockMode.READ_UNCOMMITTED);</pre>
255For 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
256DB engine.  For example, the size of an internal Btree node can be specified
257as follows:
258<pre class="code">
259DatabaseConfig config = store.getPrimaryConfig(Employer.class);
260config.setNodeMaxEntries(64);
261store.setPrimaryConfig(config);</pre>
262</li>
263</ul>
264
265<a name="model"><h2>The Entity Model</h2></a>
266
267<p>The DPL is intended for applications that represent persistent domain
268objects using Java classes.  An <em>entity class</em> is an ordinary Java class
269that has a primary key and is stored and accessed using a primary index.  It
270may also have any number of secondary keys, and entities may be accessed by
271secondary key using a secondary index.</p>
272
273<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,
274its 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
275secondary 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>
276
277<p>In the following example, the <code>Person.ssn</code> (social security number)
278field is the primary key and the <code>Person.employerIds</code> field is a
279many-to-many secondary key.</p>
280<pre class="code">
281@Entity
282class Person {
283
284    @PrimaryKey
285    String ssn;
286
287    String name;
288    Address address;
289
290    @SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Employer.class)
291    Set&lt;Long&gt; employerIds = new HashSet&lt;Long&gt;();
292
293    private Person() {} // For bindings
294}</pre>
295
296<p>A set of entity classes constitutes an <em>entity model</em>.  In addition
297to isolated entity classes, an entity model may contain relationships between
298entities.  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.
299Many-to-one, one-to-many, many-to-many and one-to-one relationships are
300supported, as well as foreign key constraints.</p>
301
302<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
303<code>relatedEntity=Employer.class</code> annotation property establishes foreign
304key constraints to guarantee that every element of the <code>employerIds</code> set
305is a valid <code>Employer</code> primary key.</p>
306
307<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>
308
309<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
310class defined in the model.  The store provides access to the primary and
311secondary indices for each entity class, for example:</p>
312
313<pre class="code">
314EntityStore store = new EntityStore(...);
315
316PrimaryIndex&lt;String,Person&gt; personBySsn =
317    store.getPrimaryIndex(String.class, Person.class);</pre>
318
319<a name="example"><h2>A brief example</h2></a>
320
321<p>The following example shows how to define an entity model and how to store
322and access persistent objects.  Exception handling is omitted for brevity.</p>
323
324<pre class="code">
325import java.io.File;
326import java.util.HashSet;
327import java.util.Set;
328
329import com.sleepycat.db.DatabaseException;
330import com.sleepycat.db.Environment;
331import com.sleepycat.db.EnvironmentConfig;
332import com.sleepycat.persist.EntityCursor;
333import com.sleepycat.persist.EntityIndex;
334import com.sleepycat.persist.EntityStore;
335import com.sleepycat.persist.PrimaryIndex;
336import com.sleepycat.persist.SecondaryIndex;
337import com.sleepycat.persist.StoreConfig;
338import com.sleepycat.persist.model.Entity;
339import com.sleepycat.persist.model.Persistent;
340import com.sleepycat.persist.model.PrimaryKey;
341import com.sleepycat.persist.model.SecondaryKey;
342import static com.sleepycat.persist.model.DeleteAction.NULLIFY;
343import static com.sleepycat.persist.model.Relationship.ONE_TO_ONE;
344import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY;
345import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE;
346import static com.sleepycat.persist.model.Relationship.MANY_TO_MANY;
347
348// An entity class.
349//
350@Entity
351class Person {
352
353    @PrimaryKey
354    String ssn;
355
356    String name;
357    Address address;
358
359    @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class)
360    String parentSsn;
361
362    @SecondaryKey(relate=ONE_TO_MANY)
363    Set&lt;String&gt; emailAddresses = new HashSet&lt;String&gt;();
364
365    <code>@SecondaryKey(relate=MANY_TO_MANY, relatedEntity=Employer.class,
366                                       onRelatedEntityDelete=NULLIFY)</code>
367    <code>Set&lt;Long&gt; employerIds = new HashSet&lt;Long&gt;();</code>
368
369    Person(String name, String ssn, String parentSsn) {
370        this.name = name;
371        this.ssn = ssn;
372        this.parentSsn = parentSsn;
373    }
374
375    private Person() {} // For bindings
376}
377
378// Another entity class.
379//
380@Entity
381class Employer {
382
383    @PrimaryKey(sequence="ID")
384    long id;
385
386    @SecondaryKey(relate=ONE_TO_ONE)
387    String name;
388
389    Address address;
390
391    Employer(String name) {
392        this.name = name;
393    }
394
395    private Employer() {} // For bindings
396}
397
398// A persistent class used in other classes.
399//
400@Persistent
401class Address {
402    String street;
403    String city;
404    String state;
405    int zipCode;
406    private Address() {} // For bindings
407}
408
409// The data accessor class for the entity model.
410//
411class PersonAccessor {
412
413    // Person accessors
414    //
415    PrimaryIndex&lt;String,Person&gt; personBySsn;
416    SecondaryIndex&lt;String,String,Person&gt; personByParentSsn;
417    SecondaryIndex&lt;String,String,Person&gt; personByEmailAddresses;
418    SecondaryIndex&lt;Long,String,Person&gt; personByEmployerIds;
419
420    // Employer accessors
421    //
422    PrimaryIndex&lt;Long,Employer&gt; employerById;
423    SecondaryIndex&lt;String,Long,Employer&gt; employerByName;
424
425    // Opens all primary and secondary indices.
426    //
427    public PersonAccessor(EntityStore store)
428        throws DatabaseException {
429
430        personBySsn = store.getPrimaryIndex(
431            String.class, Person.class);
432
433        personByParentSsn = store.getSecondaryIndex(
434            personBySsn, String.class, "parentSsn");
435
436        personByEmailAddresses = store.getSecondaryIndex(
437            personBySsn, String.class, "emailAddresses");
438
439        personByEmployerIds = store.getSecondaryIndex(
440            personBySsn, Long.class, "employerIds");
441
442        employerById = store.getPrimaryIndex(
443            Long.class, Employer.class);
444
445        employerByName = store.getSecondaryIndex(
446            employerById, String.class, "name"); 
447    }
448}
449
450// Open a transactional Berkeley DB engine environment.
451//
452EnvironmentConfig envConfig = new EnvironmentConfig();
453envConfig.setAllowCreate(true);
454envConfig.setTransactional(true);
455Environment env = new Environment(new File("/my/data"), envConfig);
456
457// Open a transactional entity store.
458//
459StoreConfig storeConfig = new StoreConfig();
460storeConfig.setAllowCreate(true);
461storeConfig.setTransactional(true);
462EntityStore store = new EntityStore(env, "PersonStore", storeConfig);
463
464// Initialize the data access object.
465//
466PersonAccessor dao = new PersonAccessor(store);
467
468// Add a parent and two children using the Person primary index.  Specifying a
469// non-null parentSsn adds the child Person to the sub-index of children for
470// that parent key.
471//
472dao.personBySsn.put(new Person("Bob Smith", "111-11-1111", null));
473dao.personBySsn.put(new Person("Mary Smith", "333-33-3333", "111-11-1111"));
474dao.personBySsn.put(new Person("Jack Smith", "222-22-2222", "111-11-1111"));
475
476// Print the children of a parent using a sub-index and a cursor.
477//
478EntityCursor&lt;Person&gt; children =
479    dao.personByParentSsn.subIndex("111-11-1111").entities();
480try {
481    for (Person child : children) {
482        System.out.println(child.ssn + ' ' + child.name);
483    }
484} finally {
485    children.close();
486}
487
488// Get Bob by primary key using the primary index.
489//
490Person bob = dao.personBySsn.get("111-11-1111");
491assert bob != null;
492
493// Create two employers.  Their primary keys are assigned from a sequence.
494//
495Employer gizmoInc = new Employer("Gizmo Inc");
496Employer gadgetInc = new Employer("Gadget Inc");
497dao.employerById.put(gizmoInc);
498dao.employerById.put(gadgetInc);
499
500// Bob has two jobs and two email addresses.
501//
502bob.employerIds.add(gizmoInc.id);
503bob.employerIds.add(gadgetInc.id);
504bob.emailAddresses.add("bob@bob.com");
505bob.emailAddresses.add("bob@gmail.com");
506
507// Update Bob's record.
508//
509dao.personBySsn.put(bob);
510
511// Bob can now be found by both email addresses.
512//
513bob = dao.personByEmailAddresses.get("bob@bob.com");
514assert bob != null;
515bob = dao.personByEmailAddresses.get("bob@gmail.com");
516assert bob != null;
517
518// Bob can also be found as an employee of both employers.
519//
520EntityIndex&lt;String,Person&gt; employees;
521employees = dao.personByEmployerIds.subIndex(gizmoInc.id);
522assert employees.contains("111-11-1111");
523employees = dao.personByEmployerIds.subIndex(gadgetInc.id);
524assert employees.contains("111-11-1111");
525
526// When an employer is deleted, the onRelatedEntityDelete=NULLIFY for the
527// employerIds key causes the deleted ID to be removed from Bob's employerIds.
528//
529dao.employerById.delete(gizmoInc.id);
530bob = dao.personBySsn.get("111-11-1111");
531assert !bob.employerIds.contains(gizmoInc.id);
532
533store.close();
534env.close();
535</pre>
536<p>The example illustrates several characteristics of the DPL:</p>
537<ul>
538<li>Persistent data and keys are defined in terms of instance fields.  For
539brevity the example does not show getter and setter methods, although these
540would normally exist to provide encapsulation.  The DPL accesses fields during
541object serialization and deserialization, rather than calling getter/setter
542methods, leaving business methods free to enforce arbitrary validation rules.
543For example: 
544<pre class="code">
545@Persistent
546public class ConstrainedValue {
547
548    private int min;
549    private int max;
550    private int value;
551
552    private ConstrainedValue() {} // For bindings
553
554    public ConstrainedValue(int min, int max) {
555        this.min = min;
556        this.max = max;
557        value = min;
558    }
559
560    public setValue(int value) {
561        if (value &lt; min || value &gt; max) {
562            throw new IllegalArgumentException("out of range");
563        }
564        this.value = value;
565    }
566}
567</pre>
568The above <code>setValue</code> method would not work if it were called during
569object deserialization, since the order of setting fields is arbitrary.  The
570<code>min</code> and <code>max</code> fields may not be set before the <code>value</code> is
571set.
572</li>
573<br>
574<li>The example creates a transactional store and therefore all operations are
575transaction protected.  Because no explicit transactions are used, auto-commit
576is used implicitly.
577
578<p>Explicit transactions may also be used to group multiple operations in a
579single transaction, and all access methods have optional transaction
580parameters.  For example, the following two operations are performed atomically
581in a transaction:
582<pre class="code">
583Transaction txn = env.beginTransaction(null, null);
584dao.employerById.put(txn, gizmoInc);
585dao.employerById.put(txn, gadgetInc);
586txn.commit();
587</pre>
588</li>
589<li>To provide maximum performance, the DPL operations map directly to the
590Btree operations of the Berkeley DB engine.  Unlike other persistence
591approaches, keys and indices are exposed for direct access and performance
592tuning.
593<p>Queries are implemented by calling methods of the primary and secondary
594indices.  An <A HREF="/com/sleepycat/persist/EntityJoin.html" title="class in com.sleepycat.persist"><CODE>EntityJoin</CODE></A> class is also
595available for performing equality joins.  For example, the following code
596queries all of Bob's children that work for Gizmo Inc:
597<pre class="code">
598EntityJoin&lt;String,Person&gt; join = new EntityJoin(dao.personBySsn);
599
600join.addCondition(dao.personByParentSsn, "111-11-1111");
601join.addCondition(dao.personByEmployerIds, gizmoInc.id);
602
603ForwardCursor&lt;Person&gt; results = join.entities();
604try {
605    for (Person person : results) {
606        System.out.println(person.ssn + ' ' + person.name);
607    }
608} finally {
609    results.close();
610}
611</li>
612<li>Object relationships are based on keys.  When a <code>Person</code> with a given
613employer ID in its <code>employerIds</code> set is stored, the <code>Person</code> object
614becomes part of the collection of employees for that employer.  This collection
615of employees is accessed using a <A HREF="/com/sleepycat/persist/SecondaryIndex.html#subIndex(SK)"><CODE>SecondaryIndex.subIndex</CODE></A> for the
616employer ID, as shown below:
617<pre class="code">
618EntityCursor&lt;Person&gt; employees =
619    dao.personByEmployerIds.subIndex(gizmoInc.id).entities();
620try {
621    for (Person employee : employees) {
622        System.out.println(employee.ssn + ' ' + employee.name);
623    }
624} finally {
625    employees.close();
626}
627</pre></li>
628<li>Note that when Bob's employer is deleted in the example, the <code>Person</code>
629object for Bob is refetched to see the change to its <code>employerIds</code>.  This
630is because objects are accessed by value, not by reference.  In other words, no
631object cache or "persistence context" is maintained by the DPL.  The low level
632caching of the embedded Berkeley DB engine, combined with lightweight object
633bindings, provides maximum performance.</li>
634</ul>
635
636<a name="whichAPI"><h2>Which API to use?</h2></a>
637
638<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
639which API to use:</p>
640<ul>
641<li>When Java classes are used to represent domain objects in an application,
642the DPL is recommended.  The more domain classes, the more value there is in
643using annotations to define your schema.</li>
644<br>
645<li>When porting an application between Berkeley DB and Berkeley DB Java
646Edition, or when you've chosen not to use Java classes to represent domain
647objects, then the Base API is recommended.  You may also prefer to use this API
648if you have very few domain classes.</li>
649<br>
650<li>The Collections API is useful for interoperating with external components
651because it conforms to the standard Java Collections Framework.  It is
652therefore useful in combination with both the Base API and the DPL.  You may
653prefer this API because it provides the familiar Java Collections
654interface.</li>
655</ul>
656
657<a name="java14and15"><h2>Java 1.5 dependencies</h2></a>
658
659<p><em>NOTE:</em> The current release of the DPL requires compiling and
660deploying with Java 1.5 or greater.  Support for Java 1.4 may be added in a
661future release, based on user demand.</p>
662
663<p>The DPL uses two features of Java 1.5: generic types and annotations.  If
664you wish to avoid using these two Java 1.5 features, the DPL provides options
665for doing so.</p>
666
667<a name="genericTypes"><h3>Generic Types</h3></a>
668
669<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
670use generic types, you can simply not declare your index and cursor objects
671using generic type parameters.  This is the same as using the Java 1.5
672Collections Framework without using generic types.</p>
673
674<a name="annotations"><h3>Annotations</h3></a>
675
676<p>If you don't wish to use annotations, you can provide another source of
677metadata 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
678configuration file might be used as a source of metadata.  However, if you
679don't use annotations then you won't be able to use bytecode enhancement, which
680is described next.</p>
681
682<a name="bytecode"><h2>Bytecode Enhancement</h2></a>
683
684<p>The persistent fields of a class may be private, package-private, protected
685or public.  The DPL can access persistent fields either by bytecode enhancement
686or by reflection.</p>
687
688<p>Bytecode enhancement may be used to fully optimize binding performance and
689to avoid the use of Java reflection.  In applications that are CPU bound,
690avoiding Java reflection can have a significant performance impact.</p>
691
692<p>Bytecode enhancement may be performed either at runtime or at build time
693(offline).  When enhancement is performed at runtime, persistent classes are
694enhanced as they are loaded.  When enhancement is performed offline, class
695files are enhanced during a post-compilation step.
696Enhanced classes are used to efficiently access all fields and default
697constructors, including non-public members.</p>
698
699<p>See <A HREF="/com/sleepycat/persist/model/ClassEnhancer.html" title="class in com.sleepycat.persist.model"><CODE>ClassEnhancer</CODE></A> for
700bytecode enhancement configuration details.</p>
701
702<p>If bytecode enhancement is not used as described above, the DPL will use
703reflection for accessing persistent fields and the default constructor.  The
704<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
705non-public fields and constructors.  If you are running under a Java security
706manager you must configure your security policy to allow the following
707permission:</p>
708
709<p><code>permission java.lang.reflect.ReflectPermission "suppressAccessChecks";</code>
710
711<p>There are three cases where setting the above permission is <em>not</em>
712required:</p>
713<ol>
714<li>If you are not running under a Java Security Manager, then access to
715non-public members via reflection is not restricted.  This is the default for
716J2SE.</li>
717<br>
718<li>If all persistent fields and default constructors are <code>public</code> then
719they can be accessed via reflection without special permissions, even when
720running under a Java Security Manager.  However, declaring <code>public</code>
721instance fields is not recommended because it discourages encapsulation.</li>
722<br>
723<li>If bytecode enhancement is used as described above, then reflection will
724not be used.</li>
725</ol>
726
727<p>It is well known that executing generated code is faster than reflection.
728However, this performance difference may or may not impact a given application
729since it may be overshadowed by other factors.  Performance testing in a
730realistic usage scenario is the best way to determine the impact.  If you are
731determined to avoid the use of reflection then option 3 above is
732recommended.</p>
733<P>
734
735<P>
736<DL>
737</DL>
738<HR>
739
740
741<!-- ======= START OF BOTTOM NAVBAR ====== -->
742<A NAME="navbar_bottom"><!-- --></A>
743<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
744<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
745<TR>
746<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
747<A NAME="navbar_bottom_firstrow"><!-- --></A>
748<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
749  <TR ALIGN="center" VALIGN="top">
750  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A>&nbsp;</TD>
751  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Package</B></FONT>&nbsp;</TD>
752  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
753  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-use.html"><FONT CLASS="NavBarFont1"><B>Use</B></FONT></A>&nbsp;</TD>
754  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
755  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
756  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
757  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="/help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
758  </TR>
759</TABLE>
760</TD>
761<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
762<b>Berkeley DB</b><br><font size="-1"> version 4.7.25</font></EM>
763</TD>
764</TR>
765
766<TR>
767<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
768&nbsp;<A HREF="/com/sleepycat/db/package-summary.html"><B>PREV PACKAGE</B></A>&nbsp;
769&nbsp;<A HREF="/com/sleepycat/persist/evolve/package-summary.html"><B>NEXT PACKAGE</B></A></FONT></TD>
770<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
771  <A HREF="/index.html?com/sleepycat/persist/package-summary.html" target="_top"><B>FRAMES</B></A>  &nbsp;
772&nbsp;<A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
773&nbsp;<SCRIPT type="text/javascript">
774  <!--
775  if(window==top) {
776    document.writeln('<A HREF="/allclasses-noframe.html"><B>All Classes</B></A>');
777  }
778  //-->
779</SCRIPT>
780<NOSCRIPT>
781  <A HREF="/allclasses-noframe.html"><B>All Classes</B></A>
782</NOSCRIPT>
783
784
785</FONT></TD>
786</TR>
787</TABLE>
788<A NAME="skip-navbar_bottom"></A>
789<!-- ======== END OF BOTTOM NAVBAR ======= -->
790
791<HR>
792<font size=1>Copyright (c) 1996,2008 Oracle.  All rights reserved.</font>
793</BODY>
794</HTML>
795