Chapter 5. Metadata

5.1. XML MetaData
5.2. Class Annotations
5.2.1. Entity
5.2.2. IdClass
5.2.3. MappedSuperclass
5.2.4. Embeddable
5.2.5. EntityListeners
5.2.6. Example
5.3. Field and Property Annotations
5.3.1. Transient
5.3.2. Id
5.3.3. GeneratedValue
5.3.4. Version
5.3.5. Basic
5.3.5.1. FetchType
5.3.6. Embedded
5.3.7. ManyToOne
5.3.7.1. CascadeType
5.3.8. OneToMany
5.3.8.1. Bidirectional Relations
5.3.9. OneToOne
5.3.10. ManyToMany
5.3.11. OrderBy
5.3.12. MapKey
5.3.13. Persistent Field Defaults
5.4. Conclusion

EJB requires that you accompany each persistent class with persistence metadata. This metadata serves three primary purposes:

  1. To identify persistent classes.

  2. To override default EJB persistence behavior.

  3. To provide the EJB persistence implementation with information that it cannot glean from simply reflecting on the persistent class.

Persistence metadata is specified using either Java 5 annotations or XML mapping files enumerated in the persistence.xml file. All EJB metadata annotations are in the javax.persistence package. EJB also standardizes relational mapping metadata and named query metadata, which we discuss in Chapter 12, Mapping Metadata and Section 10.9, “Named Queries” respectively.

[Note]Note

Kodo defines many useful annotations beyond the standard set. See Section 6.3, “Additional EJB Metadata” and Section 6.4, “Metadata Extensions” in the Reference Guide for details. There are currently no XML equivalents for these extension annotations.

Through the course of this chapter, we will create the persistent object model above.

5.1. XML MetaData

While annotations are the most commonly used way to declare metadata for persistent classes, XML can be used instead of or in addition to annotations. This allows you to deploy the same class to different systems which may require different schemas or behaviors such as entity listeners.

These XML mapping files must be available at development and runtime. These files must be available via two locating strategies:

  • Be declared in persistence.xml. Each file must be listed in a mapping-file element whose content is either a path to the given file or a resource location available to the class' class loader.

  • In a resource named orm.xml placed in the META-INF directory of the classpath or the archive jar for the persistent class.

Every metadata annotation has a corresponding XML element. The XSD schema for orm.xml format is below:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Java Persistence orm.xml schema -->
<xsd:schema targetNamespace="http://java.sun.com/xml/ns/persistence/orm" 
xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" 
xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" 
attributeFormDefault="unqualified" version="1.0">
    <xsd:annotation>
        <xsd:documentation>
            @(#)orm_1_0.xsd 1.0  Jan 20 2006
        </xsd:documentation>
    </xsd:annotation>
    <xsd:annotation>
        <xsd:documentation>
        This is the XML Schema for the persistence object-relational 
        mapping file. 
        The file may be named "META-INF/orm.xml" in the persistence
        archive or it may be named some other name which would be
        used to locate the file as resource on the classpath.
        </xsd:documentation>
    </xsd:annotation>

    <!-- ************************************************ -->

    <xsd:element name="entity-mappings">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="package" type="xsd:string" 
                    minOccurs="0"/>
                <xsd:element name="catalog" type="xsd:string" 
                    minOccurs="0"/>
                <xsd:element name="schema" type="xsd:string" 
                    minOccurs="0"/>
                <xsd:element name="access" type="orm:access-type" 
                    minOccurs="0"/>
                <xsd:element name="flush-mode" type="orm:flush-mode-type" 
                    minOccurs="0"/>
                <xsd:element name="cascade" type="orm:cascade-type" 
                    minOccurs="0"/>
                <xsd:element name="entity-listeners" 
                    type="orm:default-entity-listeners" 
                    minOccurs="0"/>
                <xsd:element name="sequence-generator" type="orm:sequence-generator"
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="table-generator" type="orm:table-generator" 
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="named-query" type="orm:named-query" 
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="named-native-query" type="orm:named-native-query"
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="sql-result-set-mapping" 
                    type="orm:sql-result-set-mapping" 
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="mapped-superclass" type="orm:mapped-superclass" 
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="entity" type="orm:entity" 
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="embeddable" type="orm:embeddable" 
                    minOccurs="0" maxOccurs="unbounded"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <!-- ************************************************ -->

    <xsd:complexType name="entity">
        <xsd:annotation>
            <xsd:documentation>
                @Target(TYPE) @Retention(RUNTIME)
                public @interface Entity {
                    String name() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="table" type="orm:table" minOccurs="0"/>
            <xsd:element name="secondary-table" type="orm:secondary-table" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="primary-key-join-column" 
                type="orm:primary-key-join-column" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="id-class" type="orm:id-class" minOccurs="0"/>
            <xsd:element name="inheritance" type="orm:inheritance" minOccurs="0"/>
            <xsd:element name="discriminator-value" type="orm:discriminator-value" 
                minOccurs="0"/>
            <xsd:element name="discriminator-column" 
                type="orm:discriminator-column" 
                minOccurs="0"/>
            <xsd:element name="sequence-generator" type="orm:sequence-generator" 
                minOccurs="0"/>
            <xsd:element name="table-generator" type="orm:table-generator" 
                minOccurs="0"/>
            <xsd:element name="named-query" type="orm:named-query" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="named-native-query" type="orm:named-native-query" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="sql-result-set-mapping" type="orm:sql-result-set-mapping" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="exclude-default-listeners" type="xsd:boolean" 
                minOccurs="0"/>
            <xsd:element name="exclude-superclass-listeners" type="xsd:boolean" 
                minOccurs="0"/>
            <xsd:element name="entity-listeners" type="orm:entity-listeners" 
                minOccurs="0"/>
            <xsd:element name="pre-persist" type="orm:pre-persist" minOccurs="0"/>
            <xsd:element name="post-persist" type="orm:post-persist" 
                minOccurs="0"/>
            <xsd:element name="pre-remove" type="orm:pre-remove" minOccurs="0"/>
            <xsd:element name="post-remove" type="orm:post-remove" minOccurs="0"/>
            <xsd:element name="pre-update" type="orm:pre-update" minOccurs="0"/>
            <xsd:element name="post-update" type="orm:post-update" minOccurs="0"/>
            <xsd:element name="post-load" type="orm:post-load" minOccurs="0"/>
            <xsd:element name="attribute-override" type="orm:attribute-override" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="association-override" type="orm:association-override" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="attributes" type="orm:attributes" minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="class" type="xsd:string" use="required"/>
        <xsd:attribute name="access" type="orm:access-type"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="attributes">
        <xsd:sequence>
            <xsd:choice minOccurs="0">
                <xsd:element name="id" type="orm:id" 
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="embedded-id" type="orm:embedded-id" 
                    minOccurs="0" maxOccurs="unbounded"/>
            </xsd:choice>
            <xsd:element name="basic" type="orm:basic"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="version" type="orm:version"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="many-to-one" type="orm:many-to-one"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="one-to-many" type="orm:one-to-many"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="one-to-one" type="orm:one-to-one"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="many-to-many" type="orm:many-to-many"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="embedded" type="orm:embedded"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="transient" type="orm:embedded"
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:simpleType name="access-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum AccessType { PROPERTY, FIELD };
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="PROPERTY"/>
            <xsd:enumeration value="FIELD"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:complexType name="default-entity-listeners">
        <xsd:sequence>
            <xsd:element name="entity-listener" type="orm:entity-listener"
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="entity-listeners">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface EntityListeners {
                    Class[] value();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="entity-listener" type="orm:entity-listener"
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="entity-listener">
        <xsd:sequence>
            <xsd:element name="pre-persist" type="orm:pre-persist" minOccurs="0"/>
            <xsd:element name="post-persist" type="orm:post-persist" minOccurs="0"/>
            <xsd:element name="pre-remove" type="orm:pre-remove" minOccurs="0"/>
            <xsd:element name="post-remove" type="orm:post-remove" minOccurs="0"/>
            <xsd:element name="pre-update" type="orm:pre-update" minOccurs="0"/>
            <xsd:element name="post-update" type="orm:post-update" minOccurs="0"/>
            <xsd:element name="post-load" type="orm:post-load" minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="class" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="pre-persist">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PrePersist {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="post-persist">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PostPersist {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="pre-remove">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PreRemove {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="post-remove">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PostRemove {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="pre-update">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PreUpdate {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="post-update">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PostUpdate {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="post-load">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD}) @Retention(RUNTIME)
                public @interface PostLoad {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="method-name" type="xsd:string" use="required"/>
    </xsd:complexType>
    
    <!-- ************************************************ -->

    <xsd:simpleType name="flush-mode-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum FlushModeType {
                    COMMIT,
                    AUTO
                 }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="COMMIT"/>
            <xsd:enumeration value="AUTO"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:complexType name="query-hint">
        <xsd:annotation>
            <xsd:documentation>
                @Target({}) @Retention(RUNTIME)
                public @interface QueryHint {
                    String name();
                    String value();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="value" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="named-query">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface NamedQuery {
                    String name();
                    String query();
                    QueryHint[] hints();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="query" type="xsd:string" maxOccurs="unbounded"/>
            <xsd:element name="hint" type="orm:query-hint" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="named-native-query">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface NamedNativeQuery {
                    String name();
                    String query();
                    Class resultClass();
                    String resultSetMapping() default ""; // name of SQLResultSetMapping
                    QueryHint[] hints();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="query" type="xsd:string" maxOccurs="unbounded"/>
            <xsd:element name="hint" type="orm:query-hint" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="result-class" type="xsd:string"/>
        <xsd:attribute name="result-set-mapping" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="sql-result-set-mapping">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD}) @Retention(RUNTIME)
                public @interface SqlResultSetMapping {
                    String name();
                    EntityResult[] entities() default {};
                    ColumnResult[] columns() default {};
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="entity-result" type="orm:entity-result" minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="column-result" type="orm:column-result" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="entity-result">
        <xsd:annotation>
            <xsd:documentation>
                @Target({}) @Retention(RUNTIME)
                public @interface EntityResult {
                    Class entityClass();
                    FieldResult[] fields() default {};
                    String discriminatorColumn() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="field-result" type="orm:field-result" minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="entity-class" type="xsd:string" use="required"/>
        <xsd:attribute name="discriminator-column" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="field-result">
        <xsd:annotation>
            <xsd:documentation>
                @Target({}) @Retention(RUNTIME)
                public @interface FieldResult {
                    String name();
                    String column();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="column" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="column-result">
        <xsd:annotation>
            <xsd:documentation>
                @Target({}) @Retention(RUNTIME)
                public @interface ColumnResult {
                    String name();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="table">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface Table {
                    String name() default "";
                    String catalog() default "";
                    String schema() default "";
                    UniqueConstraint[] uniqueConstraints() default {};
                }            
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="unique-constraint" type="orm:unique-constraint" 
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="catalog" type="xsd:string"/>
        <xsd:attribute name="schema" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="secondary-table">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface SecondaryTable {
                    String name();
                    String catalog() default "";
                    String schema() default "";
                    PrimaryKeyJoinColumn[] pkJoin() default {};
                    UniqueConstraint[] uniqueConstraints() default {};
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="primary-key-join-column" 
                type="orm:primary-key-join-column" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="unique-constraint" type="orm:unique-constraint" 
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="catalog" type="xsd:string"/>
        <xsd:attribute name="schema" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="unique-constraint">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface UniqueConstraint {
                    String[] columnNames();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="column-name" type="xsd:string" 
                maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="column">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Column {
                    String name() default "";
                    boolean unique() default false;
                    boolean nullable() default true;
                    boolean insertable() default true;
                    boolean updatable() default true;
                    String columnDefinition() default "";
                    String secondaryTable() default "";
                    int length() default 255;
                    int precision() default 0; // decimal precision
                    int scale() default 0; // decimal scale
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="unique" type="xsd:boolean"/>
        <xsd:attribute name="nullable" type="xsd:boolean"/>
        <xsd:attribute name="insertable" type="xsd:boolean"/>
        <xsd:attribute name="updatable" type="xsd:boolean"/>
        <xsd:attribute name="column-definition" type="xsd:string"/>
        <xsd:attribute name="table" type="xsd:string"/>
        <xsd:attribute name="length" type="xsd:int"/>
        <xsd:attribute name="precision" type="xsd:int"/>
        <xsd:attribute name="scale" type="xsd:int"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="join-column">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
                public @interface JoinColumn {
                    String name() default "";
                    String referencedColumnName() default "";
                    boolean unique() default false;
                    boolean nullable() default true;
                    boolean insertable() default true;
                    boolean updatable() default true;
                    String columnDefinition() default "";
                    String secondaryTable() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="referenced-column-name" type="xsd:string"/>
        <xsd:attribute name="unique" type="xsd:boolean"/>
        <xsd:attribute name="nullable" type="xsd:boolean"/>
        <xsd:attribute name="insertable" type="xsd:boolean"/>
        <xsd:attribute name="updatable" type="xsd:boolean"/>
        <xsd:attribute name="column-definition" type="xsd:string"/>
        <xsd:attribute name="table" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:simpleType name="generation-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum GenerationType { TABLE, SEQUENCE, IDENTITY, AUTO };
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="TABLE"/>
            <xsd:enumeration value="SEQUENCE"/>
            <xsd:enumeration value="IDENTITY"/>
            <xsd:enumeration value="AUTO"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:complexType name="attribute-override">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
                public @interface AttributeOverride {
                    String name();
                    Column column();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="column" type="orm:column"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="association-override">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
                public @interface AssociationOverride {
                    String name();
                    JoinColumn[] joinColumns();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="join-column" type="orm:join-column" 
                maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="id-class">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface IdClass {
                    Class value();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="class" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="id">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Id {
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="column" type="orm:column"
                minOccurs="0"/>
            <xsd:element name="generated-value" type="orm:generated-value"
                minOccurs="0"/>
            <xsd:element name="temporal" type="orm:temporal"
                minOccurs="0"/>
            <xsd:element name="table-generator" type="orm:table-generator"
                minOccurs="0"/>
            <xsd:element name="sequence-generator" type="orm:sequence-generator"
                minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="embedded-id">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface EmbeddedId {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="attribute-override" type="orm:attribute-override"
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="transient">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Transient {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="version">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Version {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="column" type="orm:column" minOccurs="0"/>
            <xsd:element name="temporal" type="orm:temporal" minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="basic">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Basic {
                    FetchType fetch() default EAGER;
                    TemporalType temporalType() default NONE;
                    boolean optional() default true;
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="column" type="orm:column" minOccurs="0"/>
            <xsd:element name="lob" type="orm:lob" minOccurs="0"/>
            <xsd:element name="temporal" type="orm:temporal" minOccurs="0"/>
            <xsd:element name="enumerated" type="orm:enumerated" minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="fetch" type="orm:fetch-type"/>
        <xsd:attribute name="optional" type="xsd:boolean"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:simpleType name="fetch-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum FetchType { LAZY, EAGER };            
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="LAZY"/>
            <xsd:enumeration value="EAGER"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="lob">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Lob {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:string">
            <xsd:length value="0"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="temporal">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD,FIELD}) @Retention(RUNTIME)
                public @interface Temporal {
                    TemporalType value() default TIMESTAMP;
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="temporal-type"/>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="temporal-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum TemporalType {
                    DATE, //java.sql.Date
                    TIME, //java.sql.Time
                    TIMESTAMP, //java.sql.Timestamp
                    NONE
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="DATE"/>
            <xsd:enumeration value="TIME"/>
            <xsd:enumeration value="TIMESTAMP"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="enumerated">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD,FIELD}) @Retention(RUNTIME)
                public @interface Enumerated {
                    EnumType value() default ORDINAL;
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="enum-type"/>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="enum-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum EnumType {
                    ORDINAL,
                    STRING
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="ORDINAL"/>
            <xsd:enumeration value="STRING"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:complexType name="many-to-one">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface ManyToOne {
                    Class targetEntity();
                    CascadeType[] cascade() default {};
                    FetchType fetch() default EAGER;
                    boolean optional() default true;
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:choice>
                <xsd:element name="join-column" type="orm:join-column"
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="join-table" type="orm:join-table"
                    minOccurs="0"/>
            </xsd:choice>
            <xsd:element name="cascade" type="orm:cascade-type" minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="target-entity" type="xsd:string"/>
        <xsd:attribute name="fetch" type="orm:fetch-type"/>
        <xsd:attribute name="optional" type="xsd:boolean"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="cascade-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, REFRESH};
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="cascade-all" type="xsd:string"
                minOccurs="0"/>
            <xsd:element name="cascade-persist" type="xsd:string"
                minOccurs="0"/>
            <xsd:element name="cascade-merge" type="xsd:string"
                minOccurs="0"/>
            <xsd:element name="cascade-remove" type="xsd:string"
                minOccurs="0"/>
            <xsd:element name="cascade-refresh" type="xsd:string"
                minOccurs="0"/>
        </xsd:sequence>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="one-to-one">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface OneToOne {
                    Class targetEntity();
                    CascadeType[] cascade() default {};
                    FetchType fetch() default EAGER;
                    boolean optional() default true;
                    String mappedBy() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:choice>
                <xsd:element name="primary-key-join-column" 
                    type="orm:primary-key-join-column"
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="join-column" type="orm:join-column"
                    minOccurs="0" maxOccurs="unbounded"/>
                <xsd:element name="join-table" type="orm:join-table"
                    minOccurs="0"/>
            </xsd:choice>
            <xsd:element name="cascade" type="orm:cascade-type" 
                minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="target-entity" type="xsd:string"/>
        <xsd:attribute name="fetch" type="orm:fetch-type"/>
        <xsd:attribute name="optional" type="xsd:boolean"/>
        <xsd:attribute name="mapped-by" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="one-to-many">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface OneToMany {
                    Class targetEntity();
                    CascadeType[] cascade() default {};
                    FetchType fetch() default LAZY;
                    String mappedBy() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="order-by" type="orm:order-by"
                minOccurs="0"/>
            <xsd:element name="map-key" type="orm:map-key"
                minOccurs="0"/>
            <xsd:choice>
                <xsd:element name="join-table" type="orm:join-table"
                    minOccurs="0"/>
                <xsd:element name="join-column" type="orm:join-column"
                    minOccurs="0" maxOccurs="unbounded"/>
            </xsd:choice>
            <xsd:element name="cascade" type="orm:cascade-type" 
                minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="target-entity" type="xsd:string"/>
        <xsd:attribute name="fetch" type="orm:fetch-type"/>
        <xsd:attribute name="mapped-by" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="join-table">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD})
                public @interface JoinTable {
                    String name() default "";
                    String catalog() default "";
                    String schema() default "";
                    JoinColumn[] joinColumns() default {};
                    JoinColumn[] inverseJoinColumns() default {};
                    UniqueConstraint[] uniqueConstraints() default {};
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="join-column" type="orm:join-column" minOccurs="0" 
                maxOccurs="unbounded"/>
            <xsd:element name="inverse-join-column" type="orm:join-column" 
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="unique-constraint" type="orm:unique-constraint" 
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="catalog" type="xsd:string"/>
        <xsd:attribute name="schema" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="many-to-many">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface ManyToMany {
                    Class targetEntity();
                    CascadeType[] cascade() default {};
                    FetchType fetch() default LAZY;
                    String mappedBy() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="order-by" type="orm:order-by"
                minOccurs="0"/>
            <xsd:element name="map-key" type="orm:map-key"
                minOccurs="0"/>
            <xsd:element name="join-table" type="orm:join-table"
                minOccurs="0"/>
            <xsd:element name="cascade" type="orm:cascade-type" 
                minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="target-entity" type="xsd:string"/>
        <xsd:attribute name="fetch" type="orm:fetch-type"/>
        <xsd:attribute name="mapped-by" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="generated-value">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface GeneratedValue {
                    GenerationType strategy() default AUTO;
                    String generator() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="strategy" type="orm:generation-type"/>
        <xsd:attribute name="generator" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="map-key">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface MapKey {
                    String name() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:simpleType name="order-by">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface OrderBy {
                    String value() default "";
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:string"/>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:complexType name="inheritance">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface Inheritance {
                    InheritanceType strategy() default SINGLE_TABLE;
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="strategy" type="orm:inheritance-type"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:simpleType name="inheritance-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum InheritanceType
                    { SINGLE_TABLE, JOINED, TABLE_PER_CLASS};
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="SINGLE_TABLE"/>
            <xsd:enumeration value="JOINED"/>
            <xsd:enumeration value="TABLE_PER_CLASS"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="discriminator-value">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE} @Retention(RUNTIME)
                public @interface DiscriminatorValue {
                    String value();
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:string"/>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:simpleType name="discriminator-type">
        <xsd:annotation>
            <xsd:documentation>
                public enum DiscriminatorType { STRING, CHAR, INTEGER };
            </xsd:documentation>
        </xsd:annotation>
        <xsd:restriction base="xsd:token">
            <xsd:enumeration value="STRING"/>
            <xsd:enumeration value="CHAR"/>
            <xsd:enumeration value="INTEGER"/>
        </xsd:restriction>
    </xsd:simpleType>

    <!-- ************************************************ -->

    <xsd:complexType name="primary-key-join-column">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
                public @interface PrimaryKeyJoinColumn {
                    String name() default "";
                    String referencedColumnName() default "";
                    String columnDefinition() default "";
                }            
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="referenced-column-name" type="xsd:string"/>
        <xsd:attribute name="column-definition" type="xsd:string"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="discriminator-column">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface DiscriminatorColumn {
                    String name() default "";
                    DiscriminatorType discriminatorType() default STRING;
                    String columnDefinition() default "";
                    int length() default 10;
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string"/>
        <xsd:attribute name="discriminator-type" type="orm:discriminator-type"/>
        <xsd:attribute name="column-definition" type="xsd:string"/>
        <xsd:attribute name="length" type="xsd:int"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="embeddable">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE}) @Retention(RUNTIME)
                public @interface Embeddable {
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="table" type="orm:table" minOccurs="0"/>
            <xsd:element name="attributes" type="orm:embeddable-attributes" 
                minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="class" type="xsd:string"/>
        <xsd:attribute name="access" type="orm:access-type"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="embeddable-attributes">
        <xsd:sequence>
            <xsd:element name="basic" type="orm:basic"
                minOccurs="0" maxOccurs="unbounded"/>
            <xsd:element name="transient" type="orm:transient"
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="embedded">
        <xsd:annotation>
            <xsd:documentation>
                @Target({METHOD, FIELD}) @Retention(RUNTIME)
                public @interface Embedded {}
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="attribute-override" type="orm:attribute-override"
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="mapped-superclass">
        <xsd:annotation>
            <xsd:documentation>
                @Target(TYPE) @Retention(RUNTIME)
                public @interface MappedSuperclass {
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="id-class" type="orm:id-class" minOccurs="0"/>
            <xsd:element name="exclude-default-listeners" type="xsd:boolean" 
                minOccurs="0"/>
            <xsd:element name="exclude-superclass-listeners" type="xsd:boolean"
                minOccurs="0"/>
            <xsd:element name="entity-listeners" type="orm:entity-listeners" 
                minOccurs="0"/>
            <xsd:element name="pre-persist" type="orm:pre-persist" minOccurs="0"/>
            <xsd:element name="post-persist" type="orm:post-persist" minOccurs="0"/>
            <xsd:element name="pre-remove" type="orm:pre-remove" minOccurs="0"/>
            <xsd:element name="post-remove" type="orm:post-remove" minOccurs="0"/>
            <xsd:element name="pre-update" type="orm:pre-update" minOccurs="0"/>
            <xsd:element name="post-update" type="orm:post-update" minOccurs="0"/>
            <xsd:element name="post-load" type="orm:post-load" minOccurs="0"/>
            <xsd:element name="attributes" type="orm:attributes" minOccurs="0"/>
        </xsd:sequence>
        <xsd:attribute name="class" type="xsd:string"/>
        <xsd:attribute name="access" type="orm:access-type"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="sequence-generator">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
                public @interface SequenceGenerator {
                    String name();
                    String sequenceName() default "";
                    int initialValue() default 0;
                    int allocationSize() default 50;
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="sequence-name" type="xsd:string"/>
        <xsd:attribute name="initial-value" type="xsd:int"/>
        <xsd:attribute name="allocation-size" type="xsd:int"/>
    </xsd:complexType>

    <!-- ************************************************ -->

    <xsd:complexType name="table-generator">
        <xsd:annotation>
            <xsd:documentation>
                @Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
                public @interface TableGenerator {
                    String name();
                    String table() default "";
                    String catalog() default "";
                    String schema() default "";
                    String pkColumnName() default "";
                    String valueColumnName() default "";
                    String pkColumnValue() default "";
                    int initialValue() default 0;
                    int allocationSize() default 50;
                    UniqueConstraint[] uniqueConstraints() default {};
                }
            </xsd:documentation>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="unique-constraint" type="orm:unique-constraint" 
                minOccurs="0" maxOccurs="unbounded"/>
        </xsd:sequence>
        <xsd:attribute name="name" type="xsd:string" use="required"/>
        <xsd:attribute name="table" type="xsd:string"/>
        <xsd:attribute name="catalog" type="xsd:string"/>
        <xsd:attribute name="schema" type="xsd:string"/>
        <xsd:attribute name="pk-column-name" type="xsd:string"/>
        <xsd:attribute name="value-column-name" type="xsd:string"/>
        <xsd:attribute name="pk-column-value" type="xsd:string"/>
        <xsd:attribute name="initial-value" type="xsd:int"/>
        <xsd:attribute name="allocation-size" type="xsd:int"/>
    </xsd:complexType>
</xsd:schema>