blob: e66ef5f8f169f150d4238a40cc918ce55f8aa17b [file] [log] [blame]
/*-
* 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.je.Environment;
/**
* Indicates the sorting position of a key field in a composite key class when
* the {@code Comparable} interface is not implemented. The {@code KeyField}
* integer value specifies the sort order of this field within the set of
* fields in the composite key.
*
* <p>If the field type of a {@link PrimaryKey} or {@link SecondaryKey} is a
* composite key class containing more than one key field, then a {@code
* KeyField} annotation must be present on each non-transient instance field of
* the composite key class. The {@code KeyField} value must be a number
* between one and the number of non-transient instance fields declared in the
* composite key class.</p>
*
* <p>Note that a composite key class is a flat container for one or more
* simple type fields. All non-transient instance fields in the composite key
* class are key fields, and its superclass must be {@code Object}.</p>
*
* <p>For example:</p>
* <pre class="code">
* {@literal @Entity}
* class Animal {
* {@literal @PrimaryKey}
* Classification classification;
* ...
* }
*
* {@literal @Persistent}
* class Classification {
* {@literal @KeyField(1) String kingdom;}
* {@literal @KeyField(2) String phylum;}
* {@literal @KeyField(3) String clazz;}
* {@literal @KeyField(4) String order;}
* {@literal @KeyField(5) String family;}
* {@literal @KeyField(6) String genus;}
* {@literal @KeyField(7) String species;}
* {@literal @KeyField(8) String subspecies;}
* ...
* }</pre>
*
* <p>This causes entities to be sorted first by {@code kingdom}, then by
* {@code phylum} within {@code kingdom}, and so on.</p>
*
* <p>The fields in a composite key class may not be null.</p>
*
* <p><a name="comparable"><strong>Custom Sort Order</strong></a></p>
*
* <p>To override the default sort order, a composite key class may implement
* the {@link Comparable} interface. This allows overriding the sort order and
* is therefore useful even when there is only one key field in the composite
* key class. For example, the following class sorts Strings using a Canadian
* collator:</p>
*
* <pre class="code">
* import java.text.Collator;
* import java.util.Locale;
*
* {@literal @Entity}
* class Animal {
* ...
* {@literal @SecondaryKey(relate=ONE_TO_ONE)}
* CollatedString canadianName;
* ...
* }
*
* {@literal @Persistent}
* {@literal class CollatedString implements Comparable<CollatedString>} {
*
* static Collator collator = Collator.getInstance(Locale.CANADA);
*
* {@literal @KeyField(1)}
* String value;
*
* CollatedString(String value) { this.value = value; }
*
* private CollatedString() {}
*
* public int compareTo(CollatedString o) {
* return collator.compare(value, o.value);
* }
* }</pre>
*
* <p>Several important rules should be considered when implementing a custom
* comparison method. Failure to follow these rules may result in the primary
* or secondary index becoming unusable; in other words, the store will not be
* able to function.</p>
* <ol>
* <li>The comparison method must always return the same result, given the same
* inputs. The behavior of the comparison method must not change over
* time.</li>
* <li>A corollary to the first rule is that the behavior of the comparison
* method must not be dependent on state which may change over time. For
* example, if the above collation method used the default Java locale, and the
* default locale is changed, then the sort order will change.</li>
* <li>The comparison method must not assume that it is called after the store
* has been opened. With Berkeley DB Java Edition, the comparison method is
* called during database recovery, which occurs in the {@link Environment}
* constructor.</li>
* <li>The comparison method must not assume that it will only be called with
* keys that are currently present in the database. The comparison method will
* occasionally be called with deleted keys or with keys for records that were
* not part of a committed transaction.</li>
* </ol>
*
* @author Mark Hayes
*/
@Documented @Retention(RUNTIME) @Target(FIELD)
public @interface KeyField {
int value();
}