Class Database
Includes support for:
- Objects and fields defined by a
SchemaModel, with positive schema verification - Simple value fields containing any standard or custom type that has an
Encoding - Invertable reference fields with referential integrity and configurable delete cascading
- Lockless counter fields
- Complex fields of type
List,NavigableSet, andNavigableMap - Configurable indexing of any simple field or complex sub-field
- Composite indexes on multiple simple fields
- Notification of object creation and deletion
- Notification of object field changes, as seen through an arbitrary path of references
- Automatic schema tracking and migration with notification support
See Transaction for further details on the above functionality.
This class defines an abstraction layer that usually sits below a Permazen but is completely
independent of Permazen and can be used on its own.
Compared to Permazen, a Database has these differences:
- A
SchemaModelmust be explicitly provided to define the schema in use, whereas when using aPermazenthe schema is derived automatically from annotated Java model classes. - Simple fields are encoded/decoded into
byte[]arrays using anEncodingwhich defines the field's "type". - References from one object to another are represented by
ObjIds and encoded/decoded usingReferenceEncoding. - There is no explicit notion of object sub-types, i.e., the object type hierarchy is completely flat. However, object types can share the same field definitions, and reference fields can be restricted to only refer to certain other object types.
- There is no automatic validation support.
Schema Tracking
Within each Database is stored a record of all schemas used with that database (termed the "schema bundle").
When creating a new transaction, the caller provides a SchemaModel to use for accessing objects in the transaction.
If the schema is not already registered in the database, it is automatically registered if at the start of the transaction
assuming TransactionConfig.isAllowNewSchema() is true (otherwise a SchemaMismatchException is thrown).
Transactions can be opened with an empty SchemaModel when no particular schema
is needed. In any case, the empty SchemaModel is never recorded in a database.
Schema Migration
Each object in a Database is associated with an object type in one of the registered schemas;
this dictates which fields the object contains, how they are indexed, etc. Newly created objects are always defined
in terms of the transaction's configured schema, but it's also possible to access objects that were created
in previous transactions under different schemas.
When an object is accessed during a Transaction, if the object's schema is not the transaction's configured
schema, then (if requested) the object will be automatically migrated to the transaction's schema if the object's type
still exists (otherwise a TypeNotInSchemaException is thrown).
Object migration involves the following steps:
- Fields that exist in the old schema but not in the current schema are removed.
- Fields that exist in the current schema but not in the old schema are initialized to their default values.
- For fields that are common to both the old and the new schema:
- If the two field's
Encodings are the same, the value is not changed - Otherwise, the field's old value is converted to the new
Encoding, if possible, viaEncoding.convert(). - Otherwise, the field is reset to its default value.
- Any
SchemaChangeListeners registered with theTransactionare notified.
Object type and field identity is based on names. So when comparing across schemas, two object types or fields are assumed to be "the same" if they have the same name.
Indexes may be added and removed across different schemas without losing information, however,
indexes will only contain those objects whose schema includes the index. In other words, it's not
possible to find an object using an index that was added after the object was created until the object
is migrated to a newer schema. The same principle applies to other schema-defined behavior, for example,
the DeleteAction taken when a referenced object is deleted depends on the DeleteAction
configured in the schema of the object containing the reference.
- See Also:
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intThe maximum number of fields that may be indexed in a composite index (4). -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptioncreateDetachedTransaction(KVStore kvstore, TransactionConfig txConfig) Create a detached transaction based on the provided key/value store.createTransaction(TransactionConfig txConfig) Create a newTransactionon this database using the specific configuration.createTransaction(KVTransaction kvt, TransactionConfig txConfig) Create a newTransactionon this database using an already-openedKVTransactionand specified configuration.createTransaction(SchemaModel schemaModel) Create a newTransactionon this database using the givenSchemaModeland the defaults for all otherTransactionConfigitems.Get theEncodingRegistryassociated with this instance.Get theKVDatabaseunderlying this instance.voidsetEncodingRegistry(EncodingRegistry encodingRegistry) Set theEncodingRegistryassociated with this instance.
-
Field Details
-
MAX_INDEXED_FIELDS
public static final int MAX_INDEXED_FIELDSThe maximum number of fields that may be indexed in a composite index (4).- See Also:
-
-
Constructor Details
-
Database
Constructor.- Parameters:
kvdb- the underlying key/value store in which to store information- Throws:
IllegalArgumentException- ifkvdbis null
-
-
Method Details
-
getEncodingRegistry
Get theEncodingRegistryassociated with this instance.By default a
DefaultEncodingRegistryis automatically created.- Returns:
- encoding registry associated with this instance
-
setEncodingRegistry
Set theEncodingRegistryassociated with this instance.- Parameters:
encodingRegistry- encoding registry to associate with this instance- Throws:
IllegalArgumentException- ifencodingRegistryis null
-
getKVDatabase
Get theKVDatabaseunderlying this instance.- Returns:
- underlying key/value database
-
createTransaction
Create a newTransactionon this database using the givenSchemaModeland the defaults for all otherTransactionConfigitems.Equivalent to:
createTransaction(TransactionConfig.builder().schemaModel(schemaModel).build()).- Parameters:
schemaModel- schema model- Returns:
- newly created transaction
- Throws:
InvalidSchemaException- if the configured schema is invalid (i.e., does not pass validation checks)SchemaMismatchException- if the configuredSchemaModelhas any explicit storage ID assignments that conflict with storage ID assignments already recorded in the databaseInconsistentDatabaseException- if inconsistent or invalid meta-data is detected in the databaseInconsistentDatabaseException- if an uninitialized database is encountered but the database is not emptyIllegalArgumentException- ifschemaModelis null
-
createTransaction
Create a newTransactionon this database using the specific configuration.- Parameters:
txConfig- transaction configuration- Returns:
- newly created transaction
- Throws:
InvalidSchemaException- if the configured schema is invalid (i.e., does not pass validation checks)SchemaMismatchException- if the configured schema is not registered in the database andTransactionConfig.isAllowNewSchema()is falseSchemaMismatchException- if the configuredSchemaModelhas any explicit storage ID assignments that conflict with storage ID assignments already recorded in the databaseInconsistentDatabaseException- if inconsistent or invalid meta-data is detected in the databaseInconsistentDatabaseException- if an uninitialized database is encountered but the database is not emptyIllegalArgumentException- iftxConfigis null
-
createTransaction
Create a newTransactionon this database using an already-openedKVTransactionand specified configuration.The given
KVTransactionwill be committed or rolled-back along with the returnedTransaction.See
createTransaction(TransactionConfig)for further details.- Parameters:
kvt- already opened key/value store transactiontxConfig- transaction configuration- Returns:
- newly created transaction
- Throws:
IllegalArgumentException- ifkvtortxConfigis null
-
createDetachedTransaction
Create a detached transaction based on the provided key/value store.The key/value store will be initialized if necessary (i.e.,
kvstoremay be empty), otherwise it will be validated against the schema information associated with this instance.The returned
DetachedTransactiondoes not supportcommit()orrollback()and can be used indefinitely. It does supportaddCallback()but that method has no effect because the transaction cannot be committed.DetachedTransaction's do implementCloseable; if thkvstoreis aCloseableKVStore, then it will beclose()'d if/when the returnedDetachedTransactionis.See
createTransaction(TransactionConfig)for further details.- Parameters:
kvstore- key/value store, empty or having content compatible with this transaction'sDatabasetxConfig- transaction configuration- Returns:
- detached transaction based on
kvstore - Throws:
InvalidSchemaException- if the configured schema is invalid (i.e., does not pass validation checks)SchemaMismatchException- if the configuredSchemaModelhas any explicit storage ID assignments that conflict with storage ID assignments already recorded in the databaseInconsistentDatabaseException- if inconsistent or invalid meta-data is detected in the databaseInconsistentDatabaseException- if an uninitialized database is encountered but the database is not emptyIllegalArgumentException- ifkvstoreortxConfigis null
-