7 Understanding Mappings

EclipseLink can transform data between an object representation and a representation specific to a data source. This transformation is called mapping and it is the core of EclipseLink projects.

A mapping corresponds to a single data member of a domain object. It associates the object data member with its data source representation and defines the means of performing the two-way conversion between object and data source.

This chapter includes the following sections:

7.1 Common Mapping Concepts

This section describes concepts for relational and nonrelational mappings that are unique to EclipseLink:

7.1.1 Mapping Architecture

To define a mapping, you draw upon the following components:

  • The data representation specific to the data source (such as a relational database table or schema-defined XML element) in which you store the object's data.

  • A descriptor for a particular object class.

  • An object class to map.

Note:

A mapping is the same regardless of whether your project is persistent or nonpersistent.

For an example of a typical EclipseLink mapping, see Section 7.1.2, "Mapping Examples".

The type of data source you define in your project determines the type of mappings you can use and how you configure them. In a persistent project, you use mappings to persist to a data source. In a nonpersistent project, you use mappings simply to transform between the object format and some other data representation (such as XML).

A descriptor represents a particular domain object: it describes the object's class. A descriptor also owns the mappings: one mapping for each of the class data members that you intend to persist or transform in memory.

For more information about descriptors, see Chapter 6, "Understanding Descriptors".

7.1.2 Mapping Examples

Although EclipseLink supports more complex mappings, most EclipseLink classes map to a single database table or XML element that defines the type of information available in the class. Each object instance of a given class maps to a single row comprising the object's attributes, plus an identifier (the primary key) that uniquely identifies the object.

Figure 7-1 illustrates the simplest database mapping case in which:

  • Table_X in the database represents Class_X.

  • Object_X1 and Object_X2 are instances of Class_X.

  • Individual rows in Table_X represent Object_X1 and Object_X2, as well as any other instances of Class_X.

Figure 7-1 How Classes and Objects Map to a Database Table

Description of Figure 7-1 follows
Description of "Figure 7-1 How Classes and Objects Map to a Database Table"

EclipseLink provides you with the tools to build these mappings, from the simple mappings illustrated in Figure 7-1, to complex mappings.

For an additional example of a relational mapping, see Figure 7-2, "Serialized Object Converter (relational)".

7.1.3 Using Lazy Loading

JPA specifies that lazy loading is a hint to the persistence provider that data should be fetched lazily when it is first accessed, if possible. If you are developing your application in a Java EE environment, set fetch to javax.persistence.FetchType.LAZY, and the persistence provider supplies all the necessary functionality.

When using a one-to-one or many-to-one mapping in a Java SE environment, use either dynamic or static weaving to perform lazy loading when the fetch attribute is set to FetchType.LAZY.

When using a one-to-one or many-to-one mapping in a Java SE environment and the environment does not permit the use of -javaagent on the JVM command line, use static weaving to perform lazy loading when the fetch attribute is set to FetchType.LAZY.

Table 7-1 lists support for lazy loading by mapping type.

Table 7-1 Support for Lazy Loading by Mapping Type

Mapping Java EE Java SE

Many-to-many

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY (default).

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY (default).

One-to-many

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY (default).

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY (default).

One-to-one

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY.

The fetch attribute is ignored and default javax.persistence.FetchType.EAGER applies.

Many-to-one

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY.

The fetch attribute is ignored and default javax.persistence.FetchType.EAGER applies

Basic

Lazy loading is performed when the fetch attribute is set to javax.persistence.FetchType.LAZY.

The fetch attribute is ignored and default javax.persistence.FetchType.EAGER applies


7.1.4 Mapping Converters and Transformers

If existing EclipseLink mappings do not meet your needs, you can create custom mappings using mapping extensions. These extensions include the following:

Note:

Except for simple type translation, you can use the mapping converters and transformers regardless of whether your data source is relational or nonrelational. Simple type translation is applicable only to XML projects.

7.1.4.1 Serialized Object Converter

The serialized object converter can be used with direct and direct collection mappings, allowing you to map complex objects into binary fields through Java object serialization. Serialized objects are normally stored in RAW or Binary Large Object (BLOB) fields in the database, or HEX or BASE64 elements in an XML document.

Figure 7-2 shows an example of a direct-to-field mappings that uses a serialized object converter. The attribute jobDescription contains a formatted text document that is stored in the JOB_DESC field of the database.

Figure 7-2 Serialized Object Converter (relational)

Description of Figure 7-2 follows
Description of "Figure 7-2 Serialized Object Converter (relational)"

Figure 7-3 demonstrates an example of a nonrelational mapping that uses a serialized object converter. The attribute jobDescription contains a formatted text document that EclipseLink stores in the JOB DESCRIPTION element of an XML schema.

Figure 7-3 Serialized Object Converter (nonrelational)

Description of Figure 7-3 follows
Description of "Figure 7-3 Serialized Object Converter (nonrelational)"

The serialized object converter relies on the Java serializer. Before you map a domain object with the serialized object converter, ensure that the domain object implements the java.io.Serializable interface (or inherits that implementation) and marks all nonserializable fields transient.

7.1.4.2 Type Conversion Converter

The type conversion converter can be used with direct and direct collection mappings, allowing you to map complex objects into binary fields. For example, a Number in the data source can be mapped to a String in Java, or a java.util.Date in Java can be mapped to a java.sql.Date in the data source.

Figure 7-4 illustrates a type conversion mapping (relational). Because the java.util.Date class is stored by default as a Timestamp in the database, it must first be converted to an explicit database type such as java.sql.Date (required only for DB2–most other databases have a single date data type that can store any date or time).

Figure 7-4 Type Conversion Mapping (relational)

Description of Figure 7-4 follows
Description of "Figure 7-4 Type Conversion Mapping (relational) "

Figure 7-5 illustrates a type conversion mapping (nonrelational). java.util.Date object is mapped to a String in a XML schema.

Figure 7-5 Type Conversion Mapping (nonrelational)

Description of Figure 7-5 follows
Description of "Figure 7-5 Type Conversion Mapping (nonrelational)"

You can use a type conversion converter to specify the specific database type when that type must be handled specially for the database. This includes support for the special Oracle JDBC binding options required for NCHAR, NVARCHAR2, and NCLOB fields as well as the special Oracle Thin JDBC insert and update requirements for handling BLOB and CLOB fields greater than 5K.

EclipseLink uses the NCharacter, NClob and NString types in the org.eclipse.persistence.platform.database.oracle package as the converter data type to support the NCHAR, NCLOB and NVARCHAR2 types. EclipseLink uses the java.sql.Blob and Clob types as the converter data type to support BLOB and CLOB values greater than 5K.

You can configure a type conversion converter to map a data source time type (such as TIMESTAMP) to a java.lang.String provided that the String value conforms to the following formats:

  • YYYY/MM/DD HH:MM:SS

  • YY/MM/DD HH:MM:SS

  • YYYY-MM-DD HH:MM:SS

  • YY-MM-DD HH:MM:SS

For more complex String to TIMESTAMP type conversion, consider a transformation mapping (see Section 7.1.4.4, "Transformation Mappings").

7.1.4.3 Object Type Converter

The object type converter can be used with direct and direct collection mappings allowing you to match a fixed number of values to Java objects. Use this converter when the values in the schema differ from those in Java.

Figure 7-6 illustrates an object type conversion between the Employee attribute gender and the XML element gender. If the value of the Java object attribute is Female, EclipseLink stores it in the XML element as F.

Figure 7-6 Object Type XML Converter

Description of Figure 7-6 follows
Description of "Figure 7-6 Object Type XML Converter"

7.1.4.4 Transformation Mappings

In some special circumstances, existing mapping types and their default Java to data source type handling may be insufficient. In these special cases, you can consider using a transformation mapping to perform specialized translations between how a value is represented in Java and in the data source.

A transformation mapping is made up of the following two components:

  • attribute transformer: performs the object attribute transformation at read time

  • field transformer: performs the object attribute-to-field transformation at write time

You can implement a transformer as either a separate class or as a method on your domain object.

Within your implementation of the attribute and field transformer, you can take whatever actions are necessary to transform your application data to suit your data source, and vise versa.

For more information, see Section 7.1.5, "Transformation Mapping".

7.1.5 Transformation Mapping

Use transformation mappings for specialized translations for how a value is represented in Java and how it is represented in the database.

Tip:

Because of the complexity of transformation mappings, it is often easier to perform the transformation with a converter or getter and setter methods of a direct-to-field mapping.

Figure 7-7 illustrates a transformation mapping. The values from the B_DATE and B_TIME fields are used to create a java.util.Date to be stored in the birthDate attribute.

Figure 7-7 Transformation Mappings

Description of Figure 7-7 follows
Description of "Figure 7-7 Transformation Mappings"

Often, a transformation mapping is appropriate when values from multiple fields are used to create an object. This type of mapping requires that you provide an attribute transformation that is invoked when reading the object from the database. This must have at least one parameter that is an instance of Record. In your attribute transformation, you can use Record method get to retrieve the value in a specific column. Your attribute transformation can optionally specify a second parameter, an instance of Session. The Session performs queries on the database to get additional values needed in the transformation. The transformation should return the value to be stored in the attribute.

Transformation mappings also require a field transformation for each field, to be written to the database when the object is saved. The transformation returns the value to be stored in that field.

7.2 Object-Relational Mapping Concepts

This section describes concepts for relational mappings that are unique to EclipseLink:

7.2.1 Indirection (Lazy Loading)

By default, when EclipseLink retrieves a persistent object, it retrieves all of the dependent objects to which it refers. When you configure indirection (also known as lazy reading, lazy loading, and just-in-time reading) for an attribute mapped with a relationship mapping, EclipseLink uses an indirection object as a place holder for the referenced object: EclipseLink defers reading the dependent object until you access that specific attribute. This can result in a significant performance improvement, especially if the application is interested only in the contents of the retrieved object, rather than the objects to which it is related.

Oracle strongly recommends using indirection for all relationship mappings. Not only does this lets you optimize data source access, but it also allows EclipseLink to optimize the unit of work processing, cache access, and concurrency.

Note:

The use of indirection is especially important for providing a proper maintenance of bidirectional relationships. In this case, you must use indirection. If you are operating with collections, you must use transparent indirection (see Section 7.2.3, "Transparent Indirection").

Figure 7-8 shows an indirection example. Without indirection, reading the Order object also reads the dependent collection of LineItem objects. With indirection, reading the Order object does not read the dependent collection of LineItem objects: the lineItems attribute refers to an indirection object. You can access other attributes (such as customerId), but EclipseLink reads the dependent LineItem objects only if and when you access the lineItems attribute.

Figure 7-8 EclipseLink Indirection

Description of Figure 7-8 follows
Description of "Figure 7-8 EclipseLink Indirection"

EclipseLink supports the following types of indirection:

When using indirection with an object that your application serializes, you must consider the effect of any untriggered indirection objects at deserialization time. See Section 7.2.7, "Indirection, Serialization, and Detachment".

7.2.2 Value Holder Indirection

Persistent classes that use indirection must replace relationship attributes with value holder attributes. A value holder is an instance of a class that implements the ValueHolderInterface interface, such as ValueHolder. This object stores the information necessary to retrieve the object it is replacing from the database. If the application does not access the value holder, the replaced object is never read from the database.

To obtain the object that the value holder replaces, use the getValue and setValue methods of the ValueHolderInterface. A convenient way of using these methods is to hide the getValue and setValue methods of the ValueHolderInterface inside get and set methods, as shown in the following illustrations.

Figure 7-9 shows the Employee object being read from the database. The Address object is not read and will not be created unless it is accessed.

Figure 7-9 Address Object Not Read

Description of Figure 7-9 follows
Description of "Figure 7-9 Address Object Not Read"

The first time the address is accessed, as in Figure 7-10, the ValueHolder reads and returns the Address object.

Subsequent requests for the address do not access the database, as shown in Figure 7-11.

Figure 7-11 Subsequent Requests

Description of Figure 7-11 follows
Description of "Figure 7-11 Subsequent Requests"

If you are using method access, the get and set methods specified in the mapping must access the instance of ValueHolderInterface, rather than the object referenced by the value holder. The application should not use these getter and setter, but use the getter and setter that hide the usage of value holders, for example:

public class Employee {
 
   private ValueHolderInterface addressValueHolder;
 
   // Use this get/set pair when configuring your Mapping
   public void setAddressValueHolder(ValueHolderInterface value) {
      this.addressValueHolder = value;
   }
   public ValueHolderInterface getAddressValueHolder() {
      return this.addressValueHolder;
   }
 
   // Your application uses these methods to interact with Addresses
   public void setAddress(Address address) {
      this.addressValueHolder.setValue(address);
   }
   public Address getAddress() {
      return this.addressValueHolder.getValue(address);
   }
 
}

7.2.3 Transparent Indirection

Transparent indirection lets you declare any relationship attribute of a persistent class that holds a collection of related objects as any of the following:

  • java.util.Collection

  • java.util.Hastable

  • java.util.List

  • java.util.Map

  • java.util.Set

  • java.util.Vector

EclipseLink will use an indirection object that implements the appropriate interface and also performs just-in-time reading of the related objects. When using transparent indirection, you do not have to declare the attributes as ValueHolderInterface.

Newly created collection mappings use transparent indirection by default if their attribute is not a ValueHolderInterface.

You can configure EclipseLink to automatically weave transparent indirect container indirection for JPA entities and Plain Old Java Object (POJO) classes. For more information, see Section 3.3.1.4, "Using Java Byte-code Weaving" and Section 3.7, "About Weaving."

7.2.4 Proxy Indirection

The Java class Proxy lets you use dynamic proxy objects as place-holders for a defined interface. Certain EclipseLink mappings can be configured to use proxy indirection, which gives you the benefits of indirection without the need to include EclipseLink classes in your domain model. Proxy indirection is to one-to-one relationship mappings as indirect containers are to collection mappings.

To use proxy indirection, your domain model must satisfy all of the following criteria:

  • The target class of the one-to-one relationship must implement a public interface.

  • The one-to-one attribute on the source class must be of the interface type.

  • If you employ method accessing, then the getter and setter methods must use the interface.

Before using proxy indirection, be aware of the restrictions it places on how you use the unit of work (see Section 7.2.4.1, "Proxy Indirection Restrictions").

To configure proxy indirection, you can use JDeveloper or Java in an amendment method.

7.2.4.1 Proxy Indirection Restrictions

Proxy objects in Java are only able to intercept messages sent. If a primitive operation such as ==, instanceof, or getClass is used on a proxy, it will not be intercepted. This limitation can require the application to be somewhat aware of the usage of proxy objects.

You cannot register the target of a proxy indirection implementation with a unit of work. Instead, first register the source object with the unit of work. This lets you retrieve a target object clone with a call to a getter on the source object clone.

7.2.5 Weaved Indirection

For JPA entities or POJO classes that you configure for weaving, EclipseLink weaves value holder indirection for one-to-one mappings. If you want EclipseLink to weave change tracking and your application includes collection mappings (one-to-many or many-to-many), then you must configure all collection mappings to use transparent indirect container indirection only (you may not configure your collection mappings to use eager loading nor value holder indirection).

For more information, see Section 3.3.1.4, "Using Java Byte-code Weaving".

7.2.6 Indirection and JPA

When you set mapping annotation attribute fetch to lazy, the EclipseLink JPA persistence provider uses indirection.

By default, one-to-many and many-to-many relationships are lazy and use transparent indirection, while one-to-one and many-to-one relationships are not lazy.

If you set one-to-one or many-to-one relationships to lazy, and you enable weaving, the EclipseLink JPA persistence provider will use weaving to enable value holder indirection for these relationships.

For more information, see the following:

7.2.7 Indirection, Serialization, and Detachment

When using indirection (lazy loading), it is likely that a graph of persistent objects will contain untriggered indirection objects. Because indirection objects are transient and do not survive serialization between one JVM and another, untriggered indirection objects will trigger an error if the relationship is accessed after deserialization.

The application must ensure that any indirect relationships that will be required after deserialization have been instantiated before serialization. This can be done through accessing the get method for any relationship using ValueHolder or weaved indirection, and by calling the size method to any relationship using transparent indirection. If the application desired the relationships to be always instantiated on serialization, you could overwrite the serialization writeObject method in the persistent class to first instantiate the desired relationships. Use caution for objects with many or deep relationships to avoid serializing large object graphs: ideally, only the relationships required by the client should be instantiated.

When serializing JPA entities, any lazy relationships that have not been instantiated prior to serialization will trigger errors if they are accessed. If weaving is used on the server, and the entities are serialized to a client, the same weaved classes must exist on the client, either through static weaving of the jar, or through launching the client JVM using the EclipseLink agent.

For more information, see Section 3.3.1.4, "Using Java Byte-code Weaving".

7.3 Object-XML Mapping Concepts

This section describes concepts for nonrelational mappings that are unique to EclipseLink:

7.3.1 Simple Type Translation

The simple type translation can be used with direct and direct collection mappings, allowing you to automatically translate an XML element value to an appropriate Java type based on the element's <type> attribute as defined in your XML schema.

Note:

Simple type translation is applicable only for XML projects.

In code, this is set up when building a mapping using the setIsTypedTextField method on XMLField, for example:

XMLDirectMapping mapping = new XMLDirectMapping();
XMLField tef = new XMLField();
tef.setIsTypedTextField(true);
tef.setXPath("NUMBER/text()");
mapping.setField(tef);
mapping.setAttributeName("number");
xmlDescriptor.addMapping(mapping); 

You can use simple type translation only when the mapping's XPath goes to a text node. You cannot use a simple type translation if the mapping's XPath goes to an attribute.

Using simple type translation, you can make the XML document preserve type information. This is useful when your object model specifies generic object attributes such as java.lang.Object and java.io.Serializable, since they do not trigger specific type conversions in EclipseLink as do specific object attributes such as java.lang.Integer or java.util.Calendar.

Figure 7-12 illustrates a type translation XML mapping for the number attribute of the PhoneNumber class. Notice that the Java attribute is not specific enough to preserve the typing. Simple type translation adds the type information to the resulting document to preserve the typing.

Figure 7-12 Simple Type Translation

Description of Figure 7-12 follows
Description of "Figure 7-12 Simple Type Translation"

By default, EclipseLink uses built-in read and write conversion pairs (see Section 7.3.1.1, "Default Read Conversions" and Section 7.3.1.2, "Default Write Conversions").

You can override this behavior by specifying and configuring your own simple type translation, for example, to write XML binary data as Base64.

7.3.1.1 Default Read Conversions

Table 7-2 lists the built-in conversion pairs for reading XML elements. When the schema <type> attribute is specified and simple type translation is enabled, the value read is converted to the corresponding Java type.

Table 7-2 Simple Type Translation Read Conversions

Schema Type Java Type

base64Binary

Byte[]

boolean

Boolean

byte

Byte

date

Calendar

dateTime

Calendar

double

Double

float

Float

hexBinary

Byte[]

int

int

integer

BigInteger

long

Long

short

Short

string

String

time

Calendar

unsignedByte

Short

unsignedInt

Long

unsignedShort

Integer


7.3.1.2 Default Write Conversions

Table 7-3 lists the built-in conversion pairs for writing XML. When a Java class attribute is of a type in Table 7-3 and the simple type translation is enabled, the corresponding schema type is specified on the element written.

Table 7-3 Simple Type Translation Write Conversions

Java Type Schema Type

Byte[]

hexBinary

BigInteger

integer

Boolean

boolean

Byte

byte

Calendar

dateTime

GregorianCalendar

dateTime

Double

double

Float

float

Integer

int

Long

long

int

int

short

short

String

string


7.4 Object-JSON Mapping Concepts

EclipseLink MOXy supports the ability to convert objects to and from JSON (JavaScript Object Notation). This feature is useful when creating RESTful services; JAX-RS services can accept both XML and JSON messages.

EclipseLink supports all MOXy object-to-XML options when reading and writing JSON, including:

  • EclipseLink's advanced and extended mapping features (in addition to the JAXB specification)

  • Storing mappings in external bindings files

  • Creating dynamic models with Dynamic JAXB

  • Building extensible models that support multitenant applications

EclipseLink provides the following support for mapping JSON documents:

  • JSON bindings that do not require compile time dependencies, in addition to those required for normal JAXB use. You can also write MOXy External Bindings files as JSON documents.

  • Although XML has a single datatype, JSON differentiates between strings, numbers, and booleans. EclipseLink supports these datatypes automatically.

  • JSON does not use attributes; anything mapped with a @XmlAttribute annotation will be marshalled as an element. By default, EclipseLink triggers both the attribute and element events, thereby allowing either the mapped attribute or element to handle the value.

  • EclipseLink supports JSON documents without a root element. By default, if no @XmlRootElement annotation exists, the marshalled JSON document will not have a root element. With EclipseLink, you can override this behavior (that is, omit the root element from the JSON output).

  • Because JSON does not use namespaces, all namespaces and prefixes are ignored by default when marshaling and unmarshaling. With EclipseLink, you can supply a Map of namespace-to-prefix (or an instance of NamespacePrefixMapper) to the marshaller and unmarshaller. The namespace prefix will appear in the marshalled document prepended to the element name.

  • By default, when marshalling to JSON, EclipseLink marshals empty collections as [ ], EclipseLink allows you to override this behavior, so that empty collections are not marshalled at all.

  • You can marshal and unmarshal root-level collections.

For more information on EclipseLink support for JSON documents, see "Using JSON Documents" in Oracle Fusion Middleware Developing JAXB Applications Using Oracle TopLink

7.5 About JPA Mapping Types

To map entity classes to relational tables you must configure a mapping per persistent field. The following sections describe EclipeLink's JPA mapping types:

7.5.1 Basic Mappings

Simple Java types are mapped as part of the immediate state of an entity in its fields or properties. Mappings of simple Java types are called basic mappings.

By default, the EclipseLink persistence provider automatically configures a basic mapping for simple types.

Use the following annotations to fine-tune how your application implements these mappings:

For all mapping types there are a common set of options:

  • Read-Only: Specifies that the mapping should populate the value on read and copy. Required when multiple mappings share the same database column.

  • Converters: Allows custom data types and data conversions to be used with most mapping types

    • Annotations: @Converter, @TypeConverter, @ObjectTypeConverter, @StructConverter, @Convert

    • External Metadata: <converter>, <type-converter>, <object-type-converter>, <struct-converter>, <convert>

For more information on these annotations, see Oracle Fusion Middleware Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

7.5.2 Default Conversions and Converters

EclipseLink defines the following converter annotations (in addition to JPA-defined annotations):

  • @Converter

  • @TypeConverter

  • @ObjectTypeConverter

  • @StructConverter

  • @Convert

The EclipseLink persistence provider searches the converter annotations in the following order:

  • @Convert

  • @Enumerated

  • @Lob

  • @Temporal

  • Serialized (automatic)

You can define converters at the class, field and property level. You can specify EclipseLink converters on the following types of classes:

  • @Entity

  • @MappedSuperclass

  • @Embeddable

You can use EclipseLink converters with the following mappings:

  • @Basic

  • @Id

  • @Version

  • @BasicMap

  • @BasicCollection

If you specify a converter with any other type of mapping annotation, EclipseLink will throw an exception.

For more information on these annotations, see Oracle Fusion Middleware Java Persistence API (JPA) Extensions Reference for Oracle TopLink.

7.5.3 Collection Mappings

You can access additional advanced mappings and mapping options through the EclipseLink descriptor and mapping API using a DescriptorCustomizer class.

7.5.3.1 One-to-Many Mapping

One-to-many mappings are used to represent the relationship between a single source object and a collection of target objects. They are a good example of something that is simple to implement in Java using a Collection (or other collection types) of target objects, but difficult to implement using relational databases.

In a Java Collection, the owner references its parts. In a relational database, the parts reference their owner. Relational databases use this implementation to make querying more efficient.

Figure 7-13 One-to-Many Relationships

This figure illustrates the one-to-many relationship.
Description of "Figure 7-13 One-to-Many Relationships"

Note:

The phone attribute shown in the One-to-Many Relationships is of type Vector. You can use a Collection interface (or any class that implements the Collection interface) for declaring the collection attribute.

7.5.3.1.1 JPA Mapping

By default, JPA automatically defines a OneToMany mapping for a many-valued association with one-to-many multiplicity.

Use the @OneToMany annotation to do the following:

  • configure the fetch type to EAGER

  • configure the associated target entity, because the Collection used is not defined using generics

  • configure the operations that must be cascaded to the target of the association: for example, if the owning entity is removed, ensure that the target of the association is also removed

  • configure the details of the join table used by the persistence provider for unidirectional one-to-many relationships. For a one-to-many using a mappedBy or JoinColumn, the deletion of the related objects is cascaded on the database. For a one-to-many using a JoinTable, the deletion of the join table is cascaded on the database (target objects cannot be cascaded even if private because of constraint direction).

For more information, see Section 11.1.23 "JoinTable Annotation" in the JPA Specification.

http://jcp.org/en/jsr/detail?id=317

7.5.3.2 Many-to-Many Mapping

Many-to-many mappings represent the relationships between a collection of source objects and a collection of target objects. They require the creation of an intermediate table for managing the associations between the source and target records.

Figure 7-14 illustrates a many-to-many mapping in Java and in relational database tables.

Figure 7-14 Many-to-many Relationships

Many-to-many Relationships
Description of "Figure 7-14 Many-to-many Relationships"

Note:

For the projects attribute shown in the Many-to-many Relationships you can use a Collection interface (or any class that implements the Collection interface) for declaring the collection attribute.

7.5.3.2.1 JPA Mapping

By default, JPA automatically defines a ManyToMany mapping for a many-valued association with many-to-many multiplicity.

Use the @ManyToMany annotation to do the following:

  • configure the Fetch Type to EAGER;

  • configure the mapping to forbid null values (for nonprimitive types) in case null values are inappropriate for your application;

  • configure the associated target entity because the Collection used is not defined using generics;

  • configure the operations that must be cascaded to the target of the association (for example, if the owning entity is removed, ensure that the target of the association is also removed).

For a list of supported attributes for the @ManyToMany annotation, see the Java Persistence specification:

http://jcp.org/en/jsr/detail?id=317

7.5.4 Using Optimistic Locking

Oracle recommends using optimistic locking. With optimistic locking, all users have read access to the data. When a user attempts to write a change, the application checks to ensure the data has not changed since the user read the data.

7.5.4.1 Optimistic Locking in a Stateless Environment

In a stateless environment, take care to avoid processing out-of-date (stale) data. A common strategy for avoiding stale data is to implement optimistic locking, and store the optimistic lock values in the object. This solution requires careful implementation if the stateless application serializes the objects, or sends the contents of the object to the client in an alternative format. In this case, transport the optimistic lock values to the client in the HTTP contents of an edit page. You must then use the returned values in any write transaction to ensure that the data did not change while the client was performing its work.

You can use optimistic version locking or optimistic field locking policies. We recommend using version locking policies.

7.5.4.2 Optimistic Version Locking

Use the @Version annotation to enable the JPA-managed optimistic locking by specifying the version field or property of an entity class that serves as its optimistic lock value (recommended).

When choosing a version field or property, ensure that the following is true:

  • there is only one version field or property per entity;

  • you choose a property or field persisted to the primary table;

  • your application does not modify the version property or field.

For more information, see Section 11.1.45 "Table Annotation" in the JPA Specification.

http://jcp.org/en/jsr/detail?id=317

Note:

The field or property type must either be a numeric type (such as Number, long, int, BigDecimal, and so on), or a java.sql.Timestamp. EclipseLink recommends using a numeric type.

The @Version annotation does not have attributes. The @Version annotation supports the use of EclipseLink converters. See Section 7.5.2, "Default Conversions and Converters."

For more information, see Section 11.1.9 "Column Annotation" in the JPA Specification.

http://jcp.org/en/jsr/detail?id=317