com.sleepycat.persist.model.SecondaryKey Maven / Gradle / Ivy
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.persist.model;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import com.sleepycat.persist.PrimaryIndex;
import com.sleepycat.persist.StoreConfig;
/**
* Indicates a secondary key field of an entity class. The value of the
* secondary key field is a unique or non-unique identifier for the entity and
* is accessed via a {@link com.sleepycat.persist.SecondaryIndex}.
*
* {@code SecondaryKey} may appear on any number of fields in an entity
* class, subclasses and superclasses. For a secondary key field in the entity
* class or one of its superclasses, all entity instances will be indexed by
* that field (if it is non-null). For a secondary key field in an entity
* subclass, only instances of that subclass will be indexed by that field (if
* it is non-null).
*
* If a secondary key field is null, the entity will not be indexed by that
* key. In other words, the entity cannot be queried by that secondary key nor
* can the entity be found by iterating through the secondary index.
*
* For a given entity class and its superclasses and subclasses, no two
* secondary keys may have the same name. By default, the field name
* identifies the secondary key and the secondary index for a given entity
* class. {@link #name} may be specified to override this default.
*
* Using {@link #relate}, instances of the entity class are related to
* secondary keys in a many-to-one, one-to-many, many-to-many, or one-to-one
* relationship. This required property specifies the cardinality of
* each side of the relationship.
*
* A secondary key may optionally be used to form a relationship with
* instances of another entity class using {@link #relatedEntity} and {@link
* #onRelatedEntityDelete}. This establishes foreign key constraints
* for the secondary key.
*
* The secondary key field type must be a Set, Collection or array type when
* a x-to-many relationship is used or a singular type when an
* x-to-one relationship is used; see {@link #relate}.
*
* The field type (or element type, when a Set, Collection or array type is
* used) of a secondary key field must follow the same rules as for a
* primary key type. The key sort order is also the same.
*
* For a secondary key field with a collection type, a type parameter must
* be used to specify the element type. For example {@code Collection}
* is allowed but {@code Collection} is not.
*
* @author Mark Hayes
*/
@Documented @Retention(RUNTIME) @Target(FIELD)
public @interface SecondaryKey {
/**
* Defines the relationship between instances of the entity class and the
* secondary keys.
*
* The table below summarizes how to create all four variations of
* relationships.
*
*
* Relationship
* Field type
* Key type
* Example
*
* {@link Relationship#ONE_TO_ONE}
* Singular
* Unique
* A person record with a unique social security number
* key.
*
* {@link Relationship#MANY_TO_ONE}
* Singular
* Duplicates
* A person record with a non-unique employer key.
*
* {@link Relationship#ONE_TO_MANY}
* Set/Collection/array
* Unique
* A person record with multiple unique email address keys.
*
* {@link Relationship#MANY_TO_MANY}
* Set/Collection/array
* Duplicates
* A person record with multiple non-unique organization
* keys.
*
*
*
*
* For a many-to-x relationship, the secondary index will
* have non-unique keys; in other words, duplicates will be allowed.
* Conversely, for one-to-x relationship, the secondary index
* will have unique keys.
*
* For a x-to-one relationship, the secondary key field is
* singular; in other words, it may not be a Set, Collection or array type.
* Conversely, for a x-to-many relationship, the secondary key
* field must be a Set, Collection or array type. A collection type is any
* implementation of {@link java.util.Collection}.
*
* For a x-to-many relationship, the field type should normally
* be {@link java.util.Set} (or a subtype of this interface). This
* accurately expresses the fact that an Entity may not have two identical
* secondary keys. For flexibility, a {@link java.util.Collection} (or a
* subtype of this interface) or an array type may also be used. In that
* case, any duplicate key values in the Collection or array are
* ignored.
*
* @return the Relationship.
*/
Relationship relate();
/**
* Specifies the entity to which this entity is related, for establishing
* foreign key constraints. Values of this secondary key will be
* constrained to the set of primary key values for the given entity class.
*
* The given class must be an entity class. This class is called the
* related entity or foreign entity.
*
* When a related entity class is specified, a check (foreign key
* constraint) is made every time a new secondary key value is stored for
* this entity, and every time a related entity is deleted.
*
* Whenever a new secondary key value is stored for this entity, it is
* checked to ensure it exists as a primary key value of the related
* entity. If it does not, an exception is thrown by the {@link
* PrimaryIndex} {@code put} method.
*
* On BDB JE, a {@link com.sleepycat.je.ForeignConstraintException} will be
* thrown.
*
*
*
* Whenever a related entity is deleted and its primary key value exists
* as a secondary key value for this entity, the action is taken that is
* specified using the {@link #onRelatedEntityDelete} property.
*
* Together, these two checks guarantee that a secondary key value for
* this entity will always exist as a primary key value for the related
* entity. Note, however, that a transactional store must be configured
* to guarantee this to be true in the face of a crash; see {@link
* StoreConfig#setTransactional}.
*
* @return the related entity class, or void.class if none is specified.
*/
Class relatedEntity() default void.class;
/**
* Specifies the action to take when a related entity is deleted having a
* primary key value that exists as a secondary key value for this entity.
*
* Note: This property only applies when {@link #relatedEntity}
* is specified to define the related entity.
*
* The default action, {@link DeleteAction#ABORT ABORT}, means that an
* exception is thrown in order to abort the current transaction.
*
* On BDB JE, a {@link com.sleepycat.je.DeleteConstraintException} is
* thrown.
*
*
*
* If {@link DeleteAction#CASCADE CASCADE} is specified, then this
* entity will be deleted also. This in turn could trigger further
* deletions, causing a cascading effect.
*
* If {@link DeleteAction#NULLIFY NULLIFY} is specified, then the
* secondary key in this entity is set to null and this entity is updated.
* If the key field type is singular, the field value is set to null;
* therefore, to specify {@code NULLIFY} for a singular key field type, a
* primitive wrapper type must be used instead of a primitive type. If the
* key field type is an array or collection type, the key is deleted from
* the array (the array is resized) or from the collection (using {@link
* java.util.Collection#remove Collection.remove}).
*
* @return the DeleteAction, or {@link DeleteAction#ABORT} if none is
* specified.
*/
DeleteAction onRelatedEntityDelete() default DeleteAction.ABORT;
/**
* Specifies the name of the key in order to use a name that is different
* than the field name.
*
* This is convenient when prefixes or suffices are used on field names.
* For example:
*
* class Person {
* {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class, name="parentSsn")}
* String m_parentSsn;
* }
*
* It can also be used to uniquely name a key when multiple secondary
* keys for a single entity class have the same field name. For example,
* an entity class and its subclass may both have a field named 'date',
* and both fields are used as secondary keys. The {@code name} property
* can be specified for one or both fields to give each key a unique
* name.
*
* @return the key name that overrides the field name, or empty string if
* none is specified.
*/
String name() default "";
}