Oracle® TopLink Developer's Guide 10g Release 3 (10.1.3.1.0) Part Number B28218-01 |
|
|
View PDF |
This chapter describes how to configure TopLink mappings.
Table 32-1 lists the types of TopLink mappings that you can configure and provides a cross-reference to the type-specific chapter that lists the configurable options supported by that type.
Table 32-1 Configuring TopLink Mappings
Table 32-2 lists the configurable options shared by two or more TopLink mapping types.
For more information, see the following:
Table 32-2 lists the configurable options shared by two or more TopLink mapping types. In addition to the configurable options described here, you must also configure the options described for the specific Mapping Types, as shown in Table 32-1
Table 32-2 Common Mapping Options
Option | Type | TopLink Workbench |
Java |
---|---|---|---|
"Configuring Read-Only Mappings" |
Basic |
||
|
Basic |
||
|
Basic |
||
"Configuring a Default Null Value at the Mapping Level" |
Basic |
||
"Configuring Method Accessing" |
Advanced |
||
"Configuring Private or Independent Relationships" |
Advanced |
||
"Configuring Mapping Comments" |
Advanced |
||
"Configuring a Serialized Object Converter" |
Advanced |
||
"Configuring a Type Conversion Converter" |
Advanced |
||
"Configuring an Object Type Converter" |
Advanced |
||
"Configuring a Simple Type Translator" |
Advanced |
||
"Configuring a JAXB Typesafe Enumeration Converter" |
Advanced |
|
|
"Configuring Container Policy" |
Advanced |
||
"Configuring Attribute Transformer" |
Advanced |
||
"Configuring Field Transformer Associations" |
Advanced |
||
"Configuring Mutable Mappings" |
Advanced |
||
"Configuring Bidirectional Relationship" |
Advanced |
||
"Configuring the Use of a Single Node" |
Advanced |
Mappings that are read-only will not be affected during insert, update, and delete operations.
Use read-only mappings when multiple attributes in an object map to the same fields in the database but only one of the mappings can write to the field.
You can also use read-only mappings with bi-directional many-to-many mappings to designate which mapping will be responsible for updating the many-to-many join table.
Mappings defined for the write-lock or class indicator field must be read-only, unless the write-lock is configured not to be stored in the cache or the class indicator is part of the primary key.
Use read-only mappings only if specific mappings in a descriptor are read-only. If the entire descriptor is read-only, use the descriptor-level setting (see "Configuring Read-Only Descriptors").
Table 32-3 summarizes which mappings support this option.
To specify a mapping as read-only, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-1 General Tab, Read-Only Option
Select the Read-Only option to set the mapping to be read-only and not affected during update and delete operations.
Use the following DatabaseMapping
methods to configure the read access of a mapping:
readOnly
–configures mapping read access to read-only
readWrite
–configures mapping read access to read and write (default)
Example 32-1 shows how to use these methods with a class that has a read-only attribute named phones
.
By default, when TopLink retrieves a persistent object, it retrieves all of the dependent objects to which it refers. When you enable indirection for an attribute mapped with a relationship mapping, TopLink uses an indirection object as a placeholder 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 refers.
Oracle strongly recommends using indirection for all relationship mappings. Not only does this allow you to optimize data source access, but it also allows TopLink to optimize the unit of work processing, cache access, and concurrency.
Table 32-4 summarizes which mappings support this option.
Table 32-4 Mapping Support for Indirection
In general, Oracle recommends that you use value holder indirection (see "Value Holder Indirection") for one-to-one mappings and transparent indirect container indirection (see "Transparent Indirect Container Indirection") for collection mappings. Enable indirection for transformation mappings if the execution of the transformation is a resource-intensive task (such as accessing a database, in a relational project).
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 more information, see "Indirection".
To complete the indirection options on a mapping's General tab use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-2 General Tab, Indirection Options
Use the following information to complete the Indirection fields on the tab:
Field | Description |
---|---|
Use Indirection | Specify if this mapping uses indirection. |
ValueHolder | Specify that the mapping uses Value Holder indirection. See "Value Holder Indirection" for more information. |
Proxy | Specify that the mapping uses Proxy indirection. See "Proxy Indirection" for more information. |
When creating mappings through the Java API, all foreign reference mappings default to using value-holder indirection and all transformation mappings default to not using indirection.
To disable indirection use ForeignReferenceMapping
method dontUseIndirection
.
To enable value holder indirection, use ForeignReferenceMapping
method useBasicIndirection
.
To enable transparent container indirection, use one of the following CollectionMapping
methods:
useTransparentCollection
useTransparentList
useTransparentMap
useTransparentSet
To enable proxy indirection, use ObjectReferenceMapping
method useProxyIndirection
.
This section provides additional information on the following:
Instances of oracle.toplink.mappings.ForeignReferenceMapping
and oracle.toplink.mappings.foundation.AbstractTransformationMapping
provide the useBasicIndirection
method to configure a mapping to an attribute that you code with an oracle.toplink.indirection.ValueHolderInterface
between it and the real object.
If the attribute is of a Collection
type (such as a Vector
), then you can either use an IndirectContainer
(see "Configuring IndirectContainer Indirection") or define the ValueHolder
in the constructor as follows:
addresses = new ValueHolder(new Vector());
Example 32-2 illustrates the Employee
class using ValueHolder
indirection. The class definition conceals the use of ValueHolder within the existing getter and setter methods.
Example 32-2 Class Using ValueHolder Indirection
public class Employee {
protected ValueHolderInterface address;
// Initialize ValueHolders in constructor
public Employee() {
address = new ValueHolder();
}
public Address getAddress() {
return (Address) this.addressHolder.getValue();
}
public void setAddress(Address address) {
this.addressHolder.setValue(address);
}
}
Example 32-3 shows how to configure a one-to-one mapping to the address
attribute.
Example 32-3 Mapping Using ValueHolder Indirection
OneToOneMapping mapping = new OneToOneMapping(); mapping.useBasicIndirection(); mapping.setReferenceClass(Employee.class); mapping.setAttributeName("address");
The application uses Employee
methods getAddress
and setAddress
to access the Address
object. Because basic indirection is enabled, TopLink expects the persistent fields to be of type ValueHolderInterface
.
If you are using ValueHolder
indirection with method accessing (see "Configuring Method Accessing"), in addition to changing your attributes types in your Java code to ValueHolderInterface
, you must also provide TopLink with two pairs of getter and setter methods:
getter and setter of the indirection object that are registered with the mapping and used only by TopLink. They include a get
method that returns an instance that conforms to ValueHolderInterface
, and a set
method that accepts one argument that conforms to the same interface.
getter and setter of the actual attribute value used by the application
Example 32-2 illustrates the Employee
class using ValueHolder
indirection with method access. The class definition is modified so that the address
attribute of Employee
is a ValueHolderInterface
instead of an Address
, and appropriate getter and setter methods are supplied.
Example 32-4 Class Using ValueHolder Indirection with Method Accessing
public class Employee { protected ValueHolderInterface address; // Initialize ValueHolders in constructor public Employee() { address = new ValueHolder(); } // getter and setter registered with the mapping and used only by TopLink public ValueHolderInterface getAddressHolder() { return address; } public void setAddressHolder(ValueHolderInterface holder) { address = holder; } // getter and setter methods used by the application to access the attribute public Address getAddress() { return (Address) address.getValue(); } public void setAddress(Address theAddress) { address.setValue(theAddress); } }
Example 32-3 shows how to configure a one-to-one mapping to the address
attribute.
Example 32-5 Mapping Using ValueHolder Indirection with Method Accessing
OneToOneMapping mapping = new OneToOneMapping(); mapping.useBasicIndirection(); mapping.setReferenceClass(Employee.class); mapping.setAttributeName("address"); mapping.setGetMethodName("getAddressHolder"); mapping.setSetMethodName("setAddressHolder");
The application uses Employee
methods getAddress
and setAddress
to access the Address
object. Because basic indirection is enabled, TopLink uses Employee
methods getAddressHolder
and setAddressHolder
methods when performing persistence operations on instances of Employee
.
When using indirection with EJB 3.0 persistence on OC4J (see "Indirection and EJB"), if your application serializes any indirection-enabled enterprise bean (see "Indirection, Serialization, and Detachment"), then, to preserve untriggered indirection objects on deserialization, configure your client to use the same Java agent that OC4J uses, as follows:
Include the following JAR files (from <
TOPLINK_HOME
>\jlib
) in your client classpath:
toplink.jar
toplink-agent.jar
asm.jar
asm-util.jar
ejb3-toplink-session.xml
(and whatever project deployment XML it refers to)
Add the following argument to the Java command line you use to start your client:
-javaagent:toplink-agent.jar
Instances of oracle.toplink.mappings.ForeignReferenceMapping
and oracle.toplink.mappings.foundation.AbstractTransformationMapping
provide the useContainerIndirection
method to configure a mapping to an attribute that you code with an oracle.toplink.indirection.IndirectContainer
between it and the real object.
Using an IndirectContainer
, a java.util.Collection
class can act as a TopLink indirection object: the Collection
will only read its contents from the database when necessary (typically, when a Collection
accessor is invoked). Without an IndirectContainer
, all members of the Collection
must be retrieved when the Collection
attribute is accessed.
Example 32-2 illustrates the Employee
class using IndirectContainer
indirection with method access. The class definition is modified so that the addresses
attribute of Employee
is an IndirectContainer
instead of an Address
es, and appropriate getter and setter methods are supplied. In this example, addresses
is a java.util.List
, so an instance of oracle.toplink.indirection.IndirectList
is used.
Example 32-6 Class Using IndirectContainer Indirection
public class Employee { protected IndirectList addresses; // Initialize ValueHolders in constructor public Employee() { addresses = new IndirectList(); } // getter and setter methods registered with the mapping and used by TopLink public ValueHolderInterface getAddressesHolder() { return addresses.getValueHolder(); } public void setAddressesHolder(ValueHolderInterface holder) { addresses = addresses.setValueHolder(holder); } // getter and setter methods used by the application to access the attribute public List getAddresses() { return (List) addresses.getValue(); } public void setAddresses(List newAddresses) { addresses.removeAll(); addresses.addAll(newAddresses); } }
Example 32-3 shows how to configure a one-to-one mapping to the addresses
attribute.
Example 32-7 Mapping Using IndirectContainer Indirection
OneToOneMapping mapping = new OneToOneMapping(); mapping.useBasicIndirection(); mapping.setReferenceClass(Employee.class); mapping.setAttributeName("addresses"); mapping.setGetMethodName("getAddressesHolder"); mapping.setSetMethodName("setAddressesHolder");
Example 32-8 illustrates an Employee
to Address
one-to-one relationship.
Example 32-8 Proxy indirection Examples
public interface Employee { public String getName(); public Address getAddress(); public void setName(String value); public void setAddress(Address value); . . . } public class EmployeeImpl implements Employee { public String name; public Address address; . . . public Address getAddress() { return this.address; } public void setAddress(Address value) { this.address = value; } } public interface Address { public String getStreet(); public void setStreet(String value); . . . } public class AddressImpl implements Address { public String street; . . . }
In Example 32-8, both the EmployeeImpl
and the AddressImpl
classes implement public interfaces (Employee
and Address
respectively). Therefore, because the AddressImpl
class is the target of the one-to-one relationship, it is the only class that must implement an interface. However, if the EmployeeImpl
is ever to be the target of another one-to-one relationship using transparent indirection, it must also implement an interface, as shown in the following example:
Employee emp = (Employee) session.readObject(Employee.class); System.out.println(emp.toString()); System.out.println(emp.getAddress().toString()); // Would print: [Employee] John Smith { IndirectProxy: not instantiated } String street = emp.getAddress().getStreet(); // Triggers database read to get Address information System.out.println(emp.toString()); System.out.println(emp.getAddress().toString()); // Would print: [Employee] John Smith { [Address] 123 Main St. }
Using proxy indirection does not change how you instantiate your own domain objects for an insert operation. You still use the following code:
Employee emp = new EmployeeImpl("John Smith"); Address add = new AddressImpl("123 Main St."); emp.setAddress(add);
TopLink uses XPath statements to map the attributes of a Java object to locations in an XML document. When you create an XML mapping or EIS mapping using XML records, you can specify the XPath based on any of the following:
Name
Position
Path and name
Table 32-5 summarizes which mappings support this option.
Table 32-5 Mapping Support for XPath
Footnote 1 When used with XML records only (see "Configuring Record Format").
Footnote 2 Supports the self XPath (".") so that the TopLink runtime performs all read and write operations in the parent's element and not an element nested within it (see "Mappings and the jaxb:class Customization").
Before you can select an XPath for a mapping, you must associate the descriptor with a schema context (see "Configuring Schema Context for an EIS Descriptor" or "Configuring Schema Context for an XML Descriptor").
For more information, see "Mappings and XPath".
Use this table to select the XPath for an XMl mapping or EIS mapping using XML records:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
If necessary, click the General tab. The General tab appears.
Figure 32-4 XPath Options for Composite Object Mappings
Click Browse and select the XPath to map to this attribute (see "Choosing the XPath").
For an EIS composite object mapping using XML records or an XML composite object mapping, you can choose one of the following:
Specify XPath: select the XPath to map to this attribute (see "Choosing the XPath").
Aggregate into parent element: select the self XPath ("."
) (see "Self XPath" ) so that the TopLink runtime performs all read and write operations in the parent's element, and not an element nested within it (see "Mappings and the jaxb:class Customization").
From the Choose XPath dialog box, select the XPath and click OK. TopLink Workbench builds the complete XPath name.
A default null value is the Java Object
type and value that TopLink uses instead of null
when TopLink reads a null value from a data source.
When you configure a default null value at the mapping level, TopLink uses it to translate in two directions:
When TopLink reads null
from the data source, it converts this null
to the specified type and value.
When TopLink writes or queries to the data source, it converts the specified type and value back to null
.
Table 32-6 summarizes which mappings support this option.
Table 32-6 Mapping Support for Default Null Values
Mapping | Using TopLink Workbench |
Using Java |
---|---|---|
|
||
|
|
|
|
|
|
|
||
|
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
|
Note: A default null value must be anObject . To specify a primitive value (such as int ), you must use the corresponding Object wrapper (such as Integer ). |
You can also use TopLink to set a default null value for all mappings used in a session (see "Configuring a Default Null Value at the Login Level").
To configure a default null value for a mapping, use this procedure.
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-6 General Tab, Default Null Value Options
Use the following information to complete the Default Null Value fields on the tab:
Field | Description |
---|---|
Default Null Value | Specify if this mapping contains a default value in the event that the data source is null . If selected, you must enter both the Type and Value of the default. |
Type | Select the Java type of the default value. |
Value | Enter the default value. |
To configure a mapping null value using Java API, use the AbstractDirectMapping
method setNullValue
.
For example:
// Defaults a null salary to 0
salaryMapping.setNullValue(new Integer(0));
By default, TopLink uses direct access to access public attributes. Alternatively, you can use getter and setter methods to access object attributes when writing the attributes of the object to the database, or reading the attributes of the object from the database. This is known as method access.
The attribute's visibility (public, protected, private, or package visibility) and the supported version of JDK may restrict the type of access that you can use.
Using private, protected or package variable or method access requires you to enable the Java reflect security setting. This is enabled by default in most application servers (see "Security Permissions"), but may need to be enabled explicitly in certain JVM configurations. If necessary, use the java.policy
file to grant ReflectPermission
to the entire application or the application's code base. For example:
grant{ permission java.lang.reflect.ReflectPermission; };
Oracle recommends using direct access whenever possible to improve performance and avoid executing any application-specific behavior while building objects.
Table 32-7 summarizes which mappings support this option.
For information on configuring method accessing at the project level, see "Configuring Mapped Field Access at the Project Level".
To complete the field access method for a mapping, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-7 General Tab, Method Accessing Options
Use the following information to complete the Method Accessing fields on this tab:
Field | Description |
---|---|
Method Accessing | Specify if this mapping uses specific accessor methods instead directly accessing public attributes. By default, this option is not selected (that is, the mapping uses direct access). |
Get Method | Select a specific get method. |
Set Method | Select a specific set method. |
To change the default access type used by all new mappings, use the Defaults tab on the project Editor window. See "Configuring Mapped Field Access at the Project Level" for more information.
Use the following DatabaseMapping
methods to configure the user-defined getters and setters that TopLink will use to access the mapped attribute:
For mappings not supported in TopLink Workbench, use the setGetMethodName
and setSetMethodName
methods to access the attribute through user-defined methods, rather than directly.
setGetMethodName
–set the String
name of the user-defined method to get the mapped attribute
setSetMethodName
–set the String
name of the user-defined method to set the mapped attribute
Example 32-9 shows how to use these methods with a class that has an attribute phones
and accessor methods getPhones
and setPhones
in an object-relational mapping.
In TopLink, object relationships can be either private or independent:
In a private relationship, the target object is a private component of the source object. The target object cannot exist without the source and is accessible only through the source object. Destroying the source object will also destroy the target object.
In an independent relationship, the source and target objects are public ones that exist independently. Destroying one object does not necessarily imply the destruction of the other.
Tip: TopLink automatically manages private relationships. Whenever an object is written to the database, any private objects it owns are also written to the database. When an object is removed from the database, any private objects it owns are also removed. Be aware of this when creating new systems, since it may affect both the behavior and the performance of your application. |
Table 32-8 summarizes which mappings support this option.
Table 32-8 Mapping Support for Private or Independent Relationships
To create a privately owned mapping, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-8 General Tab, Private Owned option
To create private ownership, select the Private Owned option.
For mappings not supported in TopLink Workbench, use the independentRelationship
(default), privateOwnedRelationship
, and setIsPrivateOwned
methods.
Example 32-9 shows how to use these methods with a class that has a privately owned attribute, phones
, in a mapping.
You can define a free-form textual comment for each mapping. You can use these comments however you whish: for example, to record important project implementation details such as the purpose or importance of a mapping.
Comments are stored in the TopLink Workbench project, in the TopLink deployment XML file. There is no Java API for this feature.
Table 32-9 summarizes which mappings support this option.
To add a comment for a mapping, use this procedure.
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Enter a comment that describes this mapping.
A serialized object converter can be used to store an arbitrary object or set of objects into a data source binary large object (BLOB) field. It uses the Java serializer so the target must be serializable.
For more information about the serialized object converter, see "Serialized Object Converter".
Table 32-10 summarizes which mappings support this option.
Table 32-10 Mapping Support for Serialized Object Converter
Mapping | Using TopLink Workbench |
Using Java |
---|---|---|
|
||
|
|
|
|
||
Object-Relational Array Mapping |
|
|
|
||
|
|
|
EIS Composite Direct Collection Mapping |
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
|
To create an serialized object direct mapping, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the Converter tab. The Converter tab appears.
Figure 32-10 Converter Tab, Serialized Object Converter Option
To specify a serialized object converter, select the Serialized Object Converter option.
You can set an oracle.toplink.converters.SerializedObjectConverter
on any instance of oracle.toplink.mappings.foundation.AbstractCompositeDirectCollectionMapping
using AbstractCompositeDirectCollectionMapping
method setValueConverter
as Example 32-11 shows.
Example 32-11 Configuring a SerializedObjectConverter in Java
// Create SerializedObjectConverter instance SerializedObjectConverter serializedObjectConvter = new SerializedObjectConverter(); // Set SerializedObjectConverter on ArrayMapping ArrayMapping arrayMapping = new ArrayMapping(); arrayMapping.setValueConverter(serializedObjectConvter); arrayMapping.setAttributeName("responsibilities"); arrayMapping.setStructureName("Responsibilities_t"); arrayMapping.setFieldName("RESPONSIBILITIES"); orDescriptor.addMapping(arrayMapping);
A type conversion converter is used to explicitly map a data source type to a Java type.
For more information about the type conversion converter, see "Type Conversion Converter".
Table 32-11 summarizes which mappings support this option.
Table 32-11 Mapping Support for Type Conversion Converter
Mapping | Using TopLink Workbench |
Using Java |
---|---|---|
|
||
|
|
|
|
||
Object-Relational Array Mapping |
|
|
|
||
|
|
|
EIS Composite Direct Collection Mapping |
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
|
To create an type conversion direct mapping, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the Converter tab. The Converter tab appears.
Select the Type Conversion Converter option.
Figure 32-11 Converter Tab, Type Conversion Converter Option
Use the following information to complete the Type Conversion Converter fields on the Converter tab:
Field | Description |
---|---|
Data Type | Select the Java type of the data in the data source. |
Attribute Type | Select the Java type of the attribute in the Java class. |
You can set an oracle.toplink.converters.TypeConversionConverter
on any instance of oracle.toplink.mappings.foundation.AbstractCompositeDirectCollectionMapping
using AbstractCompositeDirectCollectionMapping
method setValueConverter
as Example 32-12 shows.
Example 32-12 Configuring a TypeConversionConverter in Java
// Create TypeConversionConverter instance TypeConversionConverter typeConversionConverter = new TypeConversionConverter(); typeConversionConverter.setDataClass(); typeConversionConverter.setObjectClass(); // Set TypeConversionConverter on ArrayMapping ArrayMapping arrayMapping = new ArrayMapping(); arrayMapping.setValueConverter(typeConversionConverter); arrayMapping.setAttributeName("responsibilities"); arrayMapping.setStructureName("Responsibilities_t"); arrayMapping.setFieldName("RESPONSIBILITIES"); orDescriptor.addMapping(arrayMapping);
Configure the TypeConversionConverter
instance using the following API:
setDataClass(java.lang.Class dataClass)
–to specify the data type class
setObjectClass(java.lang.Class objectClass)
–to specify the object type class
An object type converter is used to match a fixed number of data source data values to Java object values. It can be used when the values in the data source and in Java differ.
For more information about the object type converter, see "Object Type Converter".
Table 32-12 summarizes which mappings support this option.
Table 32-12 Mapping Support for Object Type Converter
Mapping | Using TopLink Workbench |
Using Java |
---|---|---|
|
|
|
|
||
Object-Relational Array Mapping |
|
|
|
||
|
|
|
EIS Composite Direct Collection Mapping |
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
|
To add an object type converter to a direct mapping, use this procedure:
Select the mapping in the Navigator. Its properties appear in the Editor.
Click the Converter tab. The Converter tab appears.
Figure 32-12 Converter Tab, Object Type Converter
Use the following fields on the mapping's Converter tab to specify the object type converter options:
Field | Description |
---|---|
Data Type | Select the Java type of the data in the data source. |
Attribute Type | Select the Java type of the attribute in the Java class. |
Conversion Values | Click Add to add a new conversion value. Click Edit to modify an existing conversion value. Click Remove to delete an existing conversion value.
Use to specify the selected value as the default value. If TopLink retrieves a value from the database that is not mapped as a valid Conversion Value, the default value will be used. |
Data Value | Specify the value of the attribute in the data source. |
Attribute Value | Specify the value of the attribute in the Java class |
Default Attribute Value | Specify whether or not to use the selected value as the default value. If TopLink retrieves a value from the database that is not mapped as a valid Conversion Value, the default value will be used. |
You can set an oracle.toplink.converters.ObjectTypeConverter
on any instance of oracle.toplink.mappings.foundation.AbstractCompositeDirectCollectionMapping
using AbstractCompositeDirectCollectionMapping
method setValueConverter
as Example 32-13 shows.
Example 32-13 Configuring an ObjectTypeConverter in Java
// Create ObjectTypeConverter instance ObjectTypeConverter objectTypeConvter = new ObjectTypeConverter(); objectTypeConverter.addConversionValue("F", "Female"); // Set ObjectTypeConverter on ArrayMapping ArrayMapping arrayMapping = new ArrayMapping(); arrayMapping.setValueConverter(objectTypeConverter); arrayMapping.setAttributeName("responsibilities"); arrayMapping.setStructureName("Responsibilities_t"); arrayMapping.setFieldName("RESPONSIBILITIES"); orDescriptor.addMapping(arrayMapping);
Configure the ObjectTypeConverter
instance using the following API:
addConversionValue(java.lang.Object fieldValue, java.lang.Object attributeValue)
–to associate data-type values to object-type values
addToAttributeOnlyConversionValue(java.lang.Object fieldValue, java.lang.Object attributeValue)
–to add one-way conversion values
setDefaultAttributeValue(java.lang.Object defaultAttributeValue)
–to set the default value
The simple type translator allows 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. You can use a simple type translator only when the mapping's XPath goes to an element. You cannot use a simple type translator if the mapping's XPath goes to an attribute.
For more information, see "Simple Type Translator".
Table 32-13 summarizes which mappings support this option.
Table 32-13 Mapping Support for Simple Type Translator
Mapping | Using TopLink Workbench |
Using Java |
---|---|---|
|
||
|
|
|
EIS Composite Direct Collection Mapping |
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
|
Use this table to qualify elements from the XML schema
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-13 General Tab, Use XML Schema "type" Attribute Option
Select the Field Uses XML Schema "type" attribute field to qualify elements from the XML schema.
To create an XML mapping with a simple type translator with Java code in your IDE, you need the following elements:
EISDirectMapping
or EISCompositeDirectCollectionMapping
or XMLDirectMapping
or XMLCompositeDirectCollectionMapping
instance of Converter
instance of TypedElementField
Example 32-14 shows how to implement your own simple type translator with an XMLDirectMapping
to override the built-in conversion for writing XML so that TopLink writes a Byte
array (ClassConstants.ABYTE
) as a Base64
(XMLConstants.BASE64_BINARY
) encoded string.
Example 32-14 Creating a Type Translation XML Mapping
XMLDirectMapping mapping = new XMLDirectMapping(); mapping.setConverter(new SerializedObjectConverter()); TypedElementField field = new TypedElementField("element"); field.getSimpleTypeTranslator().addJavaConversion( ClassConstants.ABYTE, new QName(XMLConstants.SCHEMA_URL, XMLConstants.BASE64_BINARY) ); mapping.setField(field);
The JAXB typesafe enumeration converter allows you to automatically translate an XML element value to an appropriate typesafe enumeration value as defined in your XML schema.
For more information, see "Mappings and JAXB Typesafe Enumerations".
Table 32-14 summarizes which mappings support this option.
Table 32-14 Mapping Support for JAXB Typesafe Enumeration Converter
Mapping | Using TopLink Workbench | Using Java |
---|---|---|
|
|
|
EIS Composite Direct Collection Mapping |
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
Footnote 1 When used with XML records only (see "Configuring Record Format").
TopLink Workbench does not support the JAXBTypesafeEnumConverter
directly: to configure a mapping with this converter, you must use Java to create an amendment method (see "Using Java").
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").
To configure a mapping with a JAXBTypesafeEnumConverter
in Java, use a descriptor amendment method (see "Configuring Amendment Methods"). Example 32-15 illustrates an amendment method that configures an XMLDirectMapping
with a JAXBTypesafeEnumConverter
. In this example, attribute _Val
is mapped to a JAXB typesafe enumeration corresponding to typesafe enumeration class MyTypesafeEnum
.
Example 32-15 Creating a JAXB Typesafe Enumeration XML Mapping
public class DescriptorAfterLoads { public static void amendRootImplDescriptor(ClassDescriptor descriptor) { DatabaseMapping _ValMapping = descriptor.getMappingForAttributeName("_Val"); JAXBTypesafeEnumConverter _ValConverter = new JAXBTypesafeEnumConverter(); ValConverter.setEnumClassName("MyTypesafeEnum"); ((XMLDirectMapping) _ValMapping).setConverter(_ValConverter); } }
Collection mapping container policy specifies the concrete class TopLink should use when reading target objects from the database.
Collection mappings can use any concrete class that implements the java.util.List
, java.util.Set
, java.util.Collection
, or java.util.Map
interface. You can map object attributes declared as List
, Set
, Collection
, Map
, or any subinterface of these interfaces, or as a class that implements one of these interfaces.
By default, the TopLink runtime uses the following concrete classes from the oracle.toplink.indirection
package for each of these container types:
List
–IndirectList
or EJBIndirectList
Set
–IndirectSet
or EJBIndirectSet
Collection
–IndirectList
or EJBIndirectList
Map
–IndirectMap
or EJBIndirectMap
Alternatively, you can specify in the mapping the concrete container class to be used. When TopLink reads objects from the database that contain an attribute mapped with a collection mapping, the attribute is set with an instance of the concrete class specified. For example, TopLink does not sort in memory. If you want to sort in memory, override the default Set
type (IndirectList
) with java.util.TreeSet
as the concrete collection type. By default, a collection mapping's container class is java.util.Vector
.
Note: If you are using TopLink Workbench and you override the defaultCollection class with a custom Collection class of your own, you must put your custom Collection class on the TopLink Workbench classpath (see "Configuring the TopLink Workbench Environment"). |
Table 32-15 summarizes which mappings support this option.
Table 32-15 Mapping Support for Container Policy
To specify a mapping's container policy, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Click the Advanced button. The Advanced Container Options appear on the General tab.
Figure 32-14 General Tab, Advanced Container Options
Use the following Advanced Container Options fields on the General tab to specify the container options:
FieldFoot 1 | Description |
---|---|
Container Type | Specify the type of Collection class to use:
|
Override Default Class | Specify to use a custom class as the mapping's container policy. Click Browse to select a different class. The container class must implement (directly or indirectly) the java.util.Collection interface. |
Key Method | If you configure Container Type as Map, use this option to specify the name of the zero argument method whose result, when called on the target object, is used as the key in the Hashtable or Map . This method must return an object that is a valid key in the Hashtable or Map . |
Footnote 1 Not all mappings support all options. For more information, see Table 32-15.
Classes that implement the oracle.toplink.mappings.ContainerMapping
interface provide the following methods to set the container policy:
useCollectionClass(java.lang.Class concreteClass)
–Configure the mapping to use an instance of the specified java.util.Collection
container class to hold the target objects.
useMapClass(java.lang.Class concreteClass, java.lang.String methodName)
–Configure the mapping to use an instance of the specified java.util.Map
container class to hold the target objects. The key used to index a value in the Map
is the value returned by a call to the specified zero-argument method. The method must be implemented by the class (or a superclass) of any value to be inserted into the Map
.
Classes that extend oracle.toplink.mappings.CollectionMapping
(which implements the ContainerMapping
interface) also provide the following methods to set the container policy:
useSortedSetClass(java.lang.Class concreteClass, java.util.Comparator comparator)
–Configure the mapping to use an instance of the specified java.util.SortedSet
container class. Specify the Comparator
to use to sort the target objects.
Example 32-16 shows how to configure an ObjectArrayMapping
to use a java.util.ArrayList
container class.
Example 32-16 Object Array Mapping
// Create a new mapping and register it with the source Object-relational descriptor
ObjectArrayMapping phonesMapping = new ObjectArrayMapping();
phonesMapping.setAttributeName("phones");
phonesMapping.setGetMethodName("getPhones");
phonesMapping.setSetMethodName("setPhones");
phonesMapping.setStructureName("PHONELIST_TYPE");
phonesMapping.setReferenceClass(Phone.class);
phonesMapping.setFieldName("PHONES");
phonesMapping.useCollectionClass(ArrayList.class);
orDescriptor.addMapping(phonesMapping);
A transformation mapping is made up of an attribute transformer for field-to-attribute transformation at read (unmarshall) time and one or more field transformers for attribute-to-field transformation at write (marshall) time (see "Configuring Field Transformer Associations").
This section describes how to configure the attribute transformer that a transformation mapping uses to perform the field-to-attribute transformation at read (unmarshal) time.
You can do this using either a method or class-based transformer.
A method-based transformer must map to a method in the domain object.
A class-based transformer allows you to place the transformation code in another class, making this approach non-intrusive: that is, your domain object does not need to implement a TopLink interface or provide a special transformation method
Table 32-16 summarizes which mappings support this option.
To specify a mapping's attribute transformer, use this procedure:
Select the transformation mapping in the Navigator. Its properties appear in the Editor.
Figure 32-15 Transformation Mapping, Attribute Transformer Field
Click Edit. The Specify Transformer dialog box appears.
Figure 32-16 Specify Transformer Dialog Box
Use the following information to enter data in each field of the dialog box and click OK:
Field | Description |
---|---|
Use Transformation Method | Select a specific method to control the transformation. A method based transformer must map to a method in the domain object. |
Use Transformer Class | Select a specific class to control the transformation. The class must be available on the TopLink Workbench application classpath. |
You can configure a method-based attribute transformer using AbstractTransformationMapping
method setAttributeTransformation
, passing in the name of the domain object method to use.
You can configure a class-based attribute transformer using AbstractTransformationMapping
method setAttributeTransformer
, passing in an instance of oracle.toplink.mappings.Transfomers.AttributeTransformer
.
A convenient way to create an AttributeTransformer
is to extend AttributeTransformerAdapter
.
A transformation mapping is made up of an attribute transformer for field-to-attribute transformation at read (unmarshall) time (see "Configuring Attribute Transformer") and one or more field transformers for attribute-to-field transformation at write (marshall) time.
This section describes how to configure the field transformers that a transformation mapping uses to perform the object attribute-to-field transformation at write (marshal) time.
You can do this using either a method or class-based transformer.
A method-based transformer must map to a method in the domain object.
A class-based transformer allows you to place the transformation code in another class, making this approach non-intrusive: that is, your domain object does not need to implement a TopLink interface or provide a special transformation method.
Table 32-17 summarizes which mappings support this option.
Use this procedure to complete the Object->Field Method fields:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Figure 32-17 Transformation Mapping, Field Transformer Associations
To add a new association, click Add. Continue with "Specifying Field-to-Transformer Associations".
To change an existing association, click Edit. Continue with "Specifying Field-to-Transformer Associations".
To delete an existing association, select the field transformation association and click Delete.
To specify the actual transformation method or class used for the field of a transformation mapping, use this procedure.
From the Transformation Mapping, Field Transformer Associations, click Add or Edit. The Specify Field-Transformer Association dialog box appears.
Figure 32-18 Specify Field-Transformer Association Dialog Box
Use the following information to complete each field on the dialog box:
Field | Description |
---|---|
Field | Select the database field (from the descriptor's associated table) for this transformation. |
Transformer | Select one of the following methods to control the transformation: |
Use Transformation Method | Select a specific method to control the transformation. A method based transformer must map to a method in the domain object. |
Use Transformer Class | Select a specific class to control the transformation. The class must be available on TopLink Workbench application classpath. |
You can specify a specific transformation method on your domain object or an instance of oracle.toplink.mappings.Transfomers.FieldTransformer
(you can also extend the FieldTransformerAdapter
). Using a FieldTransformer
is non-intrusive: that is, your domain object does not need to implement a TopLink interface or provide a special transformation method.
You can configure a method-based field transformer using AbstractTransformationMapping
method addFieldTransformation
, passing in the name of the database field and the name of the domain object method to use.
You can configure a class-based field transformer using AbstractTransformationMapping
method addFieldTransformer
, passing in the name of the database field and an instance of oracle.toplink.mappings.Transfomers.FieldTransformer
.
A convenient way to create a FieldTransformer
is to extend FieldTransformerAdapter
.
Direct mappings typically map simple, non-mutable values such as String
or Integer
. Transformation mappings can potentially map complex mutable object values, such as mapping several database field values to an instance of a Java class.
If a transformation mapping maps a mutable value, TopLink must clone and compare the value in a unit of work (see "Configuring Copy Policy").
By default, TopLink assumes that all transformation mappings are mutable. If the mapping maps a simple nonmutable value, you can improve unit of work performance by configuring the IsMutable option to false
.
Table 32-18 summarizes which mappings support this option.
Use this table to complete the Object->Field Method fields:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Figure 32-19 Transformation Mapping, Mutable Option
By default, the IsMutable option is selected in all transformation mappings. If the mapping maps to a simple atomic value, unselect this option.
If a mapping has a bidirectional relationship in which the two classes in the relationship reference each other with one-to-one mappings, then set up the foreign key information as follows:
One mapping must call the setForeignKeyFieldName
method.
The other must call the setTargetForeignKeyFieldName
method.
It is also possible to set up composite foreign key information by calling the addForeignKeyFieldName
and addTargetForeignKeyFieldName
methods. Because TopLink enables indirection by default, the attribute must be a ValueHolderInterface
.
Table 32-18 summarizes which mappings support this option.
To maintain a bidirectional relationship for a mapping, use this procedure:
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-20 General tab, Maintains Bidirectional Relationship option
Use this table to enter data in the following fields on the tab:
Field | Description |
---|---|
Maintains Bidirectional Relationship | Specify if TopLink should maintain the bidirectional link for this relational mapping. |
Relationship Partner | Select the relationship partner (from the list of mapped attributes of the Reference Descriptor) for this bidirectional relationship. |
For the XML-based mappings that Table 32-6 summarizes, when you map a list value, 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, like:
<item>aaa</item> <item>bbb</item> <item>ccc</item>
Table 32-6 summarizes which mappings support this option.
Table 32-20 Mapping Support for Use Single Node
Mapping | Using TopLink Workbench |
Using Java |
---|---|---|
|
|
|
EIS Composite Direct Collection Mapping |
|
|
|
||
|
|
|
XML Composite Direct Collection Mapping |
|
|
Footnote 1 When used with XML records only (see "Configuring Record Format").
To configure a mapping to use a single node, use this procedure.
Select the mapped attribute in the Navigator. Its properties appear in the Editor.
Click the General tab. The General tab appears.
Figure 32-21 General Tab, Use Single Node Option
To configure the mapping to unmarshall (write) a list value to a single node (like <item>aaa bbb ccc</item>
), click Use single node.
By default, the mapping unmarshalls a list value to separate nodes.
Use AbstractCompositeDirectCollectionMapping
method setUsesSingleNode
to configure the mapping to write a list value to a single node by passing in a value of true
. To configure the mapping to write a list value to multiple nodes, pass in a value of false
.
For any mapping that takes an XMLField
, use XMLField
method setUsesSingleNode
to configure the mapping to write a list value to a single node by passing in a value of true
. To configure the mapping to write a list value to multiple nodes, pass in a value of false
. Example 32-17 shows how to use this method with an XMLDirectMapping
: