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;
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) { ... }
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.
Each class must use either field access or property access for all state; you cannot use both access types within the same class. Additionally, a subclass must use the same access type as its superclass.
The remainder of this document uses the term "persistent field" to refer to either a persistent field or a persistent property.
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.
Annotate your simple identity fields with Id
. This
annotation has no properties. We explore entity identity and identity fields in
Section 1.3, “
Identity Fields
”.
The equivalent XML element is id
. It has one required
attribute:
name
: The name of the identity field or property.
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
Section 5, “
Generators
”. 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
Section 4.4, “
Autoassign / Identity Strategy Caveats
” 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:
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/
uuid-hex
: Same as uuid-string
, but
represents the type 1 UUID as a 32-character hexadecimal 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/
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 Section 6, “
Generators
” and
Section 11, “
Default Schema
” in the Reference Guide.
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 Section 1.3, “
Identity Fields
”.
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.
Use the Version
annotation to designate a version field.
Section 1.4, “
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
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
,
Enum
s, 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.
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 Section 3, “ Persistence Context ”, 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 Section 7, “ Fetch Groups ” in the Reference Guide for details.
The Reference Guide details OpenJPA's eager fetching behavior in Section 8, “ Eager Fetching ”.
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.
When an entity A
references a single entity
B
, and other A
s 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 Section 2.7.1, “
Fetch Type
” 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.
We introduce the JPA EntityManager
in
Chapter 8,
EntityManager
. 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 Section 4.2.1, “ Dependent ” 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>
When an entity A
references multiple B
entities, and no two A
s 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
Section 2.9.1, “
Cascade Type
”. Defaults to an empty array.
FetchType fetch
: Whether to load the field eagerly
(FetchType.EAGER
) or lazily
(FetchType.LAZY
). Defaults to
FetchType.LAZY
. See Section 2.7.1, “
Fetch Type
” 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 Section 2, “
Field and Property Metadata
”.
You may also nest the cascade
element within a
one-to-many
element.
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 mappedBy
Magazine.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 Chapter 13,
Mapping Metadata
.
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 Section 5, “ Managed Inverses ” in the Reference Guide for details.
When an entity A
references a single entity
B
, and no other A
s 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
Section 2.10.1, “
Bidirectional Relations
” 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
Section 2.9.1, “
Cascade Type
” 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 Section 2.7.1, “
Fetch Type
” 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
Section 2, “
Field and Property Metadata
”.
You may also nest the cascade
element within a
one-to-one
element.
When an entity A
references multiple B
entities, and other A
s might reference some of the same
B
s, 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 Section 2.10.1, “
Bidirectional Relations
” 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
Section 2.9.1, “
Cascade Type
”. Defaults to an empty array.
FetchType fetch
: Whether to load the field eagerly
(FetchType.EAGER
) or lazily
(FetchType.LAZY
). Defaults to
FetchType.LAZY
. See Section 2.7.1, “
Fetch Type
” 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
Section 2, “
Field and Property Metadata
”.
You may also nest the cascade
element within a
many-to-many
element.
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.
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.
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.