001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: KeyField.java,v 1.5.2.4 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.Environment;
019:
020: /**
021: * Indicates the sorting position of a key field in a composite key class when
022: * the {@code Comparable} interface is not implemented. The {@code KeyField}
023: * integer value specifies the sort order of this field within the set of
024: * fields in the composite key.
025: *
026: * <p>If the field type of a {@link PrimaryKey} or {@link SecondaryKey} is a
027: * composite key class containing more than one key field, then a {@code
028: * KeyField} annotation must be present on each non-transient instance field of
029: * the composite key class. The {@code KeyField} value must be a number
030: * between one and the number of non-transient instance fields declared in the
031: * composite key class.</p>
032: *
033: * <p>Note that a composite key class is a flat container for one or more
034: * simple type fields. All non-transient instance fields in the composite key
035: * class are key fields, and the composite key class may not have superclasses
036: * containing non-transient instance fields.</p>
037: *
038: * <p>For example:</p>
039: * <pre class="code">
040: * {@literal @Entity}
041: * class Animal {
042: * {@literal @PrimaryKey}
043: * Classification classification;
044: * ...
045: * }
046: *
047: * {@literal @Persistent}
048: * class Classification {
049: * {@literal @KeyField(1) String kingdom;}
050: * {@literal @KeyField(2) String phylum;}
051: * {@literal @KeyField(3) String clazz;}
052: * {@literal @KeyField(4) String order;}
053: * {@literal @KeyField(5) String family;}
054: * {@literal @KeyField(6) String genus;}
055: * {@literal @KeyField(7) String species;}
056: * {@literal @KeyField(8) String subspecies;}
057: * ...
058: * }</pre>
059: *
060: * <p>This causes entities to be sorted first by {@code kingdom}, then by
061: * {@code phylum} within {@code kingdom}, and so on.</p>
062: *
063: * <p>The fields in a composite key class may not be null.</p>
064: *
065: * <p><a name="comparable"><strong>Custom Sort Order</strong></a></p>
066: *
067: * <p>To override the default sort order, a composite key class may implement
068: * the {@link Comparable} interface. This allows overriding the sort order and
069: * is therefore useful even when there is only one key field in the composite
070: * key class. For example, the following class sorts Strings using a Canadian
071: * collator:</p>
072: *
073: * <pre class="code">
074: * import java.text.Collator;
075: * import java.util.Locale;
076: *
077: * {@literal @Entity}
078: * class Animal {
079: * ...
080: * {@literal @SecondaryKey(relate=ONE_TO_ONE)}
081: * CollatedString canadianName;
082: * ...
083: * }
084: *
085: * {@literal @Persistent}
086: * {@literal class CollatedString implements Comparable<CollatedString>} {
087: *
088: * static Collator collator = Collator.getInstance(Locale.CANADA);
089: *
090: * {@literal @KeyField(1)}
091: * String value;
092: *
093: * CollatedString(String value) { this.value = value; }
094: *
095: * private CollatedString() {}
096: *
097: * public int compareTo(CollatedString o) {
098: * return collator.compare(value, o.value);
099: * }
100: * }</pre>
101: *
102: * <p>Several important rules should be considered when implementing a custom
103: * comparison method. Failure to follow these rules may result in the primary
104: * or secondary index becoming unusable; in other words, the store will not be
105: * able to function.</p>
106: * <ol>
107: * <li>The comparison method must always return the same result, given the same
108: * inputs. The behavior of the comparison method must not change over
109: * time.</li>
110: * <br>
111: * <li>A corollary to the first rule is that the behavior of the comparison
112: * method must not be dependent on state which may change over time. For
113: * example, if the above collation method used the default Java locale, and the
114: * default locale is changed, then the sort order will change.</li>
115: * <br>
116: * <li>The comparison method must not assume that it is called after the store
117: * has been opened. With Berkeley DB Java Edition, the comparison method is
118: * called during database recovery, which occurs in the {@link Environment}
119: * constructor.</li>
120: * <br>
121: * <li>The comparison method must not assume that it will only be called with
122: * keys that are currently present in the database. The comparison method will
123: * occasionally be called with deleted keys or with keys for records that were
124: * not part of a committed transaction.</li>
125: * </ol>
126: *
127: * @author Mark Hayes
128: */
129: @Documented
130: @Retention(RUNTIME)
131: @Target(FIELD)
132: public @interface KeyField {
133:
134: int value();
135: }
|