• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt/router/db-4.8.30/java/src/com/sleepycat/persist/
1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002-2009 Oracle.  All rights reserved.
5 *
6 * $Id$
7 */
8
9package com.sleepycat.persist;
10
11import java.util.Set;
12
13import com.sleepycat.db.Database; // for javadoc
14import com.sleepycat.db.DatabaseConfig;
15import com.sleepycat.db.DatabaseException;
16import com.sleepycat.db.Environment;
17import com.sleepycat.db.SecondaryConfig;
18import com.sleepycat.db.Sequence;
19import com.sleepycat.db.SequenceConfig;
20import com.sleepycat.db.Transaction;
21import com.sleepycat.persist.evolve.EvolveConfig;
22import com.sleepycat.persist.evolve.EvolveStats;
23import com.sleepycat.persist.evolve.IncompatibleClassException;
24import com.sleepycat.persist.evolve.Mutations;
25import com.sleepycat.persist.impl.Store;
26import com.sleepycat.persist.model.DeleteAction;
27import com.sleepycat.persist.model.Entity; // for javadoc
28import com.sleepycat.persist.model.EntityModel;
29import com.sleepycat.persist.model.PrimaryKey;
30import com.sleepycat.persist.model.SecondaryKey;
31
32/**
33 * A store for managing persistent entity objects.
34 *
35 * <p>{@code EntityStore} objects are thread-safe.  Multiple threads may safely
36 * call the methods of a shared {@code EntityStore} object.</p>
37 *
38 * <p>See the {@link <a href="package-summary.html#example">package
39 * summary example</a>} for an example of using an {@code EntityStore}.</p>
40 *
41 * <p>Before creating an <code>EntityStore</code> you must create an {@link
42 * Environment} object using the Berkeley DB engine API.  The environment may
43 * contain any number of entity stores and their associated databases, as well
44 * as other databases not associated with an entity store.</p>
45 *
46 * <p>An entity store is based on an {@link EntityModel}: a data model which
47 * defines persistent classes (<em>entity classes</em>), primary keys,
48 * secondary keys, and relationships between entities.  A primary index is
49 * created for each entity class.  An associated secondary index is created for
50 * each secondary key.  The {@link Entity}, {@link PrimaryKey} and {@link
51 * SecondaryKey} annotations may be used to define entities and keys.</p>
52 *
53 * <p>To use an <code>EntityStore</code>, first obtain {@link PrimaryIndex} and
54 * {@link SecondaryIndex} objects by calling {@link #getPrimaryIndex
55 * getPrimaryIndex} and {@link #getSecondaryIndex getSecondaryIndex}.  Then use
56 * these indices to store and access entity records by key.</p>
57 *
58 * <p>Although not normally needed, you can also use the entity store along
59 * with the {@link com.sleepycat.db Base API}.  Methods in the {@link
60 * PrimaryIndex} and {@link SecondaryIndex} classes may be used to obtain
61 * databases and bindings.  The databases may be used directly for accessing
62 * entity records.  The bindings should be called explicitly to translate
63 * between {@link com.sleepycat.db.DatabaseEntry} objects and entity model
64 * objects.</p>
65 *
66 * <p>Each primary and secondary index is associated internally with a {@link
67 * Database}.  With any of the above mentioned use cases, methods are provided
68 * that may be used for database performance tuning.  The {@link
69 * #setPrimaryConfig setPrimaryConfig} and {@link #setSecondaryConfig
70 * setSecondaryConfig} methods may be called anytime before a database is
71 * opened via {@link #getPrimaryIndex getPrimaryIndex} or {@link
72 * #getSecondaryIndex getSecondaryIndex}.  The {@link #setSequenceConfig
73 * setSequenceConfig} method may be called anytime before {@link #getSequence
74 * getSequence} is called or {@link #getPrimaryIndex getPrimaryIndex} is called
75 * for a primary index associated with that sequence.</p>
76 *
77 *
78 * @author Mark Hayes
79 */
80public class EntityStore {
81
82    private Store store;
83
84    /**
85     * Opens an entity store in a given environment.
86     *
87     * @param env an open Berkeley DB Environment.
88     *
89     * @param storeName the name of the entity store within the given
90     * environment.  An empty string is allowed.  Named stores may be used to
91     * distinguish multiple sets of persistent entities for the same entity
92     * classes in a single environment.  Underlying database names are prefixed
93     * with the store name.
94     *
95     * @param config the entity store configuration, or null to use default
96     * configuration properties.
97     *
98     * @throws IncompatibleClassException if an incompatible class change has
99     * been made and mutations are not configured for handling the change.  See
100     * {@link com.sleepycat.persist.evolve Class Evolution} for more
101     * information.
102     */
103    public EntityStore(Environment env, String storeName, StoreConfig config)
104        throws StoreExistsException,
105               StoreNotFoundException,
106               IncompatibleClassException,
107               DatabaseException {
108
109        store = new Store(env, storeName, config, false /*rawAccess*/);
110    }
111
112    /**
113     * Returns the environment associated with this store.
114     *
115     * @return the environment.
116     */
117    public Environment getEnvironment() {
118        return store.getEnvironment();
119    }
120
121    /**
122     * Returns a copy of the entity store configuration.
123     *
124     * @return the config.
125     */
126    public StoreConfig getConfig() {
127        return store.getConfig();
128    }
129
130    /**
131     * Returns the name of this store.
132     *
133     * @return the name.
134     */
135    public String getStoreName() {
136        return store.getStoreName();
137    }
138
139
140    /**
141     * Returns the current entity model for this store.  The current model is
142     * derived from the configured entity model and the live entity class
143     * definitions.
144     *
145     * @return the model.
146     */
147    public EntityModel getModel() {
148        return store.getModel();
149    }
150
151    /**
152     * Returns the set of mutations that were configured when the store was
153     * opened, or if none were configured, the set of mutations that were
154     * configured and stored previously.
155     *
156     * @return the mutations.
157     */
158    public Mutations getMutations() {
159        return store.getMutations();
160    }
161
162    /**
163     * Returns the primary index for a given entity class, opening it if
164     * necessary.
165     *
166     * <p>If they are not already open, the primary and secondary databases for
167     * the entity class are created/opened together in a single internal
168     * transaction.  When the secondary indices are opened, that can cascade to
169     * open other related primary indices.</p>
170     *
171     * @param primaryKeyClass the class of the entity's primary key field, or
172     * the corresponding primitive wrapper class if the primary key field type
173     * is a primitive.
174     *
175     * @param entityClass the entity class for which to open the primary index.
176     *
177     * @return the primary index.
178     *
179     * @throws IllegalArgumentException if the entity class or classes
180     * referenced by it are not persistent, or the primary key class does not
181     * match the entity's primary key field, or if metadata for the entity or
182     * primary key is invalid.
183     */
184    public <PK,E> PrimaryIndex<PK,E> getPrimaryIndex(Class<PK> primaryKeyClass,
185                                                     Class<E> entityClass)
186        throws DatabaseException {
187
188        return store.getPrimaryIndex
189            (primaryKeyClass, primaryKeyClass.getName(),
190             entityClass, entityClass.getName());
191    }
192
193    /**
194     * Returns a secondary index for a given primary index and secondary key,
195     * opening it if necessary.
196     *
197     * <p><em>NOTE:</em> If the secondary key field is declared in a subclass
198     * of the entity class, use {@link #getSubclassIndex} instead.</p>
199     *
200     * <p>If a {@link SecondaryKey#relatedEntity} is used and the primary index
201     * for the related entity is not already open, it will be opened by this
202     * method.  That will, in turn, open its secondary indices, which can
203     * cascade to open other primary indices.</p>
204     *
205     * @param primaryIndex the primary index associated with the returned
206     * secondary index.  The entity class of the primary index, or one of its
207     * superclasses, must contain a secondary key with the given secondary key
208     * class and key name.
209     *
210     * @param keyClass the class of the secondary key field, or the
211     * corresponding primitive wrapper class if the secondary key field type is
212     * a primitive.
213     *
214     * @param keyName the name of the secondary key field, or the {@link
215     * SecondaryKey#name} if this name annotation property was specified.
216     *
217     * @return the secondary index.
218     *
219     * @throws IllegalArgumentException if the entity class or one of its
220     * superclasses does not contain a key field of the given key class and key
221     * name, or if the metadata for the secondary key is invalid.
222     */
223    public <SK,PK,E> SecondaryIndex<SK,PK,E>
224        getSecondaryIndex(PrimaryIndex<PK,E> primaryIndex,
225                          Class<SK> keyClass,
226                          String keyName)
227        throws DatabaseException {
228
229        return store.getSecondaryIndex
230            (primaryIndex, primaryIndex.getEntityClass(),
231             primaryIndex.getEntityClass().getName(),
232             keyClass, keyClass.getName(), keyName);
233    }
234
235    /**
236     * Returns a secondary index for a secondary key in an entity subclass,
237     * opening it if necessary.
238     *
239     * <p>If a {@link SecondaryKey#relatedEntity} is used and the primary index
240     * for the related entity is not already open, it will be opened by this
241     * method.  That will, in turn, open its secondary indices, which can
242     * cascade to open other primary indices.</p>
243     *
244     * @param primaryIndex the primary index associated with the returned
245     * secondary index.  The entity class of the primary index, or one of its
246     * superclasses, must contain a secondary key with the given secondary key
247     * class and key name.
248     *
249     * @param entitySubclass a subclass of the entity class for the primary
250     * index.  The entity subclass must contain a secondary key with the given
251     * secondary key class and key name.
252     *
253     * @param keyClass the class of the secondary key field, or the
254     * corresponding primitive wrapper class if the secondary key field type is
255     * a primitive.
256     *
257     * @param keyName the name of the secondary key field, or the {@link
258     * SecondaryKey#name} if this name annotation property was specified.
259     *
260     * @return the secondary index.
261     *
262     * @throws IllegalArgumentException if the given entity subclass does not
263     * contain a key field of the given key class and key name, or if the
264     * metadata for the secondary key is invalid.
265     */
266    public <SK,PK,E1,E2 extends E1> SecondaryIndex<SK,PK,E2>
267        getSubclassIndex(PrimaryIndex<PK,E1> primaryIndex,
268                         Class<E2> entitySubclass,
269                         Class<SK> keyClass,
270                         String keyName)
271        throws DatabaseException {
272
273        /* Make subclass metadata available before getting the index. */
274        getModel().getClassMetadata(entitySubclass.getName());
275
276        return store.getSecondaryIndex
277            (primaryIndex, entitySubclass,
278             primaryIndex.getEntityClass().getName(),
279             keyClass, keyClass.getName(), keyName);
280    }
281
282    /**
283     * Performs conversion of unevolved objects in order to reduce lazy
284     * conversion overhead.  Evolution may be performed concurrently with
285     * normal access to the store.
286     *
287     * <p>Conversion is performed one entity class at a time.  An entity class
288     * is converted only if it has {@link Mutations} associated with it via
289     * {@link StoreConfig#setMutations StoreConfig.setMutations}.</p>
290     *
291     * <p>Conversion of an entity class is performed by reading each entity,
292     * converting it if necessary, and updating it if conversion was performed.
293     * When all instances of an entity class are converted, references to the
294     * appropriate {@link Mutations} are deleted.  Therefore, if this method is
295     * called twice successfully without changing class definitions, the second
296     * call will do nothing.</p>
297     *
298     * @see com.sleepycat.persist.evolve Class Evolution
299     */
300    public EvolveStats evolve(EvolveConfig config)
301        throws DatabaseException {
302
303        return store.evolve(config);
304    }
305
306    /**
307     * Deletes all instances of this entity class and its (non-entity)
308     * subclasses.
309     *
310     * <p>The primary database for the given entity class will be truncated and
311     * all secondary databases will be removed.  The primary and secondary
312     * databases associated with the entity class must not be open except by
313     * this store, since database truncation/removal is only possible when the
314     * database is not open.  The databases to be truncated/removed will be
315     * closed before performing this operation, if they were previously opened
316     * by this store.</p>
317     *
318     * <p>Auto-commit is used implicitly if the store is transactional.</p>
319     *
320     * @param entityClass the entity class whose instances are to be deleted.
321     */
322    public void truncateClass(Class entityClass)
323        throws DatabaseException {
324
325        store.truncateClass(null, entityClass);
326    }
327
328    /**
329     * Deletes all instances of this entity class and its (non-entity)
330     * subclasses.
331     *
332     * <p>The primary database for the given entity class will be truncated and
333     * all secondary databases will be removed.  The primary and secondary
334     * databases associated with the entity class must not be open except by
335     * this store, since database truncation/removal is only possible when the
336     * database is not open.  The databases to be truncated/removed will be
337     * closed before performing this operation, if they were previously opened
338     * by this store.</p>
339     *
340     * @param txn the transaction used to protect this operation, null to use
341     * auto-commit, or null if the store is non-transactional.
342     *
343     * @param entityClass the entity class whose instances are to be deleted.
344     */
345    public void truncateClass(Transaction txn, Class entityClass)
346        throws DatabaseException {
347
348        store.truncateClass(txn, entityClass);
349    }
350
351
352    /**
353     * Closes the primary and secondary databases for the given entity class
354     * that were opened via this store.  The caller must ensure that the
355     * primary and secondary indices obtained from this store are no longer in
356     * use.
357     *
358     * @param entityClass the entity class whose databases are to be closed.
359     */
360    public void closeClass(Class entityClass)
361        throws DatabaseException {
362
363        store.closeClass(entityClass);
364    }
365
366    /**
367     * Closes all databases and sequences that were opened via this store.  The
368     * caller must ensure that no databases opened via this store are in use.
369     */
370    public void close()
371        throws DatabaseException {
372
373        store.close();
374    }
375
376    /**
377     * Returns a named sequence for using Berkeley DB engine API directly,
378     * opening it if necessary.
379     *
380     * @param name the sequence name, which is normally defined using the
381     * {@link PrimaryKey#sequence} annotation property.
382     *
383     * @return the open sequence for the given sequence name.
384     */
385    public Sequence getSequence(String name)
386        throws DatabaseException {
387
388        return store.getSequence(name);
389    }
390
391    /**
392     * Returns the default Berkeley DB engine API configuration for a named key
393     * sequence.
394     *
395     * </p>The returned configuration is as follows.  All other properties have
396     * default values.</p>
397     * <ul>
398     * <li>The {@link SequenceConfig#setInitialValue InitialValue} is one.</li>
399     * <li>The {@link SequenceConfig#setRange Range} minimum is one.</li>
400     * <li>The {@link SequenceConfig#setCacheSize CacheSize} is 100.</li>
401     * <li>{@link SequenceConfig#setAutoCommitNoSync AutoCommitNoSync} is
402     * true.</li>
403     * <li>{@link SequenceConfig#setAllowCreate AllowCreate} is set to the
404     * inverse of the store {@link StoreConfig#setReadOnly ReadOnly}.
405     * setting.</li>
406     * </ul>
407     *
408     * @param name the sequence name, which is normally defined using the
409     * {@link PrimaryKey#sequence} annotation property.
410     *
411     * @return the default configuration for the given sequence name.
412     */
413    public SequenceConfig getSequenceConfig(String name) {
414        return store.getSequenceConfig(name);
415    }
416
417    /**
418     * Configures a named key sequence using the Berkeley DB engine API.
419     *
420     * <p>To be compatible with the entity model and the Direct Persistence
421     * Layer, the configuration should be retrieved using {@link
422     * #getSequenceConfig getSequenceConfig}, modified, and then passed to this
423     * method.  The following configuration properties may not be changed:</p>
424     * <ul>
425     * <li>{@link SequenceConfig#setExclusiveCreate ExclusiveCreate}</li>
426     * </ul>
427     * <p>In addition, {@link SequenceConfig#setAllowCreate AllowCreate} must be
428     * the inverse of {@code ReadOnly}</p>
429     *
430     * <p>If the range is changed to include the value zero, see {@link
431     * PrimaryKey} for restrictions.</p>
432     *
433     * @param name the sequence name, which is normally defined using the
434     * {@link PrimaryKey#sequence} annotation property.
435     *
436     * @param config the configuration to use for the given sequence name.
437     *
438     * @throws IllegalArgumentException if the configuration is incompatible
439     * with the entity model or the Direct Persistence Layer.
440     *
441     * @throws IllegalStateException if the sequence has already been opened.
442     */
443    public void setSequenceConfig(String name, SequenceConfig config) {
444        store.setSequenceConfig(name, config);
445    }
446
447    /**
448     * Returns the default primary database Berkeley DB engine API
449     * configuration for an entity class.
450     *
451     * </p>The returned configuration is as follows.  All other properties have
452     * default values.</p>
453     * <ul>
454     * <li>{@link DatabaseConfig#setTransactional Transactional} is set to
455     * match {@link StoreConfig#setTransactional StoreConfig}.</li>
456     * <li>{@link DatabaseConfig#setAllowCreate AllowCreate} is set to the
457     * inverse of the store {@link StoreConfig#setReadOnly ReadOnly}.
458     * setting.</li>
459     * <li>{@link DatabaseConfig#setReadOnly ReadOnly} is set to match
460     * {@link StoreConfig#setReadOnly StoreConfig}.</li>
461     * <li>{@link DatabaseConfig#setBtreeComparator BtreeComparator} is set to
462     * an internal class if a key comparator is used.</li>
463     * </ul>
464     *
465     * @param entityClass the entity class identifying the primary database.
466     *
467     * @return the default configuration for the given entity class.
468     */
469    public DatabaseConfig getPrimaryConfig(Class entityClass) {
470        return store.getPrimaryConfig(entityClass);
471    }
472
473    /**
474     * Configures the primary database for an entity class using the Berkeley
475     * DB engine API.
476     *
477     * <p>To be compatible with the entity model and the Direct Persistence
478     * Layer, the configuration should be retrieved using {@link
479     * #getPrimaryConfig getPrimaryConfig}, modified, and then passed to this
480     * method.  The following configuration properties may not be changed:</p>
481     * <ul>
482     * <li>{@link DatabaseConfig#setExclusiveCreate ExclusiveCreate}</li>
483     * <li>{@link DatabaseConfig#setSortedDuplicates SortedDuplicates}</li>
484     * <li>{@link DatabaseConfig#setBtreeComparator BtreeComparator}</li>
485     * </ul>
486     * <p>In addition, {@link DatabaseConfig#setAllowCreate AllowCreate} must be
487     * the inverse of {@code ReadOnly}</p>
488     *
489     * @param entityClass the entity class identifying the primary database.
490     *
491     * @param config the configuration to use for the given entity class.
492     *
493     * @throws IllegalArgumentException if the configuration is incompatible
494     * with the entity model or the Direct Persistence Layer.
495     *
496     * @throws IllegalStateException if the database has already been opened.
497     */
498    public void setPrimaryConfig(Class entityClass, DatabaseConfig config) {
499        store.setPrimaryConfig(entityClass, config);
500    }
501
502    /**
503     * Returns the default secondary database Berkeley DB engine API
504     * configuration for an entity class and key name.
505     *
506     * </p>The returned configuration is as follows.  All other properties have
507     * default values.</p>
508     * <ul>
509     * <li>{@link DatabaseConfig#setTransactional Transactional} is set to
510     * match the primary database.</li>
511     * <li>{@link DatabaseConfig#setAllowCreate AllowCreate} is set to the
512     * inverse of the primary database {@link DatabaseConfig#setReadOnly
513     * ReadOnly} setting.</li>
514     * <li>{@link DatabaseConfig#setReadOnly ReadOnly} is set to match
515     * the primary database.</li>
516     * <li>{@link DatabaseConfig#setBtreeComparator BtreeComparator} is set to
517     * an internal class if a key comparator is used.</li>
518     * <li>{@link DatabaseConfig#setSortedDuplicates SortedDuplicates} is set
519     * according to {@link SecondaryKey#relate}.</p>
520     * <li>{@link SecondaryConfig#setAllowPopulate AllowPopulate} is set to
521     * true when a secondary key is added to an existing primary index.</li>
522     * <li>{@link SecondaryConfig#setKeyCreator KeyCreator} or {@link
523     * SecondaryConfig#setMultiKeyCreator MultiKeyCreator} is set to an
524     * internal instance.</p>
525     * <li>{@link SecondaryConfig#setForeignMultiKeyNullifier
526     * ForeignMultiKeyNullifier} is set to an internal instance if {@link
527     * SecondaryKey#onRelatedEntityDelete} is {@link DeleteAction#NULLIFY}.</li>
528     * </ul>
529     *
530     * @param entityClass the entity class containing the given secondary key
531     * name.
532     *
533     * @param keyName the name of the secondary key field, or the {@link
534     * SecondaryKey#name} if this name annotation property was specified.
535     *
536     * @return the default configuration for the given secondary key.
537     */
538    public SecondaryConfig getSecondaryConfig(Class entityClass,
539                                              String keyName) {
540        return store.getSecondaryConfig(entityClass, keyName);
541    }
542
543    /**
544     * Configures a secondary database for an entity class and key name using
545     * the Berkeley DB engine API.
546     *
547     * <p>To be compatible with the entity model and the Direct Persistence
548     * Layer, the configuration should be retrieved using {@link
549     * #getSecondaryConfig getSecondaryConfig}, modified, and then passed to
550     * this method.  The following configuration properties may not be
551     * changed:</p>
552     * <ul>
553     * <li>{@link DatabaseConfig#setExclusiveCreate ExclusiveCreate}</li>
554     * <li>{@link DatabaseConfig#setSortedDuplicates SortedDuplicates}</li>
555     * <li>{@link DatabaseConfig#setBtreeComparator BtreeComparator}</li>
556     * <li>{@link DatabaseConfig#setDuplicateComparator
557     * DuplicateComparator}</li>
558     * <li>{@link SecondaryConfig#setAllowPopulate AllowPopulate}</li>
559     * <li>{@link SecondaryConfig#setKeyCreator KeyCreator}</li>
560     * <li>{@link SecondaryConfig#setMultiKeyCreator MultiKeyCreator}</li>
561     * <li>{@link SecondaryConfig#setForeignKeyNullifier
562     * ForeignKeyNullifier}</li>
563     * <li>{@link SecondaryConfig#setForeignMultiKeyNullifier
564     * ForeignMultiKeyNullifier}</li>
565     * <li>{@link SecondaryConfig#setForeignKeyDeleteAction
566     * ForeignKeyDeleteAction}</li>
567     * <li>{@link SecondaryConfig#setForeignKeyDatabase
568     * ForeignKeyDatabase}</li>
569     * </ul>
570     * <p>In addition, {@link DatabaseConfig#setAllowCreate AllowCreate} must be
571     * the inverse of {@code ReadOnly}</p>
572     *
573     * @param entityClass the entity class containing the given secondary key
574     * name.
575     *
576     * @param keyName the name of the secondary key field, or the {@link
577     * SecondaryKey#name} if this name annotation property was specified.
578     *
579     * @param config the configuration to use for the given secondary key.
580     *
581     * @throws IllegalArgumentException if the configuration is incompatible
582     * with the entity model or the Direct Persistence Layer.
583     *
584     * @throws IllegalStateException if the database has already been opened.
585     */
586    public void setSecondaryConfig(Class entityClass,
587                                   String keyName,
588                                   SecondaryConfig config) {
589        store.setSecondaryConfig(entityClass, keyName, config);
590    }
591}
592