001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: SecondaryKey.java,v 1.9.2.2 2008/01/07 15:14:20 cwl Exp $
007: */
008:
009: package com.sleepycat.persist.model;
010:
011: import static java.lang.annotation.ElementType.FIELD;
012: import static java.lang.annotation.RetentionPolicy.RUNTIME;
013:
014: import java.lang.annotation.Documented;
015: import java.lang.annotation.Retention;
016: import java.lang.annotation.Target;
017:
018: import com.sleepycat.je.DatabaseException;
019: import com.sleepycat.persist.PrimaryIndex;
020: import com.sleepycat.persist.SecondaryIndex; // for javadoc
021: import com.sleepycat.persist.StoreConfig;
022:
023: /**
024: * Indicates a secondary key field of an entity class. The value of the
025: * secondary key field is a unique or non-unique identifier for the entity and
026: * is accessed via a {@link SecondaryIndex}.
027: *
028: * <p>{@code SecondaryKey} may appear on any number of fields in an entity
029: * class, subclasses and superclasses. For a secondary key field in the entity
030: * class or one of its superclasses, all entity instances will be indexed by
031: * that field (if it is non-null). For a secondary key field in an entity
032: * subclass, only instances of that subclass will be indexed by that field (if
033: * it is non-null).</p>
034: *
035: * <p>If a secondary key field is null, the entity will not be indexed by that
036: * key. In other words, the entity cannot be queried by that secondary key nor
037: * can the entity be found by iterating through the secondary index.</p>
038: *
039: * <p>For a given entity class and its superclasses and subclasses, no two
040: * secondary keys may have the same name. By default, the field name
041: * identifies the secondary key and the secondary index for a given entity
042: * class. {@link #name} may be specified to override this default.</p>
043: *
044: * <p>Using {@link #relate}, instances of the entity class are related to
045: * secondary keys in a many-to-one, one-to-many, many-to-many, or one-to-one
046: * relationship. This required property specifies the <em>cardinality</em> of
047: * each side of the relationship.</p>
048: *
049: * <p>A secondary key may optionally be used to form a relationship with
050: * instances of another entity class using {@link #relatedEntity} and {@link
051: * #onRelatedEntityDelete}. This establishes <em>foreign key constraints</em>
052: * for the secondary key.</p>
053: *
054: * <p>The secondary key field type must be an array or collection type when a
055: * <em>x-to-many</em> relationship is used or a singular type when an
056: * <em>x-to-one</em> relationship is used; see {@link #relate}.</p>
057: *
058: * <p>The field type (or element type, when an array or collection type is
059: * used) of a secondary key field must follow the same rules as for a {@link
060: * <a href="PrimaryKey.html#keyTypes">primary key type</a>}. The {@link <a
061: * href="PrimaryKey.html#sortOrder">key sort order</a>} is also the same.</p>
062: *
063: * @author Mark Hayes
064: */
065: @Documented
066: @Retention(RUNTIME)
067: @Target(FIELD)
068: public @interface SecondaryKey {
069:
070: /**
071: * Defines the relationship between instances of the entity class and the
072: * secondary keys.
073: *
074: * <p>The table below summarizes how to create all four variations of
075: * relationships.</p>
076: * <div>
077: * <table border="yes">
078: * <tr><th>Relationship</th>
079: * <th>Field type</th>
080: * <th>Key type</th>
081: * <th>Example</th>
082: * </tr>
083: * <tr><td>{@link Relationship#ONE_TO_ONE}</td>
084: * <td>Singular</td>
085: * <td>Unique</td>
086: * <td>A person record with a unique social security number
087: * key.</td>
088: * </tr>
089: * <tr><td>{@link Relationship#MANY_TO_ONE}</td>
090: * <td>Singular</td>
091: * <td>Duplicates</td>
092: * <td>A person record with a non-unique employer key.</td>
093: * </tr>
094: * <tr><td>{@link Relationship#ONE_TO_MANY}</td>
095: * <td>Array/Collection</td>
096: * <td>Unique</td>
097: * <td>A person record with multiple unique email address keys.</td>
098: * </tr>
099: * <tr><td>{@link Relationship#MANY_TO_MANY}</td>
100: * <td>Array/Collection</td>
101: * <td>Duplicates</td>
102: * <td>A person record with multiple non-unique organization
103: * keys.</td>
104: * </tr>
105: * </table>
106: * </div>
107: *
108: * <p>For a <em>many-to-x</em> relationship, the secondary index will
109: * have non-unique keys; in other words, duplicates will be allowed.
110: * Conversely, for <em>one-to-x</em> relationship, the secondary index
111: * will have unique keys.</p>
112: *
113: * <p>For a <em>x-to-one</em> relationship, the secondary key field is
114: * singular; in other words, it may not be an array or collection type.
115: * Conversely, for a <em>x-to-many</em> relationship, the secondary key
116: * field must be an array or collection type. A collection type is any
117: * implementation of {@link java.util.Collection}.</p>
118: */
119: Relationship relate();
120:
121: /**
122: * Specifies the entity to which this entity is related, for establishing
123: * foreign key constraints. Values of this secondary key will be
124: * constrained to the set of primary key values for the given entity class.
125: *
126: * <p>The given class must be an entity class. This class is called the
127: * <em>related entity</em> or <em>foreign entity</em>.</p>
128: *
129: * <p>When a related entity class is specified, a check (foreign key
130: * constraint) is made every time a new secondary key value is stored for
131: * this entity, and every time a related entity is deleted.</p>
132: *
133: * <p>Whenever a new secondary key value is stored for this entity, it is
134: * checked to ensure it exists as a primary key value of the related
135: * entity. If it does not, a {@link DatabaseException} will be thrown
136: * by the {@link PrimaryIndex} {@code put} method.</p>
137: *
138: * <p>Whenever a related entity is deleted and its primary key value exists
139: * as a secondary key value for this entity, the action is taken that is
140: * specified using the {@link #onRelatedEntityDelete} property.</p>
141: *
142: * <p>Together, these two checks guarantee that a secondary key value for
143: * this entity will always exist as a primary key value for the related
144: * entity. Note, however, that a transactional store must be configured
145: * to guarantee this to be true in the face of a crash; see {@link
146: * StoreConfig#setTransactional}.</p>
147: */
148: Class relatedEntity() default void.class;
149:
150: /**
151: * Specifies the action to take when a related entity is deleted having a
152: * primary key value that exists as a secondary key value for this entity.
153: *
154: * <p><em>Note:</em> This property only applies when {@link #relatedEntity}
155: * is specified to define the related entity.</p>
156: *
157: * <p>The default action, {@link DeleteAction#ABORT ABORT}, means that a
158: * {@link DatabaseException} is thrown in order to abort the current
159: * transaction.</p>
160: *
161: * <p>If {@link DeleteAction#CASCADE CASCADE} is specified, then this
162: * entity will be deleted also. This in turn could trigger further
163: * deletions, causing a cascading effect.</p>
164: *
165: * <p>If {@link DeleteAction#NULLIFY NULLIFY} is specified, then the
166: * secondary key in this entity is set to null and this entity is updated.
167: * If the key field type is singular, the field value is set to null;
168: * therefore, to specify {@code NULLIFY} for a singular key field type, a
169: * primitive wrapper type must be used instead of a primitive type. If the
170: * key field type is an array or collection type, the key is deleted from
171: * the array (the array is resized) or from the collection (using {@link
172: * java.util.Collection#remove Collection.remove}).</p>
173: */
174: DeleteAction onRelatedEntityDelete() default DeleteAction.ABORT;
175:
176: /**
177: * Specifies the name of the key in order to use a name that is different
178: * than the field name.
179: *
180: * <p>This is convenient when prefixes or suffices are used on field names.
181: * For example:</p>
182: * <pre class="code">
183: * class Person {
184: * {@literal @SecondaryKey(relate=MANY_TO_ONE, relatedEntity=Person.class, name="parentSsn")}
185: * String m_parentSsn;
186: * }</pre>
187: *
188: * <p>It can also be used to uniquely name a key when multiple secondary
189: * keys for a single entity class have the same field name. For example,
190: * an entity class and its subclass may both have a field named 'date',
191: * and both fields are used as secondary keys. The {@code name} property
192: * can be specified for one or both fields to give each key a unique
193: * name.</p>
194: */
195: String name() default "";
196: }
|