Package io.permazen

Class Permazen


  • public class Permazen
    extends Object
    Permazen Java persistence layer.

    Permazen is a Java persistence solution built on three layers of abstraction:

    • At the bottom is a simple Key/Value Layer represented by KVDatabase. Transactions are supported at this layer and are accessed via KVTransaction. There are several available KVDatabase implementations, including "wrappers" for several third party key/value stores.
    • On top of that sits the Core API Layer, which provides a rigourous "object database" abstraction on top of a KVDatabase. It supports simple fields of any Java type that can be (de)serialized to/from a byte[] array, as well as list, set, and map complex fields, tightly controlled schema versioning, simple and composite indexes, and lifecycle and change notifications. It is not Java-specific or explicitly object-oriented: an "object" at this layer is just a structure with defined fields. The core API layer may be accessed through the Database and Transaction classes.
    • The Java Layer is a Java-centric, object-oriented persistence layer for Java applications. It sits on top of the core API layer and provides a fully "Java" view of the underlying data where all data access is through user-supplied Java model classes. All schema definition and listeners are specified through Java annotations. Incremental JSR 303 validation is supported. The Permazen class represents an instance of this top layer database, and JTransaction represents the corresonding transactions.

    User-provided Java model classes define database fields by declaring abstract Java bean methods. Permazen generates concrete subclasses of the user-provided abstract model classes at runtime. These runtime classes implement the Java bean methods as well as the JObject interface. Instances of these classes are always associated with a specific JTransaction, and all of their database state derives from that the underlying key/value KVTransaction.

    All Java model class instances have a unique ObjId which represents database identity. Permazen guarantees that at most one Java instance will exist for any given JTransaction and ObjId. Instance creation, index queries, and certain other database-related tasks are initiated using a JTransaction.

    Normal database transactions are created via createTransaction(). "Snapshot" transactions are purely in-memory transactions that are detached from the database and may persist indefinitely; their purpose is to hold a snapshot of some (user-defined) portion of the database content for use outside of a regular transaction. Otherwise, they function like normal transactions, with support for index queries, listener callbacks, etc. See JTransaction.createSnapshotTransaction(), JTransaction.getSnapshotTransaction(), JObject.copyOut(), and JObject.copyIn().

    Instances of this class are usually created using a PermazenFactory.

    See Also:
    JObject, JTransaction, PermazenFactory, io.permazen.annotation, Permazen GitHub Page
    • Field Detail

      • GENERATED_CLASS_NAME_SUFFIX

        public static final String GENERATED_CLASS_NAME_SUFFIX
        The suffix that is appended to Java model class names to get the corresponding Permazen generated class name.
        See Also:
        Constant Field Values
    • Constructor Detail

      • Permazen

        public Permazen​(Database database,
                        int version,
                        StorageIdGenerator storageIdGenerator,
                        Iterable<? extends Class<?>> classes)
        Primary constructor.
        Parameters:
        database - core database to use
        version - schema version number of the schema derived from classes, zero to use the highest version already recorded in the database, or -1 to use an auto-generated schema version
        storageIdGenerator - generator for auto-generated storage ID's, or null to disallow auto-generation of storage ID's
        classes - classes annotated with @PermazenType annotations; non-annotated classes are ignored
        Throws:
        IllegalArgumentException - if database or classes is null
        IllegalArgumentException - if version is less than -1
        IllegalArgumentException - if classes contains a null class or a class with invalid annotation(s)
        InvalidSchemaException - if the schema implied by classes is invalid
    • Method Detail

      • getDatabase

        public Database getDatabase()
        Get the core API Database underlying this instance.
        Returns:
        underlying Database
      • getConfiguredVersion

        public int getConfiguredVersion()
        Get the schema version that this instance was configured to use.

        This will either be a specific non-zero schema version number, or zero, indicating that the highest schema version found in the database should be used.

        If -1 was configured, this will return the actual auto-generated schema version.

        Returns:
        the schema version that this instance will use when opening transactions via Database.createTransaction()
      • setConfiguredVersion

        public void setConfiguredVersion​(int version)
        Change the schema version that this instance is configured to use.
        Parameters:
        version - schema version number of the schema derived from classes, zero to use the highest version already recorded in the database, or -1 to use an auto-generated schema version
        Throws:
        IllegalArgumentException - if version is less than -1
      • getActualVersion

        public int getActualVersion()
        Get the schema version that this instance used for the most recently created transaction.

        If no transactions have been created yet, this returns zero. Otherwise, it returns the schema version used by the most recently created transaction.

        If the version passed to the constructor was zero, this method can be used to read the highest schema version seen in the database by the most recently created transaction.

        If the version passed to the constructor was non-zero, and at least one transaction has been created, this method will return the same value.

        Returns:
        the schema version that this instance used in the most recently created transaction
      • getModelClass

        @Deprecated
        public static Class<?> getModelClass​(JObject jobj)
        Deprecated.
        Get the Java model class of the given JObject.

        If jobj is an instance of a Permazen-generated subclass of a user-supplied Java model class, this returns the original Java model class.

        Parameters:
        jobj - database instance
        Returns:
        the original Java model class of which jobj is an instance
        Throws:
        IllegalArgumentException - if jobj is null
      • createTransaction

        public JTransaction createTransaction()
        Create a new transaction.

        Convenience method; equivalent to:

          createTransaction(true, ValidationMode.AUTOMATIC, null)
          
        Returns:
        the newly created transaction
        Throws:
        InvalidSchemaException - if the schema does not match what's recorded in the database for the schema version provided to the constructor
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is false
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is true, but the schema is incompatible with one or more previous schemas alread recorded in the database (i.e., the same storage ID is used incompatibly between schema versions)
        InconsistentDatabaseException - if inconsistent or invalid meta-data is detected in the database
      • createTransaction

        public JTransaction createTransaction​(boolean allowNewSchema,
                                              ValidationMode validationMode)
        Create a new transaction.

        Convenience method; equivalent to:

          createTransaction(allowNewSchema, validationMode, null)
          
        Parameters:
        allowNewSchema - whether creating a new schema version is allowed
        validationMode - the ValidationMode to use for the new transaction
        Returns:
        the newly created transaction
        Throws:
        InvalidSchemaException - if the schema does not match what's recorded in the database for the schema version provided to the constructor
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is false
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is true, but the schema is incompatible with one or more previous schemas alread recorded in the database (i.e., the same storage ID is used incompatibly between schema versions)
        InconsistentDatabaseException - if inconsistent or invalid meta-data is detected in the database
        IllegalArgumentException - if validationMode is null
      • createTransaction

        public JTransaction createTransaction​(boolean allowNewSchema,
                                              ValidationMode validationMode,
                                              Map<String,​?> kvoptions)
        Create a new transaction with key/value transaction options.

        This does not invoke JTransaction.setCurrent(): the caller is responsible for doing that if necessary. However, this method does arrange for JTransaction.setCurrent(null) to be invoked as soon as the returned transaction is committed (or rolled back), assuming JTransaction.getCurrent() returns the JTransaction returned here at that time.

        Parameters:
        allowNewSchema - whether creating a new schema version is allowed
        validationMode - the ValidationMode to use for the new transaction
        kvoptions - optional KVDatabase-specific transaction options; may be null
        Returns:
        the newly created transaction
        Throws:
        InvalidSchemaException - if the schema does not match what's recorded in the database for the schema version provided to the constructor
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is false
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is true, but the schema is incompatible with one or more previous schemas alread recorded in the database (i.e., the same storage ID is used incompatibly between schema versions)
        InconsistentDatabaseException - if inconsistent or invalid meta-data is detected in the database
        IllegalArgumentException - if validationMode is null
      • createTransaction

        public JTransaction createTransaction​(KVTransaction kvt,
                                              boolean allowNewSchema,
                                              ValidationMode validationMode)
        Create a new transaction using an already-opened KVTransaction.

        This does not invoke JTransaction.setCurrent(): the caller is responsible for doing that if necessary. However, this method does arrange for JTransaction.setCurrent(null) to be invoked as soon as the returned transaction is committed (or rolled back), assuming JTransaction.getCurrent() returns the JTransaction returned here at that time.

        Parameters:
        kvt - already opened key/value store transaction
        allowNewSchema - whether creating a new schema version is allowed
        validationMode - the ValidationMode to use for the new transaction
        Returns:
        the newly created transaction
        Throws:
        InvalidSchemaException - if the schema does not match what's recorded in the database for the schema version provided to the constructor
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is false
        InvalidSchemaException - if the schema version provided to the constructor is not recorded in the database and allowNewSchema is true, but the schema is incompatible with one or more previous schemas alread recorded in the database (i.e., the same storage ID is used incompatibly between schema versions)
        InconsistentDatabaseException - if inconsistent or invalid meta-data is detected in the database
        IllegalArgumentException - if kvt or validationMode is null
      • getSchemaModel

        public SchemaModel getSchemaModel()
        Get the SchemaModel associated with this instance, derived from the annotations on the scanned classes.
        Returns:
        the associated schema model
      • getJClasses

        public SortedMap<Integer,​JClass<?>> getJClasses()
        Get all JClass's associated with this instance, indexed by storage ID.
        Returns:
        read-only mapping from storage ID to JClass
      • getJClassesByType

        public Map<Class<?>,​JClass<?>> getJClassesByType()
        Get all JClass's associated with this instance, indexed by Java model type.
        Returns:
        read-only mapping from Java model type to JClass
      • getJClass

        public <T> JClass<T> getJClass​(Class<T> type)
        Get the JClass modeled by the given type.
        Type Parameters:
        T - Java model type
        Parameters:
        type - an annotated Java object model type
        Returns:
        associated JClass
        Throws:
        IllegalArgumentException - if type is not equal to a known Java object model type
      • findJClass

        public <T> JClass<? super T> findJClass​(Class<T> type)
        Find the most specific JClass for which the give type is a sub-type of the corresponding Java model type.
        Type Parameters:
        T - Java model type or subtype thereof
        Parameters:
        type - (sub)type of some Java object model type
        Returns:
        narrowest JClass whose Java object model type is a supertype of type, or null if none found
      • getJClass

        public JClass<?> getJClass​(int storageId)
        Get the JClass associated with the given storage ID.
        Parameters:
        storageId - object type storage ID
        Returns:
        JClass instance
        Throws:
        UnknownTypeException - if storageId does not represent an object type
      • getJClasses

        public <T> List<JClass<? extends T>> getJClasses​(Class<T> type)
        Get all JClasses which sub-type the given type.
        Type Parameters:
        T - Java model type
        Parameters:
        type - type restriction, or null for no restrction
        Returns:
        list of JClasses whose type is type or a sub-type, ordered by storage ID
      • parseReferencePath

        public ReferencePath parseReferencePath​(Class<?> startType,
                                                String path,
                                                boolean expectTargetField)
        Parse a ReferencePath.
        Parameters:
        startType - starting Java type for the path
        path - dot-separated path of zero or more reference fields, followed by an optional target field
        expectTargetField - true if path contains a target field, false otherwise
        Returns:
        parsed reference path
        Throws:
        IllegalArgumentException - if path is invalid
        IllegalArgumentException - if startType or path is null
        See Also:
        ReferencePath
      • setValidatorFactory

        public void setValidatorFactory​(javax.validation.ValidatorFactory validatorFactory)
        Configure a custom ValidatorFactory used to create Validators for validation within transactions.
        Parameters:
        validatorFactory - factory for validators
        Throws:
        IllegalArgumentException - if validatorFactory is null
      • getReferencedObjects

        public Iterable<JObject> getReferencedObjects​(JObject jobj)
        Utility method to get all of the objects directly referenced by a given object via any field.

        Note: the returned Iterable may contain duplicates; these can be eliminated using an ObjIdSet if necessary.

        Parameters:
        jobj - starting object
        Returns:
        all objects directly referenced by jobj
        Throws:
        IllegalArgumentException - if jobj is null