Metadata
metadata
JPA
metadata
metadata
JPA requires that you accompany each persistent class with persistence metadata.
This metadata serves three primary purposes:
To identify persistent classes.
To override default JPA behavior.
To provide the JPA implementation with information that it cannot glean from
simply reflecting on the persistent class.
annotations
Persistence metadata is specified using either the Java annotations defined in
the javax.persistence package, XML mapping files, or a
mixture of both. In the latter case, XML declarations override conflicting
annotations. If you choose to use XML metadata, the XML files must be available
at development and runtime, and must be discoverable via either of two
strategies:
In a resource named orm.xml placed in a
META-INF directory within a directory in your classpath or within a
jar archive containing your persistent classes.
Declared in your
persistence.xml configuration file. In this case, each XML
metadata 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.
We describe the standard metadata annotations and XML equivalents throughout
this chapter. The full schema for XML mapping files is available in
. JPA also standardizes relational
mapping metadata and named query metadata, which we discuss in
and
respectively.
OpenJPA defines many useful annotations beyond the standard set. See
and
in the Reference Guide for details. There are currently no XML equivalents for
these extension annotations.
Persistence metadata may be used to validate the contents of your entities prior to communicating
with the database. This differs from mapping meta data which is primarily used for schema generation.
For example if you indicate that a relationship is not optional (e.g. @Basic(optional=false)) OpenJPA
will validate that the variable in your entity is not null before inserting a row
in the database.
Through the course of this chapter, we will create the persistent object model
above.
Class Metadata
The following metadata annotations and XML elements apply to persistent class
declarations.
Entity
Entity
annotation
metadata
Entity
annotations
Entity
The Entity annotation denotes an entity class. All entity
classes must have this annotation. The Entity annotation
takes one optional property:
String name: Name used to refer to the entity in queries.
Must not be a reserved literal in JPQL. Defaults to the unqualified name of the
entity class.
The equivalent XML element is entity. It has the following
attributes:
class: The entity class. This attribute is required.
name: Named used to refer to the class in queries. See the
name property above.
access: The access type to use for the class. Must either be
FIELD or PROPERTY. For details on access
types, see .
OpenJPA uses a process called enhancement to modify the
bytecode of entities for transparent lazy loading and immediate dirty tracking.
See in the Reference Guide for
details on enhancement.
Id Class
IdClass
metadata
IdClass
annotations
IdClass
As we discussed in ,
entities with multiple identity fields must use an identity class
to encapsulate their persistent identity. The IdClass
annotation specifies this class. It accepts a single
java.lang.Class value.
The equivalent XML element is id-class, which has a single
attribute:
class: Set this required attribute to the name of the
identity class.
Mapped Superclass
MappedSuperclass
metadata
MappedSuperclass
annotations
MappedSuperclass
A mapped superclass is a non-entity class that can define
persistent state and mapping information for entity subclasses. Mapped
superclasses are usually abstract. Unlike true entities, you cannot query a
mapped superclass, pass a mapped superclass instance to any
EntityManager or Query methods, or declare a
persistent relation with a mapped superclass target. You denote a mapped
superclass with the MappedSuperclass marker annotation.
The equivalent XML element is mapped-superclass. It expects
the following attributes:
class: The entity class. This attribute is required.
access: The access type to use for the class. Must either be
FIELD or PROPERTY. For details on access
types, see .
OpenJPA allows you to query on mapped superclasses. A query on a mapped
superclass will return all matching subclass instances. OpenJPA also allows you
to declare relations to mapped superclass types; however, you cannot query
across these relations.
Embeddable
Embeddable
metadata
Embeddable
annotations
Embeddable
The Embeddable annotation designates an embeddable
persistent class. Embeddable instances are stored as part of the record of their
owning instance. All embeddable classes must have this annotation.
A persistent class can either be an entity or an embeddable class, but not both.
The equivalent XML element is embeddable. It understands the
following attributes:
class: The entity class. This attribute is required.
access: The access type to use for the class. Must either be
FIELD or PROPERTY. For details on access
types, see .
OpenJPA allows a persistent class to be both an entity and an embeddable class.
Instances of the class will act as entities when persisted explicitly or assigned
to non-embedded fields of entities. Instances will act as embedded values when
assigned to embedded fields of entities.
To signal that a class is both an entity and an embeddable class in OpenJPA,
simply add both the @Entity and the @Embeddable
annotations to the class.
EntityListeners
EntityListeners
entity-listeners
metadata
EntityListeners
annotations
EntityListeners
An entity may list its lifecycle event listeners in the
EntityListeners annotation. This value of this annotation is an
array of the listener Class es for the entity. The
equivalent XML element is entity-listeners. For more details
on entity listeners, see .
Example
Here are the class declarations for our persistent object model, annotated with
the appropriate persistence metadata. Note that Magazine
declares an identity class, and that Document and
Address are a mapped superclass and an embeddable class,
respectively. LifetimeSubscription and
TrialSubscription override the default entity name to supply a
shorter alias for use in queries.
Class Metadata
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
public class Magazine {
...
public static class MagazineId {
...
}
}
@Entity
public class Article {
...
}
package org.mag.pub;
@Entity
public class Company {
...
}
@Entity
public class Author {
...
}
@Embeddable
public class Address {
...
}
package org.mag.subscribe;
@MappedSuperclass
public abstract class Document {
...
}
@Entity
public class Contract
extends Document {
...
}
@Entity
public class Subscription {
...
@Entity
public static class LineItem
extends Contract {
...
}
}
@Entity(name="Lifetime")
public class LifetimeSubscription
extends Subscription {
...
}
@Entity(name="Trial")
public class TrialSubscription
extends Subscription {
...
}
The equivalent declarations in XML:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
version="1.0">
<mapped-superclass class="org.mag.subscribe.Document">
...
</mapped-superclass>
<entity class="org.mag.Magazine">
<id-class class="org.mag.Magazine$MagazineId"/>
...
</entity>
<entity class="org.mag.Article">
...
</entity>
<entity class="org.mag.pub.Company">
...
</entity>
<entity class="org.mag.pub.Author">
...
</entity>
<entity class="org.mag.subscribe.Contract">
...
</entity>
<entity class="org.mag.subscribe.LineItem">
...
</entity>
<entity class="org.mag.subscribe.LifetimeSubscription" name="Lifetime">
...
</entity>
<entity class="org.mag.subscribe.TrialSubscription" name="Trial">
...
</entity>
<embeddable class="org.mag.pub.Address">
...
</embeddable>
</entity-mappings>
Field and Property Metadata
The persistence implementation must be able to retrieve and set the persistent
state of your entities, mapped superclasses, and embeddable types. JPA offers
two modes of persistent state access: field access, and
property access. The access type of a persistent attribute
can be either set explicitly on a class or attribute level, inherited, or
determined by the provider.
Under field access, the implementation injects state directly into your
persistent fields, and retrieves changed state from your fields as well. To
declare field access on an entire entity with XML metadata, set the
access attribute of your entity XML
element to FIELD. To use field access for an entire entity
using annotation metadata, simply place your metadata and mapping annotations
on your field declarations:
@ManyToOne
private Company publisher;
metadata
property access
persistent classes
property access
persistent properties
persistent fields
Property access, on the other hand, retrieves and loads state through JavaBean
"getter" and "setter" methods. For a property p of type
T, you must define the following getter method:
T getP();
For boolean properties, this is also acceptable:
boolean isP();
You must also define the following setter method:
void setP(T value);
To implicitly use property access for an entire class by default, set your
entity element's access attribute to
PROPERTY, or place your metadata and mapping annotations on
the getter method:
@ManyToOne
private Company getPublisher() { ... }
private void setPublisher(Company publisher) { ... }
Explicit Access
metadata
explicit access
persistent classes
explicit access
persistent attributes
persistent fields
persistent properties
The access type of a class or individual persistent attributes can be specified
explicitly using the @Access annotation or access
attribute on the XML elements used to define persistent attributes.
When explicitly defining access, specify the explicit access type for the class
and then apply the @Access annotation or access
XML attribute to individual fields or properties. If explicit
FIELD or PROPERTY is specified at the
class level, all eligible non-transient fields or properties will be persistent.
If using class level FIELD access, non-persistent fields must
be transient or annotated with @Transient.
If using class level PROPERTY access, non-persistent
properties must be annotated @Transient or excluded using
the transient XML attribute. Refer to the JPA specification
for specific rules regarding the use of explicit access with embeddables and
within an inheritance hierarchy.
This entity definitions shows how multiple access types may be specified
on an entity:
@Entity
@Access(AccessType.FIELD)
public class PaymentContract {
@Id
private String id;
@Temporal(TemporalType.DATE)
private String contractDate;
@Transient
private String terms;
@Version
private int version;
@Lob
@Access(AccessType.PROPERTY)
public String getContractTerms() {
return terms;
}
public void setContractTerms(String terms) {
// Format string before persisting
this.terms = formatTerms(terms);
}
...
}
The equivalent declarations in XML:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_2_0.xsd"
version="2.0">
<entity class="org.xyz.PaymentContract" access="FIELD">
<attributes>
<id name="id"/>
<basic name="contractTerms" access="PROPERTY">
<lob/>
</basic>
<basic name="contractDate">
<temporal>DATE</temporal>
</basic>
<version name="version"/>
<transient name="terms"/>
</attributes>
</entity>
</entity-mappings>
When using property access, only the getter and setter method for a property
should ever access the underlying persistent field directly. Other methods,
including internal business methods in the persistent class, should go through
the getter and setter methods when manipulating persistent state.
Also, take care when adding business logic to your getter and setter methods.
Consider that they are invoked by the persistence implementation to load and
retrieve all persistent state; other side effects might not be desirable.
The remainder of this document uses the term "persistent field" to refer to
either a persistent field or a persistent property.
Transient
Transient
metadata
Transient
annotations
Transient
The Transient annotation specifies that a field is
non-persistent. Use it to exclude fields from management that would otherwise be
persistent. Transient is a marker annotation only; it
has no properties.
The equivalent XML element is transient. It has a single
attribute:
name: The transient field or property name. This attribute
is required.
Id
Id
metadata
Id
annotations
Id
Annotate your simple identity fields with Id. This
annotation has no properties. We explore entity identity and identity fields in
.
The equivalent XML element is id. It has one required
attribute:
name: The name of the identity field or property.
Generated Value
GeneratedValue
metadata
GeneratedValue
annotations
GeneratedValue
The previous section showed you how to declare your identity fields with the
Id annotation. It is often convenient to allow the
persistence implementation to assign a unique value to your identity fields
automatically. JPA includes the GeneratedValue
annotation for this purpose. It has the following properties:
GenerationType strategy: Enum value specifying how to
auto-generate the field value. The GenerationType enum
has the following values:
GeneratorType.AUTO: The default. Assign the field a
generated value, leaving the details to the JPA vendor.
GenerationType.IDENTITY: The database will assign an
identity value on insert.
GenerationType.SEQUENCE: Use a datastore sequence to
generate a field value.
GenerationType.TABLE: Use a sequence table to generate a
field value.
String generator: The name of a generator defined in mapping
metadata. We show you how to define named generators in
. If the
GenerationType is set but this property is unset, the JPA
implementation uses appropriate defaults for the selected generation type.
The equivalent XML element is generated-value, which
includes the following attributes:
strategy: One of TABLE,
SEQUENCE, IDENTITY, or AUTO,
defaulting to AUTO.
generator: Equivalent to the generator property listed
above.
OpenJPA allows you to use the GeneratedValue annotation
on any field, not just identity fields. Before using the IDENTITY
generation strategy, however, read
in the Reference Guide.
OpenJPA also offers additional generator strategies for non-numeric fields,
which you can access by setting strategy to AUTO
(the default), and setting the generator string
to:
mapping metadata
uuid-string
uuid-string
uuid-string: OpenJPA will generate a 128-bit type 1 UUID
unique within the network, represented as a 16-character string. For more
information on UUIDs, see the IETF UUID draft specification at:
http://www.ics.uci.edu/~ejw/authoring/uuid-guid/
mapping metadata
uuid-hex
uuid-hex
uuid-hex: Same as uuid-string, but
represents the type 1 UUID as a 32-character hexadecimal string.
mapping metadata
uuid-type4-string
uuid-type4-string
uuid-type4-string: OpenJPA will generate a 128-bit type 4
pseudo-random UUID, represented as a 16-character string. For more
information on UUIDs, see the IETF UUID draft specification at:
http://www.ics.uci.edu/~ejw/authoring/uuid-guid/
mapping metadata
uuid-type4-hex
uuid-type4-hex
uuid-type4-hex: Same as uuid-type4-string
, but represents the type 4 UUID as a 32-character hexadecimal string.
These string constants are defined in
org.apache.openjpa.persistence.Generator.
If the entities are mapped to the same table name but with different schema
name within one PersistenceUnit intentionally, and the
strategy of GeneratedType.AUTO is used to generate the ID
for each entity, a schema name for each entity must be explicitly declared
either through the annotation or the mapping.xml file. Otherwise, the mapping
tool only creates the tables for those entities with the schema names under
each schema. In addition, there will be only one
OPENJPA_SEQUENCE_TABLE created for all the entities within
the PersistenceUnit if the entities are not identified
with the schema name. Read and
in the Reference Guide.
Embedded Id
EmbeddedId
metadata
EmbeddedId
annotations
EmbeddedId
If your entity has multiple identity values, you may declare multiple
@Id fields, or you may declare a single @EmbeddedId
field. The type of a field annotated with EmbeddedId must
be an embeddable entity class. The fields of this embeddable class are
considered the identity values of the owning entity. We explore entity identity
and identity fields in .
The EmbeddedId annotation has no properties.
The equivalent XML element is embedded-id. It has one
required attribute:
name: The name of the identity field or property.
Version
Version
metadata
Version
annotations
Version
Use the Version annotation to designate a version field.
explained the importance of
version fields to JPA. This is a marker annotation; it has no properties.
The equivalent XML element is version, which has a single
attribute:
name: The name of the version field or property. This
attribute is required.
Basic
Basic
metadata
Basic
annotations
Basic
Basic signifies a standard value persisted as-is to the
datastore. You can use the Basic annotation on persistent
fields of the following types: primitives, primitive wrappers,
java.lang.String, byte[],
Byte[], char[],
Character[], java.math.BigDecimal,
java.math.BigInteger,
java.util.Date, java.util.Calendar,
java.sql.Date, java.sql.Timestamp,
Enums, and Serializable types.
Basic declares these properties:
FetchType fetch: Whether to load the field eagerly
(FetchType.EAGER) or lazily (
FetchType.LAZY). Defaults to FetchType.EAGER.
boolean optional: Whether the datastore allows null values.
Defaults to true.
The equivalent XML element is basic. It has the following
attributes:
name: The name of the field or property. This attribute is
required.
fetch: One of EAGER or LAZY
.
optional: Boolean indicating whether the field value may be
null.
Fetch Type
eager fetching
FetchType
FetchType
eager fetching
metadata
FetchType
Many metadata annotations in JPA have a fetch property. This
property can take on one of two values: FetchType.EAGER or
FetchType.LAZY. FetchType.EAGER means that
the field is loaded by the JPA implementation before it returns the persistent
object to you. Whenever you retrieve an entity from a query or from the
EntityManager, you are guaranteed that all of its eager
fields are populated with datastore data.
FetchType.LAZY is a hint to the JPA runtime that you want to
defer loading of the field until you access it. This is called lazy
loading. Lazy loading is completely transparent; when you attempt to
read the field for the first time, the JPA runtime will load the value from the
datastore and populate the field automatically. Lazy loading is only a hint and
not a directive because some JPA implementations cannot lazy-load certain field
types.
With a mix of eager and lazily-loaded fields, you can ensure that commonly-used
fields load efficiently, and that other state loads transparently when accessed.
As you will see in ,
you can also use eager fetching to ensure that entities have all needed data
loaded before they become detached at the end of a
persistence context.
OpenJPA can lazy-load any field type. OpenJPA also allows you to dynamically
change which fields are eagerly or lazily loaded at runtime. See
in the Reference Guide for details.
The Reference Guide details OpenJPA's eager fetching behavior in
.
Embedded
Embedded
metadata
Embedded
annotations
Embedded
Use the Embedded marker annotation on embeddable field
types. Embedded fields are mapped as part of the datastore record of the
declaring entity. In our sample model, Author and
Company each embed their Address,
rather than forming a relation to an Address as a
separate entity.
The equivalent XML element is embedded, which expects a
single attribute:
name: The name of the field or property. This attribute is
required.
Many To One
ManyToOne
metadata
ManyToOne
annotations
ManyToOne
When an entity A references a single entity
B, and other As might also reference the same
B, we say there is a many to one
relation from A to B. In our sample
model, for example, each magazine has a reference to its publisher. Multiple
magazines might have the same publisher. We say, then, that the
Magazine.publisher field is a many to one relation from magazines to
publishers.
JPA indicates many to one relations between entities with the
ManyToOne annotation. This annotation has the following properties:
Class targetEntity: The class of the related entity type.
CascadeType[] cascade: Array of enum values defining cascade
behavior for this field. We explore cascades below. Defaults to an empty array.
FetchType fetch: Whether to load the field eagerly
(FetchType.EAGER) or lazily
(FetchType.LAZY). Defaults to
FetchType.EAGER. See above
for details on fetch types.
boolean optional: Whether the related object must exist. If
false, this field cannot be null. Defaults to
true.
The equivalent XML element is many-to-one. It accepts the
following attributes:
name: The name of the field or property. This attribute is
required.
target-entity: The class of the related type.
fetch: One of EAGER or
LAZY.
optional: Boolean indicating whether the field value may be
null.
Cascade Type
CascadeType
metadata
CascadeType
We introduce the JPA EntityManager in
. The EntityManager
has APIs to persist new entities, remove (delete) existing
entities, refresh entity state from the datastore, and merge detached
entity state back into the persistence context. We explore all of
these APIs in detail later in the overview.
When the EntityManager is performing the above
operations, you can instruct it to automatically cascade the operation to the
entities held in a persistent field with the cascade property
of your metadata annotation. This process is recursive. The cascade
property accepts an array of CascadeType enum
values.
CascadeType.PERSIST: When persisting an entity, also persist
the entities held in this field. We suggest liberal application of this cascade
rule, because if the EntityManager finds a field that
references a new entity during flush, and the field does not use
CascadeType.PERSIST, it is an error.
CascadeType.REMOVE: When deleting an entity, also delete the
entities held in this field.
CascadeType.REFRESH: When refreshing an entity, also refresh
the entities held in this field.
CascadeType.MERGE: When merging entity state, also merge the
entities held in this field.
OpenJPA offers enhancements to JPA's CascadeType.REMOVE functionality,
including additional annotations to control how and when dependent fields will
be removed. See for more details.
CascadeType defines one additional value,
CascadeType.ALL, that acts as a shortcut for all of the values above.
The following annotations are equivalent:
@ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE,
CascadeType.REFRESH,CascadeType.MERGE})
private Company publisher;
@ManyToOne(cascade=CascadeType.ALL)
private Company publisher;
In XML, these enumeration constants are available as child elements of the
cascade element. The cascade element is
itself a child of many-to-one. The following examples are
equivalent:
<many-to-one name="publisher">
<cascade>
<cascade-persist/>
<cascade-merge/>
<cascade-remove/>
<cascade-refresh/>
</cascade>
</many-to-one>
<many-to-one name="publisher">
<cascade>
<cascade-all/>
</cascade>
</many-to-one>
One To Many
OneToMany
metadata
OneToMany
annotations
OneToMany
When an entity A references multiple B
entities, and no two As reference the same
B, we say there is a one to many relation from
A to B.
One to many relations are the exact inverse of the many to one relations we
detailed in the preceding section. In that section, we said that the
Magazine.publisher field is a many to one relation from magazines to
publishers. Now, we see that the Company.mags field is the
inverse - a one to many relation from publishers to magazines. Each company may
publish multiple magazines, but each magazine can have only one publisher.
JPA indicates one to many relations between entities with the
OneToMany annotation. This annotation has the following properties:
Class targetEntity: The class of the related entity type.
This information is usually taken from the parameterized collection or map
element type. You must supply it explicitly, however, if your field isn't a
parameterized type.
String mappedBy: Names the many to one field in the related
entity that maps this bidirectional relation. We explain bidirectional relations
below. Leaving this property unset signals that this is a standard
unidirectional relation.
CascadeType[] cascade: Array of enum values defining cascade
behavior for the collection elements. We explore cascades above in
. Defaults to an empty array.
FetchType fetch: Whether to load the field eagerly
(FetchType.EAGER) or lazily
(FetchType.LAZY). Defaults to
FetchType.LAZY. See above
for details on fetch types.
The equivalent XML element is one-to-many, which includes
the following attributes:
name: The name of the field or property. This attribute is
required.
target-entity: The class of the related type.
fetch: One of EAGER or
LAZY.
mapped-by: The name of the field or property that owns the
relation. See .
You may also nest the cascade element within a
one-to-many element.
Bidirectional Relations
bidirectional relations
mappedBy
mapping metadata
mapping metadata
mappedBy property
When two fields are logical inverses of each other, they form a
bidirectional relation. Our model contains two bidirectional
relations: Magazine.publisher and Company.mags
form one bidirectional relation, and Article.authors
and Author.articles form the other. In both cases,
there is a clear link between the two fields that form the relationship. A
magazine refers to its publisher while the publisher refers to all its published
magazines. An article refers to its authors while each author refers to her
written articles.
When the two fields of a bidirectional relation share the same datastore
mapping, JPA formalizes the connection with the mappedBy
property. Marking Company.mags as mappedByMagazine.publisher means two things:
Company.mags uses the datastore mapping for
Magazine.publisher, but inverses it. In fact, it is illegal to
specify any additional mapping information when you use the mappedBy
property. All mapping information is read from the referenced field.
We explore mapping in depth in .
Magazine.publisher is the "owner" of the relation. The field
that specifies the mapping data is always the owner. This means that changes to
the Magazine.publisher field are reflected in the datastore,
while changes to the Company.mags field alone are not.
Changes to Company.mags may still affect the JPA
implementation's cache, however. Thus, it is very important that you keep your
object model consistent by properly maintaining both sides of your bidirectional
relations at all times.
You should always take advantage of the mappedBy property
rather than mapping each field of a bidirectional relation independently.
Failing to do so may result in the JPA implementation trying to update the
database with conflicting data. Be careful to only mark one side of the relation
as mappedBy, however. One side has to actually do the
mapping!
You can configure OpenJPA to automatically synchronize both sides of a
bidirectional relation, or to perform various actions when it detects
inconsistent relations. See in the
Reference Guide for details.
One To One
OneToOne
metadata
OneToOne
annotations
OneToOne
When an entity A references a single entity
B, and no other As can reference the same
B, we say there is a one to one relation between
A and B. In our sample model,
Magazine has a one to one relation to Article
through the Magazine.coverArticle field. No two magazines can
have the same cover article.
JPA indicates one to one relations between entities with the
OneToOne annotation. This annotation has the following properties:
Class targetEntity: The class of the related entity type.
This information is usually taken from the field type.
String mappedBy: Names the field in the related entity that
maps this bidirectional relation. We explain bidirectional relations in
above. Leaving this property
unset signals that this is a standard unidirectional relation.
CascadeType[] cascade: Array of enum values defining cascade
behavior for this field. We explore cascades in
above. Defaults to an empty
array.
FetchType fetch: Whether to load the field eagerly
(FetchType.EAGER) or lazily
(FetchType.LAZY). Defaults to
FetchType.EAGER. See above
for details on fetch types.
boolean optional: Whether the related object must exist. If
false, this field cannot be null. Defaults to
true.
The equivalent XML element is one-to-one which understands
the following attributes:
name: The name of the field or property. This attribute is
required.
target-entity: The class of the related type.
fetch: One of EAGER or
LAZY.
mapped-by: The field that owns the relation. See
.
You may also nest the cascade element within a
one-to-one element.
Many To Many
ManyToMany
metadata
ManyToMany
annotations
ManyToMany
When an entity A references multiple B
entities, and other As might reference some of the same
Bs, we say there is a many to many
relation between A and B. In our sample
model, for example, each article has a reference to all the authors that
contributed to the article. Other articles might have some of the same authors.
We say, then, that Article and Author
have a many to many relation through the Article.authors
field.
JPA indicates many to many relations between entities with the
ManyToMany annotation. This annotation has the following properties:
Class targetEntity: The class of the related entity type.
This information is usually taken from the parameterized collection or map
element type. You must supply it explicitly, however, if your field isn't a
parameterized type.
String mappedBy: Names the many to many field in the related
entity that maps this bidirectional relation. We explain bidirectional relations
in above. Leaving this
property unset signals that this is a standard unidirectional relation.
CascadeType[] cascade: Array of enum values defining cascade
behavior for the collection elements. We explore cascades above in
. Defaults to an empty array.
FetchType fetch: Whether to load the field eagerly
(FetchType.EAGER) or lazily
(FetchType.LAZY). Defaults to
FetchType.LAZY. See above
for details on fetch types.
The equivalent XML element is many-to-many. It accepts the
following attributes:
name: The name of the field or property. This attribute is
required.
target-entity: The class of the related type.
fetch: One of EAGER or
LAZY.
mapped-by: The field that owns the relation. See
.
You may also nest the cascade element within a
many-to-many element.
Order By
OrderBy
metadata
OrderBy
annotations
OrderBy
Datastores such as relational databases do not preserve the order of records.
Your persistent List fields might be ordered one way the
first time you retrieve an object from the datastore, and a completely different
way the next. To ensure consistent ordering of collection fields, you must use
the OrderBy annotation. The OrderBy
annotation's value is a string defining the order of the collection
elements. An empty value means to sort on the identity value(s) of the elements
in ascending order. Any other value must be of the form:
<field name>[ ASC|DESC][, ...]
Each <field name> is the name of a persistent field in
the collection's element type. You can optionally follow each field by the
keyword ASC for ascending order, or DESC
for descending order. If the direction is omitted, it defaults to ascending.
The equivalent XML element is order-by which can be listed as
a sub-element of the one-to-many or many-to-many
elements. The text within this element is parsed as the order by
string.
Map Key
MapKey
metadata
MapKey
annotations
MapKey
JPA supports persistent Map fields through either a
OneToMany
or ManyToMany
association. The related entities form the map values. JPA
derives the map keys by extracting a field from each entity value. The
MapKey annotation designates the field that is used as
the key. It has the following properties:
String name: The name of a field in the related entity class
to use as the map key. If no name is given, defaults to the identity field of
the related entity class.
The equivalent XML element is map-key which can be listed as
a sub-element of the one-to-many or many-to-many
elements. The map-key element has the following
attributes:
name: The name of the field in the related entity class to
use as the map key.
Persistent Field Defaults
In the absence of any of the annotations above, JPA defines the following
default behavior for declared fields:
Fields declared static, transient, or final
default to non-persistent.
Fields of any primitive type, primitive wrapper type,
java.lang.String, byte[],
Byte[], char[],
Character[], java.math.BigDecimal,
java.math.BigInteger,
java.util.Date, java.util.Calendar,
java.sql.Date, java.sql.Timestamp,
or any Serializable type default to persistent, as if
annotated with
@Basic.
Fields of an embeddable type default to persistent, as if annotated with
@Embedded.
All other fields default to non-persistent.
Note that according to these defaults, all relations between entities must be
annotated explicitly. Without an annotation, a relation field will default to
serialized storage if the related entity type is serializable, or will default
to being non-persistent if not.
XML Schema
metadata
XSD
JPA
metadata
XML
metadata
The latest revision of the version 2.0 orm schema is presented below. Version
2.0 of the schema must be used if JPA 2.0 elements are specified as XML
metadata. Many of the elements in the schema relate to object/relational
mapping rather than metadata; these elements are discussed in
. Version 1.0 of the orm schema can be
found at .
<?xml version="1.0" encoding="UTF-8"?>
<!-- Java Persistence API object/relational mapping file 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="2.0">
<xsd:annotation>
<xsd:documentation>
@(#)orm_2_0.xsd 2.0 October 1 2009
</xsd:documentation>
</xsd:annotation>
<xsd:annotation>
<xsd:documentation>
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright 2005-2009 Sun Microsystems, Inc. All rights reserved.
The contents of this file are subject to the terms of either the
GNU General Public License Version 2 only ("GPL") or the Common
Development and Distribution License("CDDL") (collectively, the
"License"). You may not use this file except in compliance with
the License. You can obtain a copy of the License at
https://glassfish.dev.java.net/public/CDDL+GPL.html or
glassfish/bootstrap/legal/LICENSE.txt. See the License for the
specific language governing permissions and limitations under the
License.
When distributing the software, include this License Header
Notice in each file and include the License file at
glassfish/bootstrap/legal/LICENSE.txt. Sun designates this
particular file as subject to the "Classpath" exception as
provided by Sun in the GPL Version 2 section of the License file
that accompanied this code. If applicable, add the following
below the License Header, with the fields enclosed by brackets []
replaced by your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
Contributor(s):
If you wish your version of this file to be governed by only the
CDDL or only the GPL Version 2, indicate your decision by adding
"[Contributor] elects to include this software in this
distribution under the [CDDL or GPL Version 2] license." If you
don't indicate a single choice of license, a recipient has the
option to distribute your version of this file under either the
CDDL, the GPL Version 2 or to extend the choice of license to its
licensees as provided above. However, if you add GPL Version 2
code and therefore, elected the GPL Version 2 license, then the
option applies only if the new code is made subject to such
option by the copyright holder.
</xsd:documentation>
</xsd:annotation>
<xsd:annotation>
<xsd:documentation>
<![CDATA[
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.
Object/relational mapping files must indicate the object/relational
mapping file schema by using the persistence namespace:
http://java.sun.com/xml/ns/persistence
and indicate the version of the schema by
using the version element as shown below:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm
http://java.sun.com/xml/ns/persistence/orm/orm_2_0.xsd"
version="2.0">
...
</entity-mappings>
]]>
</xsd:documentation>
</xsd:annotation>
<xsd:complexType name="emptyType" />
<xsd:simpleType name="versionType">
<xsd:restriction base="xsd:token">
<xsd:pattern value="[0-9]+(\.[0-9]+)*" />
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:element name="entity-mappings">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
The entity-mappings element is the root element of a mapping
file. It contains the following four types of elements:
1. The persistence-unit-metadata element contains metadata
for the entire persistence unit. It is undefined if this element
occurs in multiple mapping files within the same
persistence unit.
2. The package, schema, catalog and access elements apply to all of
the entity, mapped-superclass and embeddable
elements defined in
the same file in which they occur.
3. The sequence-generator, table-generator, named-query,
named-native-query and sql-result-set-mapping
elements are global
to the persistence unit. It is undefined to have more than one
sequence-generator or table-generator of the same
name in the same
or different mapping files in a persistence unit. It is also
undefined to have more than one named-query,
named-native-query, or
result-set-mapping of the same name in the same or different mapping
files in a persistence unit.
4. The entity, mapped-superclass and embeddable elements each define
the mapping information for a managed persistent
class. The mapping
information contained in these elements may be complete or it may
be partial.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="persistence-unit-metadata"
type="orm:persistence-unit-metadata" minOccurs="0" />
<xsd:element name="package" type="xsd:string"
minOccurs="0" />
<xsd:element name="schema" type="xsd:string"
minOccurs="0" />
<xsd:element name="catalog" type="xsd:string"
minOccurs="0" />
<xsd:element name="access" type="orm:access-type"
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:attribute name="version" type="orm:versionType"
fixed="2.0" use="required" />
</xsd:complexType>
</xsd:element>
<!-- **************************************************** -->
<xsd:complexType name="persistence-unit-metadata">
<xsd:annotation>
<xsd:documentation>
Metadata that applies to the persistence unit and not just to
the mapping file in which it is contained.
If the xml-mapping-metadata-complete element is specified,
the complete set of mapping metadata for the persistence unit
is contained in the XML mapping files for the persistence unit.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="xml-mapping-metadata-complete"
type="orm:emptyType" minOccurs="0" />
<xsd:element name="persistence-unit-defaults"
type="orm:persistence-unit-defaults" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="persistence-unit-defaults">
<xsd:annotation>
<xsd:documentation>
These defaults are applied to the persistence unit as a whole
unless they are overridden by local annotation or XML
element settings.
schema - Used as the schema for all tables, secondary tables, join
tables, collection tables, sequence generators, and table
generators that apply to the persistence unit
catalog - Used as the catalog for all tables, secondary tables, join
tables, collection tables, sequence generators, and
table generators that apply to the persistence unit
delimited-identifiers - Used to treat database identifiers as
delimited identifiers.
access - Used as the access type for all managed classes in
the persistence unit
cascade-persist - Adds cascade-persist to the set of cascade options
in all entity relationships of the persistence unit
entity-listeners - List of default entity listeners to be invoked
on each entity in the persistence unit.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="schema" type="xsd:string"
minOccurs="0" />
<xsd:element name="catalog" type="xsd:string"
minOccurs="0" />
<xsd:element name="delimited-identifiers" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="access" type="orm:access-type"
minOccurs="0" />
<xsd:element name="cascade-persist" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="entity-listeners" type="orm:entity-listeners"
minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="entity">
<xsd:annotation>
<xsd:documentation>
Defines the settings and mappings for an entity. Is allowed to be
sparsely populated and used in conjunction with the annotations.
Alternatively, the metadata-complete attribute can be
used to
indicate that no annotations on the entity class (and its fields
or properties) are to be processed. If this is the case then
the defaulting rules for the entity and its subelements will
be recursively applied.
@Target(TYPE) @Retention(RUNTIME)
public @interface Entity {
String name() default "";
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<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="orm:emptyType" minOccurs="0" />
<xsd:element name="exclude-superclass-listeners"
type="orm:emptyType" 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:attribute name="cacheable" type="xsd:boolean" />
<xsd:attribute name="metadata-complete" type="xsd:boolean" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:simpleType name="access-type">
<xsd:annotation>
<xsd:documentation>
This element determines how the persistence provider accesses the
state of an entity or embedded object.
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="PROPERTY" />
<xsd:enumeration value="FIELD" />
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:complexType name="association-override">
<xsd:annotation>
<xsd:documentation>
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface AssociationOverride {
String name();
JoinColumn[] joinColumns() default{};
JoinTable joinTable() default @JoinTable;
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string" minOccurs="0" />
<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:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
<!-- **************************************************** -->
<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="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="column" type="orm:column" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="attributes">
<xsd:annotation>
<xsd:documentation>
This element contains the entity field or property mappings.
It may be sparsely populated to include only a subset of the
fields or properties. If metadata-complete for the entity is true
then the remainder of the attributes will be defaulted according
to the default rules.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:choice>
<xsd:element name="id" type="orm:id"
minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="embedded-id" type="orm:embedded-id"
minOccurs="0" />
</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="element-collection" type="orm:element-collection"
minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="embedded" type="orm:embedded"
minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="transient" type="orm:transient"
minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="basic">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Basic {
FetchType fetch() default EAGER;
boolean optional() default true;
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="column" type="orm:column"
minOccurs="0" />
<xsd:choice>
<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:choice>
</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:attribute name="access" type="orm:access-type" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="cascade-type">
<xsd:annotation>
<xsd:documentation>
public enum CascadeType { ALL, PERSIST, MERGE, REMOVE, REFRESH,
DETACH};
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="cascade-all" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="cascade-persist" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="cascade-merge" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="cascade-remove" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="cascade-refresh" type="orm:emptyType"
minOccurs="0" />
<xsd:element name="cascade-detach" type="orm:emptyType"
minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="collection-table">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface CollectionTable {
String name() default "";
String catalog() default "";
String schema() default "";
JoinColumn[] joinColumns() 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="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="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 table() 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="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="discriminator-column">
<xsd:annotation>
<xsd:documentation>
@Target({TYPE}) @Retention(RUNTIME)
public @interface DiscriminatorColumn {
String name() default "DTYPE";
DiscriminatorType discriminatorType() default STRING;
String columnDefinition() default "";
int length() default 31;
}
</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: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: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:complexType name="element-collection">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ElementCollection {
Class targetClass() default void.class;
FetchType fetch() default LAZY;
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice>
<xsd:element name="order-by" type="orm:order-by"
minOccurs="0" />
<xsd:element name="order-column" type="orm:order-column"
minOccurs="0" />
</xsd:choice>
<xsd:choice>
<xsd:element name="map-key" type="orm:map-key"
minOccurs="0" />
<xsd:sequence>
<xsd:element name="map-key-class" type="orm:map-key-class"
minOccurs="0" />
<xsd:choice>
<xsd:element name="map-key-temporal"
type="orm:temporal" minOccurs="0" />
<xsd:element name="map-key-enumerated"
type="orm:enumerated" minOccurs="0" />
<xsd:element name="map-key-attribute-override"
type="orm:attribute-override" minOccurs="0"
maxOccurs="unbounded" />
</xsd:choice>
<xsd:choice>
<xsd:element name="map-key-column"
type="orm:map-key-column" minOccurs="0" />
<xsd:element name="map-key-join-column"
type="orm:map-key-join-column" minOccurs="0"
maxOccurs="unbounded" />
</xsd:choice>
</xsd:sequence>
</xsd:choice>
<xsd:choice>
<xsd:sequence>
<xsd:element name="column" type="orm:column"
minOccurs="0" />
<xsd:choice>
<xsd:element name="temporal" type="orm:temporal"
minOccurs="0" />
<xsd:element name="enumerated" type="orm:enumerated"
minOccurs="0" />
<xsd:element name="lob" type="orm:lob"
minOccurs="0" />
</xsd:choice>
</xsd:sequence>
<xsd:sequence>
<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:sequence>
</xsd:choice>
<xsd:element name="collection-table" type="orm:collection-table"
minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="target-class" type="xsd:string" />
<xsd:attribute name="fetch" type="orm:fetch-type" />
<xsd:attribute name="access" type="orm:access-type" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="embeddable">
<xsd:annotation>
<xsd:documentation>
Defines the settings and mappings for embeddable objects. Is
allowed to be sparsely populated and used in conjunction with
the annotations. Alternatively, the metadata-complete attribute
can be used to indicate that no annotations are to be processed
in the class. If this is the case then the defaulting rules will
be recursively applied.
@Target({TYPE}) @Retention(RUNTIME)
public @interface Embeddable {}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="attributes" type="orm:embeddable-attributes"
minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="class" type="xsd:string" use="required" />
<xsd:attribute name="access" type="orm:access-type" />
<xsd:attribute name="metadata-complete" type="xsd:boolean" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="embeddable-attributes">
<xsd:sequence>
<xsd:element name="basic" type="orm:basic"
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="element-collection" type="orm:element-collection"
minOccurs="0" maxOccurs="unbounded" />
<xsd:element name="embedded" type="orm:embedded"
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:element name="association-override" type="orm:association-override"
minOccurs="0" maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="access" type="orm:access-type" />
</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:attribute name="access" type="orm:access-type" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="entity-listener">
<xsd:annotation>
<xsd:documentation>
Defines an entity listener to be invoked at lifecycle events
for the entities that list this listener.
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
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:sequence>
<xsd:attribute name="class" type="xsd:string" use="required" />
</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-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: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: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="orm:enum-type" />
</xsd:simpleType>
<!-- **************************************************** -->
<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: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="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: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="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:attribute name="access" type="orm:access-type" />
</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="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:complexType name="join-column">
<xsd:annotation>
<xsd:documentation>
@Target({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 table() 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:complexType name="join-table">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
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="lob">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Lob {}
</xsd:documentation>
</xsd:annotation>
</xsd:complexType>
<!-- **************************************************** -->
<xsd:simpleType name="lock-mode-type">
<xsd:annotation>
<xsd:documentation>
public enum LockModeType { READ, WRITE, OPTIMISTIC,
OPTIMISTIC_FORCE_INCREMENT, PESSIMISTIC_READ,
PESSIMISTIC_WRITE,
PESSIMISTIC_FORCE_INCREMENT, NONE};
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:token">
<xsd:enumeration value="READ" />
<xsd:enumeration value="WRITE" />
<xsd:enumeration value="OPTIMISTIC" />
<xsd:enumeration value="OPTIMISTIC_FORCE_INCREMENT" />
<xsd:enumeration value="PESSIMISTIC_READ" />
<xsd:enumeration value="PESSIMISTIC_WRITE" />
<xsd:enumeration value="PESSIMISTIC_FORCE_INCREMENT" />
<xsd:enumeration value="NONE" />
</xsd:restriction>
</xsd:simpleType>
<!-- **************************************************** -->
<xsd:complexType name="many-to-many">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice>
<xsd:element name="order-by" type="orm:order-by"
minOccurs="0" />
<xsd:element name="order-column" type="orm:order-column"
minOccurs="0" />
</xsd:choice>
<xsd:choice>
<xsd:element name="map-key" type="orm:map-key"
minOccurs="0" />
<xsd:sequence>
<xsd:element name="map-key-class" type="orm:map-key-class"
minOccurs="0" />
<xsd:choice>
<xsd:element name="map-key-temporal"
type="orm:temporal" minOccurs="0" />
<xsd:element name="map-key-enumerated"
type="orm:enumerated" minOccurs="0" />
<xsd:element name="map-key-attribute-override"
type="orm:attribute-override" minOccurs="0"
maxOccurs="unbounded" />
</xsd:choice>
<xsd:choice>
<xsd:element name="map-key-column"
type="orm:map-key-column" minOccurs="0" />
<xsd:element name="map-key-join-column"
type="orm:map-key-join-column" minOccurs="0"
maxOccurs="unbounded" />
</xsd:choice>
</xsd:sequence>
</xsd:choice>
<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="access" type="orm:access-type" />
<xsd:attribute name="mapped-by" type="xsd:string" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="many-to-one">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface ManyToOne {
Class targetEntity() default void.class;
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:attribute name="access" type="orm:access-type" />
<xsd:attribute name="maps-id" type="xsd:string" />
<xsd:attribute name="id" type="xsd:boolean" />
</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:complexType name="map-key-class">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface MapKeyClass {
Class value();
}
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="class" type="xsd:string" use="required" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="map-key-column">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface MapKeyColumn {
String name() default "";
boolean unique() default false;
boolean nullable() default false;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
String table() 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="map-key-join-column">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface MapKeyJoinColumn {
String name() default "";
String referencedColumnName() default "";
boolean unique() default false;
boolean nullable() default false;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
String table() 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:complexType name="mapped-superclass">
<xsd:annotation>
<xsd:documentation>
Defines the settings and mappings for a mapped superclass. Is
allowed to be sparsely populated and used in conjunction with
the annotations. Alternatively, the metadata-complete attribute
can be used to indicate that no annotations are to be processed
If this is the case then the defaulting rules will be recursively
applied.
@Target(TYPE) @Retention(RUNTIME)
public @interface MappedSuperclass{}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="id-class" type="orm:id-class"
minOccurs="0" />
<xsd:element name="exclude-default-listeners"
type="orm:emptyType" minOccurs="0" />
<xsd:element name="exclude-superclass-listeners"
type="orm:emptyType" 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" use="required" />
<xsd:attribute name="access" type="orm:access-type" />
<xsd:attribute name="metadata-complete" type="xsd:boolean" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="named-native-query">
<xsd:annotation>
<xsd:documentation>
@Target({TYPE}) @Retention(RUNTIME)
public @interface NamedNativeQuery {
String name();
String query();
QueryHint[] hints() default {};
Class resultClass() default void.class;
String resultSetMapping() default ""; //named SqlResultSetMapping
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="query" type="xsd:string" />
<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="named-query">
<xsd:annotation>
<xsd:documentation>
@Target({TYPE}) @Retention(RUNTIME)
public @interface NamedQuery {
String name();
String query();
LockModeType lockMode() default NONE;
QueryHint[] hints() default {};
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<xsd:element name="query" type="xsd:string" />
<xsd:element name="lock-mode" type="orm:lock-mode-type"
minOccurs="0" />
<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="one-to-many">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToMany {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default LAZY;
String mappedBy() default "";
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:choice>
<xsd:element name="order-by" type="orm:order-by"
minOccurs="0" />
<xsd:element name="order-column" type="orm:order-column"
minOccurs="0" />
</xsd:choice>
<xsd:choice>
<xsd:element name="map-key" type="orm:map-key"
minOccurs="0" />
<xsd:sequence>
<xsd:element name="map-key-class" type="orm:map-key-class"
minOccurs="0" />
<xsd:choice>
<xsd:element name="map-key-temporal"
type="orm:temporal" minOccurs="0" />
<xsd:element name="map-key-enumerated"
type="orm:enumerated" minOccurs="0" />
<xsd:element name="map-key-attribute-override"
type="orm:attribute-override" minOccurs="0"
maxOccurs="unbounded" />
</xsd:choice>
<xsd:choice>
<xsd:element name="map-key-column"
type="orm:map-key-column" minOccurs="0" />
<xsd:element name="map-key-join-column"
type="orm:map-key-join-column" minOccurs="0"
maxOccurs="unbounded" />
</xsd:choice>
</xsd:sequence>
</xsd:choice>
<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="access" type="orm:access-type" />
<xsd:attribute name="mapped-by" type="xsd:string" />
<xsd:attribute name="orphan-removal" type="xsd:boolean" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="one-to-one">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OneToOne {
Class targetEntity() default void.class;
CascadeType[] cascade() default {};
FetchType fetch() default EAGER;
boolean optional() default true;
String mappedBy() default "";
boolean orphanRemoval() default false;
}
</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="access" type="orm:access-type" />
<xsd:attribute name="mapped-by" type="xsd:string" />
<xsd:attribute name="orphan-removal" type="xsd:boolean" />
<xsd:attribute name="maps-id" type="xsd:string" />
<xsd:attribute name="id" type="xsd:boolean" />
</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="order-column">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface OrderColumn {
String name() default "";
boolean nullable() default true;
boolean insertable() default true;
boolean updatable() default true;
String columnDefinition() default "";
}
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="name" type="xsd:string" />
<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:complexType>
<!-- **************************************************** -->
<xsd:complexType name="post-load">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD}) @Retention(RUNTIME)
public @interface PostLoad {}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<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:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<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:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<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:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="method-name" 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:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<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:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<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:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="method-name" type="xsd:string"
use="required" />
</xsd:complexType>
<!-- **************************************************** -->
<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="query-hint">
<xsd:annotation>
<xsd:documentation>
@Target({}) @Retention(RUNTIME)
public @interface QueryHint {
String name();
String value();
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="value" type="xsd:string" use="required" />
</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[] pkJoinColumns() 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="sequence-generator">
<xsd:annotation>
<xsd:documentation>
@Target({TYPE, METHOD, FIELD}) @Retention(RUNTIME)
public @interface SequenceGenerator {
String name();
String sequenceName() default "";
String catalog() default "";
String schema() default "";
int initialValue() default 1;
int allocationSize() default 50;
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
<xsd:attribute name="sequence-name" type="xsd:string" />
<xsd:attribute name="catalog" type="xsd:string" />
<xsd:attribute name="schema" type="xsd:string" />
<xsd:attribute name="initial-value" type="xsd:int" />
<xsd:attribute name="allocation-size" type="xsd:int" />
</xsd:complexType>
<!-- **************************************************** -->
<xsd:complexType name="sql-result-set-mapping">
<xsd:annotation>
<xsd:documentation>
@Target({TYPE}) @Retention(RUNTIME)
public @interface SqlResultSetMapping {
String name();
EntityResult[] entities() default {};
ColumnResult[] columns() default {};
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="description" type="xsd:string"
minOccurs="0" />
<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="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="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="description" type="xsd:string"
minOccurs="0" />
<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:simpleType name="temporal">
<xsd:annotation>
<xsd:documentation>
@Target({METHOD, FIELD}) @Retention(RUNTIME)
public @interface Temporal {
TemporalType value();
}
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="orm: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
}
</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: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="unique-constraint">
<xsd:annotation>
<xsd:documentation>
@Target({}) @Retention(RUNTIME)
public @interface UniqueConstraint {
String name() default "";
String[] columnNames();
}
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="column-name" type="xsd:string"
maxOccurs="unbounded" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
</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:attribute name="access" type="orm:access-type" />
</xsd:complexType>
</xsd:schema>
Conclusion
That exhausts persistence metadata annotations. We present the class definitions
for our sample model below:
Complete Metadata
package org.mag;
@Entity
@IdClass(Magazine.MagazineId.class)
public class Magazine {
@Id private String isbn;
@Id private String title;
@Version private int version;
private double price; // defaults to @Basic
private int copiesSold; // defaults to @Basic
@OneToOne(fetch=FetchType.LAZY,
cascade={CascadeType.PERSIST,CascadeType.REMOVE})
private Article coverArticle;
@OneToMany(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
@OrderBy
private Collection<Article> articles;
@ManyToOne(fetch=FetchType.LAZY, cascade=CascadeType.PERSIST)
private Company publisher;
@Transient private byte[] data;
...
public static class MagazineId {
...
}
}
@Entity
public class Article {
@Id private long id;
@Version private int version;
private String title; // defaults to @Basic
private byte[] content; // defaults to @Basic
@ManyToMany(cascade=CascadeType.PERSIST)
@OrderBy("lastName, firstName")
private Collection<Author> authors;
...
}
package org.mag.pub;
@Entity
public class Company {
@Id private long id;
@Version private int version;
private String name; // defaults to @Basic
private double revenue; // defaults to @Basic
private Address address; // defaults to @Embedded
@OneToMany(mappedBy="publisher", cascade=CascadeType.PERSIST)
private Collection<Magazine> mags;
@OneToMany(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
private Collection<Subscription> subscriptions;
...
}
@Entity
public class Author {
@Id private long id;
@Version private int version;
private String firstName; // defaults to @Basic
private double lastName; // defaults to @Basic
private Address address; // defaults to @Embedded
@ManyToMany(mappedBy="authors", cascade=CascadeType.PERSIST)
private Collection<Article> arts;
...
}
@Embeddable
public class Address {
private String street; // defaults to @Basic
private String city; // defaults to @Basic
private String state; // defaults to @Basic
private String zip; // defaults to @Basic
...
}
package org.mag.subscribe;
@MappedSuperclass
public abstract class Document {
@Id private long id;
@Version private int version;
...
}
@Entity
public class Contract
extends Document {
private String terms; // defaults to @Basic
...
}
@Entity
public class Subscription {
@Id private long id;
@Version private int version;
private Date startDate; // defaults to @Basic
private double payment; // defaults to @Basic
@OneToMany(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
@MapKey(name="num")
private Map<Long,LineItem> lineItems;
...
@Entity
public static class LineItem
extends Contract {
private String comments; // defaults to @Basic
private double price; // defaults to @Basic
private long num; // defaults to @Basic
@ManyToOne
private Magazine magazine;
...
}
}
@Entity(name="Lifetime")
public class LifetimeSubscription
extends Subscription {
@Basic(fetch=FetchType.LAZY)
private boolean getEliteClub() { ... }
public void setEliteClub(boolean elite) { ... }
...
}
@Entity(name="Trial")
public class TrialSubscription
extends Subscription {
public Date getEndDate() { ... }
public void setEndDate(Date end) { ... }
...
}
The same metadata declarations in XML:
<entity-mappings xmlns="http://java.sun.com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence/orm orm_1_0.xsd"
version="1.0">
<!-- declares a default access type for all entities -->
<access-type>FIELD</access-type>
<mapped-superclass class="org.mag.subscribe.Document">
<attributes>
<id name="id">
<generated-value strategy="IDENTITY"/>
</id>
<version name="version"/>
</attributes>
</mapped-superclass>
<entity class="org.mag.Magazine">
<id-class="org.mag.Magazine$MagazineId"/>
<attributes>
<id name="isbn"/>
<id name="title"/>
<basic name="name"/>
<basic name="price"/>
<basic name="copiesSold"/>
<version name="version"/>
<many-to-one name="publisher" fetch="LAZY">
<cascade>
<cascade-persist/>
</cascade>
</many-to-one>
<one-to-many name="articles">
<order-by/>
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-many>
<one-to-one name="coverArticle" fetch="LAZY">
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-one>
<transient name="data"/>
</attributes>
</entity>
<entity class="org.mag.Article">
<attributes>
<id name="id"/>
<basic name="title"/>
<basic name="content"/>
<version name="version"/>
<many-to-many name="articles">
<order-by>lastName, firstName</order-by>
</many-to-many>
</attributes>
</entity>
<entity class="org.mag.pub.Company">
<attributes>
<id name="id"/>
<basic name="name"/>
<basic name="revenue"/>
<version name="version"/>
<one-to-many name="mags" mapped-by="publisher">
<cascade>
<cascade-persist/>
</cascade>
</one-to-many>
<one-to-many name="subscriptions">
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-many>
</attributes>
</entity>
<entity class="org.mag.pub.Author">
<attributes>
<id name="id"/>
<basic name="firstName"/>
<basic name="lastName"/>
<version name="version"/>
<many-to-many name="arts" mapped-by="authors">
<cascade>
<cascade-persist/>
</cascade>
</many-to-many>
</attributes>
</entity>
<entity class="org.mag.subcribe.Contract">
<attributes>
<basic name="terms"/>
</attributes>
</entity>
<entity class="org.mag.subcribe.Subscription">
<attributes>
<id name="id"/>
<basic name="payment"/>
<basic name="startDate"/>
<version name="version"/>
<one-to-many name="items">
<map-key name="num">
<cascade>
<cascade-persist/>
<cascade-remove/>
</cascade>
</one-to-many>
</attributes>
</entity>
<entity class="org.mag.subscribe.Subscription.LineItem">
<attributes>
<basic name="comments"/>
<basic name="price"/>
<basic name="num"/>
<many-to-one name="magazine"/>
</attributes>
</entity>
<entity class="org.mag.subscribe.LifetimeSubscription" name="Lifetime"
access="PROPERTY">
<attributes>
<basic name="eliteClub" fetch="LAZY"/>
</attributes>
</entity>
<entity class="org.mag.subscribe.TrialSubscription" name="Trial">
<attributes>
<basic name="endDate"/>
</attributes>
</entity>
<embeddable class="org.mag.pub.Address">
<attributes>
<basic name="street"/>
<basic name="city"/>
<basic name="state"/>
<basic name="zip"/>
</attributes>
</embeddable>
</entity-mappings>
will show you how to map your
persistent classes to the datastore using additional annotations and XML markup.
First, however, we turn to the JPA runtime APIs.