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.
Persistence metadata is specified using either the Java 5 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
the META-INF
directory of the classpath
or the jar archive containing your persistent classes.
As 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 loader of the class.
We describe the standard metadata annotations and XML equivalents throughout this chapter. The full schema for XML mapping files is available in Section 5.3, “XML Schema”. JPA also standardizes relational mapping metadata and named query metadata, which we discuss in Chapter 12, Mapping Metadata and Section 10.1.9, “Named Queries” respectively.
Note | |
---|---|
Kodo defines many useful annotations beyond the standard set. See Section 6.3, “Additional JPA Metadata” and Section 6.4, “Metadata Extensions” in the Reference Guide for details. There are currently no XML equivalents for these extension annotations. |
Through the course of this chapter, we will create the persistent object model above.
The following metadata annotations and XML elements apply to persistent class declarations.
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. It must not be a reserved literal
in JPQL. It 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. It must either be FIELD
or
PROPERTY
. For details on access
types, see Section 5.2, “Field and Property Metadata”.
Note | |
---|---|
Kodo uses a process called enhancement to modify the bytecode of entities for transparent lazy loading and immediate dirty tracking. See Section 5.2, “Enhancement” in the Reference Guide for details on enhancement. |
As we discussed in Section 4.2.1, “Identity Class”,
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
: This required attribute lists
the class name for the identity class.
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. It must either be FIELD
or
PROPERTY
. For details on access
types, see Section 5.2, “Field and Property Metadata”.
Note | |
---|---|
Kodo allows you to query on mapped superclasses. A query on a mapped superclass will return all matching subclass instances. Kodo also allows you to declare relations to mapped superclass types; however, you cannot query across these relations. |
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. It must either be FIELD
or
PROPERTY
. For details on access
types, see Section 5.2, “Field and Property Metadata”.
Note | |
---|---|
Kodo allows a persistent class to be both an entity and an embeddable class. Instances of the class will act as entites 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 Kodo, simply add both the |
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
Section 4.3, “Lifecycle Callbacks”.
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.
Example 5.1. 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>