Skip Headers

Oracle TopLink Developer's Guide 10g Release 3 (10.1.3) B13593-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# Mapping Concepts

This section describes concepts unique to TopLink mappings, including the following:

- Mapping Architecture (applicable to relational and nonrelational mappings)

- Example Mapping (applicable to relational and nonrelational mappings)

- Automatic Mappings

  - Automapping With TopLink Workbench at Development Time (applicable to relational and nonrelational mappings)

  - Default Mapping in EJB 2.0 or 3.0 CMP Projects Using OC4J at Run Time (applicable to relational mappings)

  - JAXB Project Generation at Development Time (applicable to XML mappings)

- Indirection (applicable to object-relational mappings)

- Method Accessors and Attribute Accessors (applicable to relational and nonrelational mappings)

- Mapping Converters and Transformers

  - Serialized Object Converter (applicable to relational and nonrelational mappings)

  - Type Conversion Converter (applicable to relational and nonrelational mappings)

  - Object Type Converter (applicable to XML mappings)

  - Simple Type Translator (applicable to XML mappings)

  - Transformation Mappings (applicable to relational and nonrelational mappings)

- Mappings and XPath (applicable to XML mappings)

- Mappings and xsd:list and xsd:union Types (applicable to XML mappings)

- Mappings and the jaxb:class Customization (applicable to XML mappings)

- Mappings and JAXB Typesafe Enumerations (applicable to XML mappings)

## 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 TopLink mapping, see "Example Mapping".

The type of data source you define in your TopLink 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). For more information about data source and project types, see "TopLink Project Types".

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

Note: Persistence is applicable at the descriptor level.

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

TopLink provides mappings to handle a wide variety of data types and data representations. For more information, see "Mapping Types".

All mappings are subclasses of the `oracle.toplink.mappings.DatabaseMapping` class. For more information about the mapping API, see "Understanding the Mapping API".

## Example Mapping

Although TopLink supports more complex mappings, most TopLink 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 33-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 33-1 How Classes and Objects Map to a Database Table

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

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

For an additional example of a relational mapping, see Figure 36-1, "Direct-to-Field Mapping".

For an example of a nonrelational mapping, see Figure 65-34, "XML Transformation Mappings".

## Automatic Mappings

Typically, you use TopLink Workbench to define mappings on a class-by-class and data member-by-data-member basis manually (see "Creating Mappings Manually During Development").

Alternatively, you can take advantage of the following:

- Automapping With TopLink Workbench at Development Time

- Default Mapping in EJB 2.0 or 3.0 CMP Projects Using OC4J at Run Time

- JAXB Project Generation at Development Time

### Automapping With TopLink Workbench at Development Time

You can use TopLink Workbench Automap feature to automatically define default mappings for every class and data member in your project (see "Creating Mappings Automatically During Development").

TopLink Workbench automapping is available for all project types and assumes that both the object model and database schema are already defined.

### Default Mapping in EJB 2.0 or 3.0 CMP Projects Using OC4J at Run Time

Default mapping is a relational persistence framework term that refers to making the framework automatically generate the object descriptor metadata (including such things as mappings, login data, database platform, locking, and foreign keys).

Note: You can apply default mapping to relational projects only.

TopLink can also optionally create or drop-and-create the tables associated with the entities during the deployment. This means that TopLink can handle the whole deployment process with the minimum requirements: a compliant EAR file and a valid data source. This frees you from creating tables and specifying mappings before you deploy your application.

TopLink default mapping supports the following features:

- Direct-to-field mapping support for standard CMP (that is, not dependent object) fields

- Serialized object mapping support for dependent objects

- One-to-one, one-to-many, and many-to-many mappings support for CMR fields

- Self-referencing, unidirectional and bidirectional relationship mappings

- Optimistic version locking for each entity

- Automatic table drop and create, platform-specified supported types, default size and subsize, and database-reserved keywords

- EJB QL (EJB query language) queries, such as finder and ejbSelect

- Unknown primary key class case (primary key-class type `java.lang.Object.class`)

Default mapping is available for EJB 2.0 and 3.0 CMP relational projects deployed to OC4J configured to use TopLink as the default persistence manager. In this configuration, the EJB container provides the entity bean descriptor data (from `ejb-jar.xml`) required by the persistence manager to generate the persistence descriptor file.

If a `toplink-ejb-jar.xml` descriptor file is not present, TopLink, working as the OC4J default persistence manager, generates a default persistence descriptor file for any EJB 2.0 or 3.0 project during deployment. In this case, TopLink applies default mappings and, optionally, automatic table generation. The generated descriptor file includes the following:

- Mapping for each entity CMP and CMR field

- Optimistic locking, foreign keys, target foreign key, and relation table

- Transparent indirection for relationships

- Database login and platform metadata

If a `toplink-ejb-jar.xml` descriptor file is present and specified in the `orion-ejb-jar.xml` file or if equivalent EJB 3.0 annotations are specified, TopLink does not apply default mapping: it honours the mappings specified in the `toplink-ejb-jar.xml` file. In this case, you can still configure automatic table generation.

For more information, see "Configuring default-mapping Properties"

### JAXB Project Generation at Development Time

JAXB provides an API and a tool that allow automatic two-way mapping between XML documents and Java objects. The JAXB compiler generates all the Java classes and mappings based on the provided Document type Definition (DTD) and a schema definition.

For more information on JAXB, see Architecture for XML Binding (JAXB): A Primer at `http://java.sun.com/developer/technicalArticles/xml/jaxb/index.html`

For more information on XML mappings, see Chapter 65, "Understanding XML Mappings".

## Indirection

By default, when TopLink 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, TopLink uses an indirection object as a place holder for the referenced object: TopLink 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 TopLink to optimize the unit of work processing, cache access, and concurrency.

Figure 33-2 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 TopLink reads the dependent `LineItem` objects only if and when you access the `lineItems` attribute.

Figure 33-2 TopLink Indirection

Description of "Figure 33-2 TopLink Indirection"

TopLink supports the following types of indirection:

- Value Holder Indirection

- Transparent Indirect Container Indirection

- Proxy Indirection

When using indirection with EJB, the version of EJB and application server you use affects how indirection is configured and what types of indirection are applicable (see "Indirection and EJB").

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

For information on configuring indirection, see "Configuring Indirection".

### 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 33-3 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 33-3 Address Object Not Read

Description of "Figure 33-3 Address Object Not Read"

The first time the address is accessed, as in Figure 33-4, the `ValueHolder` reads and returns the `Address` object.

Figure 33-4 Initial Request

Description of "Figure 33-4 Initial Request"

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

Figure 33-5 Subsequent Requests

Description of "Figure 33-5 Subsequent Requests"

If you are using method access ("Configuring Method Accessing"), 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 more information, see "Configuring ValueHolder Indirection With Method Accessing".

### Transparent Indirect Container Indirection

Transparent indirect container (see "Configuring Container Policy") 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`

TopLink 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`.

### Proxy Indirection

Introduced in JDK 1.3, the Java class `Proxy` lets you to use dynamic proxy objects as place-holders for a defined interface. Certain TopLink mappings (see Table 35-4) can be configured to use proxy indirection, which gives you the benefits of TopLink indirection without the need to include TopLink 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 ("Configuring 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 "Proxy Indirection Restrictions").

To configure proxy indirection, you can use TopLink Workbench (see "Using TopLink Workbench") or Java in an amendment method (see "Configuring Proxy Indirection").

#### 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.

For example:

    UnitOfWork uow = session.acquireUnitOfWork();
    Employee emp = (Employee)session.readObject(Employee.class);

    // Register the source object
    Employee empClone = (Employee)uow.registerObject(emp);

    // All of source object's relationships are cloned when source object is cloned
    Address addressClone = empClone.getAddress();
    addressClone.setCity("Toronto");

For more information about clones and the unit of work, see Chapter 100, "Understanding TopLink Transactions".

### Indirection and EJB

When using indirection with EJB, how TopLink handles indirection depends on the EJB version and application server you are using.

In addition, you cannot use proxy indirection (see "Proxy Indirection") for relationships to an EJB because EJB do not directly implement their remote or local interfaces.

When using indirection with an EJB that your application serializes, you must consider the effect of any untriggered indirection objects at deserialization time (see "Indirection, Serialization, and Detachment").

#### EJB 3.0 CMP and OC4J

When using EJB 3.0 CMP with OC4J, if you specify the `@Bean` annotation attribute `fetch=lazy`, TopLink uses bytecode weaving to automatically configure the usage of value holder indirection (see "Value Holder Indirection") for all container-managed relationships (CMRs).

#### EJB 2.n CMP

When using EJB 2.n CMP with any of the application servers for which TopLink provides CMP integration (see "Application Server Support"), TopLink uses code generation to automatically configure the usage of value holder indirection ("Value Holder Indirection") for all CMRs.

#### EJB 1.n CMP and BMP

When using EJB 1.n CMP or BMP, the usage of indirection is up to the application.

### Indirection, Serialization, and Detachment

When using indirection, 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 may appear as null values at deserialization time. This section describes how to address this depending on the EJB version and application server you are using.

For more information on serialization and TopLink, see "Merging Changes in Working Copy Clones".

#### EJB 3.0 CMP and OC4J

When using EJB 3.0 CMP with OC4J, indirection does not affect EJB passivation and activation nor does it affect detachment from and attachment to a persistence manager within the same JVM.

However, when you serialize an indirection-enabled EJB 3.0 beans from one JVM to another, (for example, from server to client), untriggered indirection objects appear as null values at deserialization time. To avoid this, configure your client to use the same Java agent that OC4J uses (see "Configuring ValueHolder Indirection With EJB 3.0 on OC4J").

#### EJB 1.n and 2.n CMP

When using EJB 1.n or 2.n CMP with any of the application servers for which TopLink provides CMP integration (see "Application Server Support"), indirection does not affect EJB passivation and activation within the same JVM.

However, when you serialize an indirection-enabled EJB 1.n or 2.n EJB from one JVM to another (for example, from server to client), untriggered indirection objects appear as null values at deserialization time. You must code your client to handle this scenario and to distinguish between an attribute that is `null` because it was null in the data source, and an attribute that is null because of an untriggered indireciton object.

## Method Accessors and Attribute Accessors

By default, TopLink uses direct access to access public attributes. Using TopLink, you can configure field access at the project level (see "Configuring Mapped Field Access at the Project Level") and at the method level ("Configuring Method Accessing").

## Mapping Converters and Transformers

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

- Serialized Object Converter

- Type Conversion Converter

- Object Type Converter

- Simple Type Translator

- Transformation Mappings

Note: You can use the mapping converters and transformers regardless of whether your data source is relational or nonrelational.

### Serialized Object Converter

The serialized object converter is an extension of direct and direct collection mappings that lets you 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 33-6 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 33-6 Serialized Object Converter (relational)

Description of "Figure 33-6 Serialized Object Converter (relational)"

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

Figure 33-7 Serialized Object Converter (nonrelational)

Description of "Figure 33-7 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.

For more information, see "Configuring a Serialized Object Converter".

### Type Conversion Converter

The type conversion converter is an extension of direct and direct collection mappings that lets you explicitly map a data source type to a Java type. 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 33-8 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 33-8 Type Conversion Mapping (relational)

Description of "Figure 33-8 Type Conversion Mapping (relational) "

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

Figure 33-9 Type Conversion Mapping (nonrelational)

Description of "Figure 33-9 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.

TopLink uses the `NCharacter`, `NClob` and `NString` types in the `oracle.toplink.platform.database.oracle` package as the converter data type to support the `NCHAR`, `NCLOB` and `NVARCHAR2` types. TopLink 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 "Transformation Mappings").

For more information, see "Configuring a Type Conversion Converter".

### Object Type Converter

The object type converter is an extension of direct and direct collection mappings that lets you match a fixed number of XML values to Java objects. Use this converter when the values in the schema differ from those in Java.

Figure 33-10 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`, TopLink stores it in the XML element as `F`.

Figure 33-10 Object Type XML Converter

Description of "Figure 33-10 Object Type XML Converter"

For more information, see "Configuring an Object Type Converter".

### Simple Type Translator

The simple type translator is an extension of direct and direct collection mappings that lets you automatically translate an XML element value to an appropriate Java type based on the element's `<type>` attribute as defined in your XML schema.

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

Using a simple type translator, 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 TopLink as do specific object attributes such as `java.lang.Integer` or `java.util.Calendar`.

Figure 33-11 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. The simple type translator adds the type information to the resulting document to preserve the typing.

Figure 33-11 Simple Type Translator

Description of "Figure 33-11 Simple Type Translator "

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

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

For more information, see "Configuring a Simple Type Translator".

#### Default Read Conversions

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

Table 33-2 Simple Type Translator 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

#### Default Write Conversions

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

Table 33-3 Simple Type Translator Write Conversions

Java Type | Schema Type
--- | ---
Byte[] | hexBinary
BigInteger | integer
Boolean | boolean
Byte | byte
Calendar | dateTime
Gregorian_Calendar | dateTime
Double | double
Float | float
Integer | int
Long | long
int | int
short | short
String | string

### 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 (see "Configuring Attribute Transformer"): performs the object attribute transformation at read (unmarshall) time

- field transformer (see "Configuring Field Transformer Associations"): performs the object attribute-to-field transformation at write (marshal) 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 the following:

- "Transformation Mapping"

- "EIS Transformation Mapping"

- "XML Transformation Mapping"

## Mappings and XPath

TopLink uses XPath statements to efficiently map the attributes of a Java object in EIS mappings to XML records and in XML mappings to XML documents. When you create such a mapping, you can specify the following:

- XPath by Position

- XPath by Path and Name

- XPath by Name

- Self XPath

### XPath by Position

In a relational database table, columns are uniquely identified by name. In an XML document, elements are uniquely identified by name and position. Figure 33-12 illustrates mapping to an XML document in which the first instance of the `street` element stores apartment information and the second instance of the `street` element stores street information. Figure 33-12 shows that TopLink XML mappings preserve the order in which mappings are persisted and allow you to map Java object attributes to XML elements by position using an XPath like `street[2]/text()`.

Other XML technologies only recognize the name of XML elements (not their position) and force you to store the simple values from elements with the same name in a collection.

Figure 33-12 Mapping to an XML Document by Position

Description of "Figure 33-12 Mapping to an XML Document by Position"

### XPath by Path and Name

In an XML document, attributes and elements are uniquely identified by a combination of name and path. Figure 33-13 illustrates that TopLink XML mappings can uniquely identify an XML element by name and path using an XPath such as `item/name/text()`. TopLink does not require a formal object relationship between XML elements `lines` and `item`.

Other XML technologies force you to provide an object relationship for every level of nesting, resulting in the inclusion of many XML elements and classes simply to organize the data to satisfy this restriction. This produces an unnecessarily large object model that does not properly reflect the domain space.

Figure 33-13 Mapping to an XML Document by Path and Name

Description of "Figure 33-13 Mapping to an XML Document by Path and Name"

### XPath by Name

For simple XML documents, TopLink XML mappings can correctly place data in an XML document given an XPath of only an attribute or element name.

Figure 33-14 illustrates mapping to a simple XML document by name. You can map Java object attribute `name` to XML attribute `name` by specifying an XPath of only `@NAME`. Similarly, you can map Java object attribute `age` to XML text node `AGE` by specifying an XPath of only `AGE`.

Figure 33-14 Mapping to a Simple XML Document by Name

Description of "Figure 33-14 Mapping to a Simple XML Document by Name"

Specifying an XPath by name provides the worst performance of the XPath mapping options. Oracle recommends that you use XPath by position (see "XPath by Position") or XPath by path and name (see "XPath by Path and Name") instead.

### Self XPath

For composite relationships, TopLink XML mappings can place data in the parent's element rather than an element nested within it given the self XPath (`"."`).

Figure 33-15 illustrates mapping to an XML document using the self XPath.

Figure 33-15 Mapping to a XML Document Using Self XPath

Description of "Figure 33-15 Mapping to a XML Document Using Self XPath"

Using the self XPath, you can make TopLink perform all read and write operations in the parent's element and not an element nested within it (see "Mappings and the jaxb:class Customization").

## Mappings and xsd:list and xsd:union Types

TopLink supports mapping to `xsd:list` and `xsd:union` types in EIS mappings to XML records and XML mappings to XML documents as Table 33-4 shows.

Table 33-4 TopLink Support for xsd:list and xsd:union Types

XSD | EIS Direct Mapping XML Direct Mapping | EIS Composite Direct Collection Mapping XML Composite Direct Collection Mapping
--- | --- | ---
Mapping an xsd:union Type |  |
Mapping an xsd:list Type |  |
Mapping a List of Unions |  |
Mapping a Union of Lists |  |
Mapping a Union of Unions |  |

### Mapping an xsd:union Type

Use an `EISDirectMapping` (with XML records) or an `XMLDirectMapping` to map a Java attribute to an `xsd:union` type, such as:

        <xsd:simpleType name="size-type">
            <xsd:union memberTypes="xsd:decimal xsd:string"/>
        </xsd:simpleType>

When TopLink marshalls (writes) an object to XML, it uses its default conversion pairs to convert from the Java type to the appropriate `xsd` type.

In the case where the `memberTypes` map to the same Java type, TopLink marshalls using the first `memberType` in the union which allows a successful conversion. For example, if you map a Java type of `byte[]` to an `xsd:union` with `memberTypes` of `hexBinary` and `base64Binary`, then TopLink marshalls using the first `memberType`: `hexBinary`.

You can customize the default conversion pairs to control the Java type to `xsd` type conversion using `XMLField` method `addConversion` and configuring your mapping with that `XMLField` using `EISDirectMapping` or `XMLDirectMapping` method `setField`. For example, if the `memberTypes` were `xsd:date` and `xsd:time` and the Java attribute was of type `java.util.Date` instead of the JAXB 1.0 standard `java.util.Calendar`, you can modify the conversion pair for `xsd:date` to be `java.util.Date`.

When TopLink unmarshalls (reads) XML into an object, it tries each `memberType` in the order specified in the XSD until the first successful conversion is made.

If your XML document specifies the `xsi:type` attribute on an element, then TopLink converts according to the `xsi:type` instead of trying the `memberTypes`.

For more information, see "Mapping to a Union Field With an XML Direct Mapping". The same applies to an `EISDirectMapping` with XML records (see "EIS Direct Mapping").

### Mapping an xsd:list Type

You can map a Java attribute to an `xsd:list` type, such as:

    <xsd:simpleType name="sizes">
        <xsd:list itemType="xsd:int"/>
    </xsd:simpleType>

If you represent the `xsd:list` in your object model as a Java `List` type, use an `EISCompositeDirectCollectionMapping` (with XML records) or an `XMLCompositeDirectCollectionMapping` and use mapping method `useCollectionClass` to specify the `List` type of the Java attribute.

If you represent the list in your object model as a `String` of white space delimited tokens (for example, `"aaa bbb ccc"`), use an `EISDirectMapping` (with XML records) or an `XMLDirectMappng` to map this Java attribute to an `xsd:list` (for example, `<item>aaa bbb ccc</item>`).

In either case, you can configure whether or not the mapping unmarshalls (writes) the list to a single node, like `<item>aaa bbb ccc</item>`, or to multiple nodes, such as the following:

    <item>aaa</item>
    <item>bbb</item>
    <item>ccc</item>

For more information on mapping to an `xsd:list` type using an `XMLCompositeDirectCollectionMapping`, see:

- "Mapping to a Single Text Node With an XML Composite Direct Collection Mapping"

- "Mapping to a Single Attribute With an XML Composite Direct Collection Mapping"

- "Specifying the Content Type of a Collection With an XML Composite Direct Collection Mapping"

The same applies to an `EISCompositeDirectCollectionMapping` (with XML records).

For more information about mapping to an `xsd:list` type using an `XMLDirectMapping`, see "Mapping to a List Field""Mapping to a List Field With an XML Direct Mapping". The same applies to an `EISDirectMapping` with XML records (see "EIS Direct Mapping").

### Mapping a List of Unions

Use an `EISCompositeDirectCollectionMapping` (with XML records) or an `XMLCompositeDirectCollectionMapping` to map a Java attribute to an `xsd:list` that contains `xsd:union` types, such as:

    <xsd:element name="listOfUnions" type="listOfUnions"/>
        <xsd:simpleType name="listOfUnions">
            <xsd:list>
                <xsd:simpleType>
                    <xsd:union memberTypes="xsd:date xsd:integer"/>
                </xsd:simpleType>
            </xsd:list>
        </xsd:simpleType>

When TopLink marshalls (writes) an object to XML, it does not rely on a single `xsd:list` `itemType`. Instead, for each item in the list, TopLink tries each `memberType` until the first successful conversion.

For more information, see "Mapping to a List of Unions With an XML Composite Direct Collection Mapping". The same applies to an `EISCompositeDirectCollectionMapping` with XML records (see "EIS Composite Direct Collection Mapping").

### Mapping a Union of Lists

You can map a Java attribute to an `xsd:union` type whose `memberTypes` are `xsd:list` types where each `xsd:list` contains items of a single type, such as:

    <xsd:element name="listOfUnions" type="UnionOfLists"/>
        <xsd:simpleType name="UnionOfLists">
            <xsd:union memberTypes="xsd:double">
                <xsd:simpleType>
                    <xsd:list itemType="xsd:date"/>
                </xsd:simpleType>
                <xsd:simpleType>
                    <xsd:list itemType="xsd:integer"/>
                </xsd:simpleType>
            </xsd:union>
        </xsd:simpleType>

Note that in this example, valid XML documents contain either all `xsd:double`, all `xsd:date`, or all `xsd:integer` values.

If you represent the list in your object model as a `String` of white space delimited tokens (for example, `"aaa bbb ccc"`), use an `EISDirectMapping` (with XML records) or an `XMLDirectMappng` to map this Java attribute to an `xsd:list` (for example, `<item>aaa bbb ccc</item>`).

If you represent the list in your object model as a Java `List` type, use an `EISCompositeDirectCollectionMapping` (with XML records) or an `XMLCompositeDirectCollectionMapping`.

For more information, see the following:

- "Mapping to a Union of Lists With an XML Direct Mapping". The same applies to an `EISDirectMapping` with XML records (see "EIS Direct Mapping").

- "Mapping to a Union of Lists With an XML Composite Direct Collection Mapping". The same applies to an `EISCompositeDirectCollectionMapping` with XML records (see "EIS Composite Direct Collection Mapping").

### Mapping a Union of Unions

Use an `EISDirectMapping` (with XML records) or an `XMLDirectMapping` to map a Java attribute to an `xsd:union` that contains `xsd:union` types, such as:

    <xsd:simpleType name="UnionOfUnions">
        <xsd:union>
            <xsd:simpleType>
                <xsd:union>
                  <xsd:simpleType>
                    <xsd:list itemType="xsd:date"/>
                  </xsd:simpleType>
                  <xsd:simpleType>
                    <xsd:list itemType="xsd:integer"/>
                  </xsd:simpleType>
                  </xsd:union>
          </xsd:simpleType>
          <xsd:simpleType>
                <xsd:union>
                  <xsd:simpleType>
                    <xsd:list itemType="xsd:string"/>
                  </xsd:simpleType>
                  <xsd:simpleType>
                    <xsd:list itemType="xsd:float"/>
                  </xsd:simpleType>
                  </xsd:union>
          </xsd:simpleType>
        </xsd:union>
    </xsd:simpleType>

Note that in this example, valid XML documents may contain any of `xsd:date`, `xsd:integer`, `xsd:string`, or `xsd:float`.

For more information, see "Mapping to a Union of Unions With an XML Direct Mapping". The same applies to an `EISDirectMapping` with XML records (see "EIS Direct Mapping").

## Mappings and the jaxb:class Customization

Using the `jaxb:class` customization, you can declaratively specify an application-specific subclass of a schema-derived implementation class. This lets you write your own classes that extend JAXB's generated implementation classes. The JAXB runtime binding framework can then access your subclasses.

When you create an EIS composite object mapping to XML records or an XML composite object mapping to XML documents, you can configure the mapping's XPath ("Configuring XPath") to accommodate `jaxb:class` customizations with the following XSD structures:

- all, choice, or sequence Structure

- group Structure

- sequence or choice Structure Containing a group

- group Structure Containing a sequence or choice

- group Structure Containing a group

When mapping to `jaxb:class` customized structures, consider the limitations of TopLink support for this customization (see "Limitations of jaxb:class Customization Support").

### all, choice, or sequence Structure

You can use the `jaxb:class` customization with an `all`, `choice`, or `sequence` structure. Example 33-1 shows a `jaxb:class` customization of an `all` structure.

Example 33-1 jaxb:class Customization of an all Structure

    <xsd:element name="employee">
        <xsd:complexType>
            <xsd:all>
                <xsd:annotation>
                    <xsd:appinfo>
                        <jaxb:class name="period"/>
                    </xsd:appinfo>
                </xsd:annotation>
                <xsd:element name="startDate" type="xsd:date"/>
                <xsd:element name="endDate" type="xsd:date"/>
            </xsd:all>
        </xsd:complexType>
    </xsd:element>

This directs the JAXB compiler to create an inner class named `Period` in the owning element's class for the `all` structure. Use an `EISCompositeObjectMapping` (with XML records) or an `XMLCompositeObjectMapping` to map a Java attribute to this inner class.

For more information, see "XML Composite Object Mapping". The same applies to an `EISCompositeObjectMapping` with XML records (see "EIS Composite Object Mapping").

### group Structure

You can use the `jaxb:class` customization with a `group` structure as Example 33-2 shows.

Example 33-2 jaxb:class Customization of a group Structure

    <xsd:group name="G1">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="period"/>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="startDate" type="xsd:date"/>
            <xsd:element name="endDate" type="xsd:date"/>
        </xsd:sequence>
    </xsd:group>

    <xsd:element name="employee">
        <xsd:complexType>
            <xsd:group ref="G1"/>
        </xsd:complexType>
    </xsd:element>

This directs the JAXB compiler to create an external wrapper class named `Period` for the `group` structure. Use an `EISCompositeObjectMapping` (with XML records) or an `XMLCompositeObjectMapping` to map a Java attribute to this external wrapper class.

For more information, see "XML Composite Object Mapping". The same applies to an `EISCompositeObjectMapping` with XML records (see "EIS Composite Object Mapping").

### sequence or choice Structure Containing a group

You can use the `jaxb:class` customization with a `sequence` or `choice` structure that contains a `group`. Example 33-3 shows a `jaxb:class` customization of a `sequence` structure containing a `group` structure.

Example 33-3 jaxb:class Customization of a sequence Structure Containing a group

    <xsd:element name="employee">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:annotation>
                    <xsd:appinfo>
                        <jaxb:class name="EmploymentInfo"/>
                    </xsd:appinfo>
                </xsd:annotation>
                <xsd:element name="id" type="xsd:int"/>
                <xsd:group ref="G1"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

    <xsd:group name="G1">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="Period"/>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="startDate" type="xsd:date"/>
            <xsd:element name="endDate" type="xsd:date"/>
        </xsd:sequence>
    </xsd:group>

This directs the JAXB compiler to create an inner class named `EmploymentInfo` in the owning element's class for the `sequence` structure and an external wrapper class named `Period` for the `group` structure. The inner class references the external wrapper class. Use an `EISCompositeObjectMapping` (with XML records) or an `XMLCompositeObjectMapping` to map a Java attribute to this inner class.

For more information, see "XML Composite Object Mapping". The same applies to an `EISCompositeObjectMapping` with XML records (see "EIS Composite Object Mapping").

### group Structure Containing a sequence or choice

You can use the `jaxb:class` customization with a `group` structure that contains a `sequence` or `choice`. Example 33-4 shows a `jaxb:class` customization of a `group` structure containing a `sequence` structure.

Example 33-4 jaxb:class Customization of a group Structure Containing a sequence

    <xsd:group name="G1">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="EmploymentInfo"/>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:annotation>
                <xsd:appinfo>
                    <jaxb:class name="Period"/>
                </xsd:appinfo>
            </xsd:annotation>
            <xsd:element name="startDate" type="xsd:date"/>
            <xsd:element name="endDate" type="xsd:date"/>
        </xsd:sequence>
    </xsd:group>

    <xsd:element name="employee">
        <xsd:complexType>
            <xsd:sequence>
                <xsd:element name="id" type="xsd:int"/>
                <xsd:group ref="G1"/>
            </xsd:sequence>
        </xsd:complexType>
    </xsd:element>

This directs the JAXB compiler to create an external wrapper class named `EmploymentInfo` for the `group` structure and an inner class named `Period` in the external wrapper class for the `sequence` structure. The owning element references the external wrapper class. Use an `EISCompositeObjectMapping` (with XML records) or an `XMLCompositeObjectMapping` to map a Java attribute to this external wrapper class.

For more information, see "XML Composite Object Mapping". The same applies to an `EISCompositeObjectMapping` with XML records (see "EIS Composite Object Mapping").

### group Structure Containing a group

You can use the `jaxb:class` customization with a `group` structure that contains another `group` structure as Example 33-5 shows.

Example 33-5 jaxb:class Customization of a group Structure Containing a group

    <xsd:group name="G1">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="EmploymentInfo"/>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="id" type="xsd:int"/>
            <xsd:group ref="G2"/>
        </xsd:sequence>
    </xsd:group>

    <xsd:group name="G2">
        <xsd:annotation>
            <xsd:appinfo>
                <jaxb:class name="Period"/>
            </xsd:appinfo>
        </xsd:annotation>
        <xsd:sequence>
            <xsd:element name="startDate" type="xsd:date"/>
            <xsd:element name="endDate" type="xsd:date"/>
        </xsd:sequence>
    </xsd:group>

    <xsd:element name="employee">
        <xsd:complexType>
            <xsd:group ref="G1"/>
        </xsd:complexType>
    </xsd:element>

This directs the JAXB compiler to create a wrapper class named `EmploymentInfo` for the `group` structure that the owning element's class references and another wrapper class named `Period` for the `group` structure that the `EmploymentInfo` class references. Use an `EISCompositeObjectMapping` (with XML records) or an `XMLCompositeObjectMapping` to map a Java attribute to these wrapper classes.

For more information, see "XML Composite Object Mapping". The same applies to an `EISCompositeObjectMapping` with XML records (see "EIS Composite Object Mapping").

### Limitations of jaxb:class Customization Support

When mapping to jaxb:class customized structures, consider the following limitations:

- Unbounded structures are not supported.

- Partial validation is not supported.

- When mapping sequence elements to a composite object, the XML schema must order the elements so that the elements you map to the composite object are kept together.

  The `sequence` structure forces all elements to occur in the order in which they are specified in the XML schema. Consider the XML schema shown in Example 33-6. A valid XML instance must contain the sequence elements in the specified order:

  `street`, `customerName`, `city`

  In this example, you want to map the `customerName` attribute with a direct mapping and you want to map the `street` and `city` attributes to a composite `Address` object. Depending on the order in which you define the mappings, TopLink will marshall invalid XML document instances in the order

  `customerName`, `street`, `city`

  or

  `street`, `city`, `customerName`.

  Example 33-6 XML Schema With Unsupported Sequence Element Order

      <xs:element name="customer">
          <xs:complexType>
              <xs:sequence>
                  <xs:element name="street" type="xs:string"/>
                  <xs:element name="customerName" type="xs:string" />
                  <xs:element name="city" type="xs:string"/>
              </xs:sequence>
          </xs:complexType>
      </xs:element>

  To correct this problem, modify the XML schema to keep the elements you want to map to the composite object together (see Example 33-7) and define the mappings in the order specified by the XML schema.

  Example 33-7 XML Schema With Supported Sequence Element Order

      <xs:element name="customer">
          <xs:complexType>
              <xs:sequence>
                  <xs:element name="customerName" type="xs:string" />
                  <xs:element name="street" type="xs:string"/>
                  <xs:element name="city" type="xs:string"/>
              </xs:sequence>
          </xs:complexType>
      </xs:element>

## Mappings and JAXB Typesafe Enumerations

JAXB binds a typesafe enumeration class to a named simple type definition with a `basetype` that derives from `xsd:NCName` and has `enumeration` facets (see Example 33-8).

Example 33-8 Schema Fragment with Typesafe Enumeration Declaration

    <simpleType name="NISTSchema-NCName-enumeration-1-Type">
        <restriction base="NCName">
            <enumeration value="qbandwidth-and.software-use.too"/>
            <enumeration value="_effort-disseminate_and-devices.com"/>
        </restriction>
    </simpleType>

You can map a Java attribute to such an enumeration using the `JAXBTypesafeEnumConverter` with an `EISDirectMapping` or `EISCompositeDirectCollectionMapping` with XML records or with an `XMLDirectMapping` or `XMLCompositeDirectCollectionMapping` with XML documents.

TopLink Workbench does not support the `JAXBTypesafeEnumConverter` directly: to configure a mapping with this converter, you must use a descriptor amendment method (see "Configuring a JAXB Typesafe Enumeration Converter").

If you create a project and object model using the TopLink JAXB compiler (see "Creating an XML Project From an XML Schema"), the compiler will create the type safe enumeration class and a class with descriptor amendment methods and register the required amendment methods automatically (see "Typesafe Enumeration Converter Amendment Method DescriptorAfterLoads Class").