Oracle® Application Server TopLink Application Developer's Guide
10g Release 2 (10.1.2) Part No. B15901-01 |
|
Previous |
Next |
Several complex mappings are available in OracleAS TopLink. This section discusses the following mapping types:
Transformation mappings enable you to create specialized translations between how a value is represented in Java and in the database. Use transformation mappings only when mapping multiple fields into a single attribute. Transformation mapping is often appropriate when you use values from multiple fields to create an object.
Note: Because of the complexity of transformation mappings, it is often easier to perform the transformation withget and set methods of a direct-to-field mapping.
|
After you create the required transformation method, use OracleAS TopLink Mapping Workbench to implement transformation mappings.
For more information, see "Working with Transformation Mappings" in the Oracle Application Server TopLink Mapping Workbench User's Guide.
Transformation mappings are instances of the TransformationMapping
class and require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message; not required for write-only mappings
The method to be invoked that sets the value of the attribute from information in the database row; set by sending the setAttributeTransformation()
message that expects one or two parameters: a DatabaseRow
and optionally a Session
A set of methods associated to fields in the database, where the value for each field is the result of invoking the associated method; associations are made by sending the addFieldTransformation()
message, passing along the database field name and the method name
Use the optional setGetMethodName()
and setSetMethodName()
messages to access the attribute through user-defined methods, rather than directly.
Example 3-32 Creating a Transformation Mapping and Registering It with the Descriptor
This example provides custom support for two fields. You can use this approach to map any number of fields.
// Create a new mapping and register it with the descriptor. TransformationMapping transformation1 = new TransformationMapping(); transformation1.setAttributeName ("dateAndTimeOfBirth"); transformation1.setAttributeTransformation ("buildDateAndTime"); transformation1.addFieldTransformation("B_DAY", "getDateOfBirth"); transformation1.addFieldTransformation("B_TIME", "getTimeOfBirth"); descriptor.addMapping(transformation1); // Define attribute transformation method to read from the database row public java.util.Date buildDateAndTime(DatabaseRow row) { java.sql.Date sqlDateOfBirth = (java.sql.Date)row.get("B_DAY"); java.sql.Time timeOfBirth = (java.sql.Time)row.get("B_TIME"); java.util.Date utilDateOfBirth = new java.util.Date( sqlDateOfBirth.getYear(), sqlDateOfBirth.getMonth(), sqlDateOfBirth.getDate(), timeOfBirth.getHours(), timeOfBirth.getMinutes(), timeOfBirth.getSeconds()); return utilDateOfBirth; } // Define a field transformation method to write to the database public java.sql.Time getTimeOfBirth() { return new java.sql.Time this.dateAndTimeOfBirth.getHours(), this. dateAndTimeOfBirth.getMinutes(), this.dateAndTimeOfBirth.getSeconds()); } // Define a field transformation method to write to the database public java.sql.Date getDateOfBirth() { return new java.sql.DateOfBirth this.dateAndTimeOfBirth.getYear(), this.dateAndTimeOfBirth.getMonth(), this.dateAndTimeOfBirth.getDate()); }
Example 3-33 Creating a Transformation Mapping Using Indirection
// Create a new mapping and register it with the descriptor. TransformationMapping transformation2 = new transformation2.setAttributeName("designation"); transformation2.setGetMethodName ("getDesignationHolder"); transformation2.setSetMethodName ("setDesignationHolder"); transformation2.setAttributeTransformation ("getRankFromRow"); transformation2.addFieldTransformation("RANK", "getRankFromObject"); transformation2.useIndirection(); descriptor.addMapping(transformation2); //Define an attribute transformation method to read from database row. public String getRankFromRow() { Integer value = new Integer(((Number)row.get("RANK)).intValue()); String rank = null; if (value.intValue() == 1) { rank = "Executive"; } if (value.intValue() == 2) { rank = "Non-Executive"; } return rank; } //Define a field transformation method to write to the database. public Integer getRankFromObject() { Integer rank = null; if (getDesignation().equals("Executive")) rank = new Integer(1); if (getDesignation().equals("Non-Executive")) rank = new Integer(2); return rank; } //Provide accessor methods for the indirection. private ValueHolderInterface designation; public ValueHolderInterface getDesignationHolder() { return designation; } public void setDesignationHolder(ValueHolderInterface value) { designation = value; }
For more information about the available methods for TransformationMapping
, see the Oracle Application Server TopLink API Reference.
Serialized object mappings are used to store large data objects, such as multimedia files and BLOBs, in the database. Serialization transforms these large objects as a stream of bits.
Serialized object mappings are instances of the SerializedObjectMapping
class and require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The field that stores the value of the attribute, set by the setFieldName()
message
Use the optional setGetMethodName()
and setSetMethodName()
messages to access the attribute through user-defined methods, rather than directly. You do not have to define accessors when you use Java 2.
Example 3-34 Creating a Serialized Object Mapping and Registering It with the Descriptor
// Create a new mapping and register it with the descriptor. SerializedObjectMapping serializedMapping = new SerializedObjectMapping(); serializedMapping.setAttributeName("jobDescription"); serializedMapping.setFieldName("JOB_DESC"); descriptor.addMapping(serializedMapping);
For more information about the available methods for SerializedObjectMapping
, see the Oracle Application Server TopLink API Reference.
Variable one-to-one mappings are instances of the VariableOneToOneMapping()
class and require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The reference class, set by sending the setReferenceClass()
message
The foreign key and target query key information, normally specified by sending the setForeignQueryKeyName()
message and passing the source foreign key field name and the target abstract query key name on the interface descriptor
Note: If the primary keys of the target implementor descriptors are composite, then send theaddForeignQueryKeyName() message for each of the foreign key fields, and target query keys that make up the relationship.
|
If the mapping uses a class indicator field:
Specify a type indicator field.
Specify the class indicator values on the mapping so that mapping can determine the class of object to create.
Note: Because Indirection is enabled by default, the attribute must be aValueHolderInterface .
|
Example 3-35 Defining a Variable One-to-One Mapping Using a Class Indicator Field
VariableOneToOneMapping variableOneToOneMapping = new VariableOneToOneMapping(); variableOneToOneMapping.setAttributeName("contact"); variableOneToOneMapping.setReferenceClass (Contact.class); variableOneToOneMapping.setForeignQueryKeyName ("C_ID", "id"); variableOneToOneMapping.setTypeFieldName("TYPE"); variableOneToOneMapping.addClassIndicator(Email.class, "Email"); variableOneToOneMapping.addClassIndicator(Phone.class, "Phone"); variableOneToOneMapping.dontUseIndirection(); variableOneToOneMapping.privateOwnedRelationship();
Example 3-36 Defining a Variable One-to-One Mapping Using a Primary Key
VariableOneToOneMapping variableOneToOneMapping = new VariableOneToOneMapping(); variableOneToOneMapping.setAttributeName("contact"); variableOneToOneMapping.setReferenceClass (Contact.class); variableOneToOneMapping.setForeignQueryKeyName ("C_ID", "id"); variableOneToOneMapping.dontUseIndirection(); variableOneToOneMapping.privateOwnedRelationship();
For more information about the available methods for VariableOneToOneMapping
, see the Oracle Application Server TopLink API Reference.
Relational mappings define the reference between persistent objects. Object relational mappings enable you to persist an object model into an object-relational data model. OracleAS TopLink Mapping Workbench does not directly support these mappings—you must define them in code through amendment methods.
OracleAS TopLink supports the following object-relational mappings:
In an object-relational data-model, structures can contain arrays (collections of other data types). These arrays can contain primitive data types or collections of other structures. OracleAS TopLink stores the arrays with their parent structure in the same table.
All elements in the array must be of the same data type. The number of elements in an array controls the size of the array. An Oracle database allows arrays of variable sizes (called Varrays).
Oracle8i or higher offers two collection types:
Varray – Used to represent a collection of primitive data or aggregate structures.
Nested table – Similar to varrays except they store information in a separate table from the table of the parent structure
OracleAS TopLink supports arrays of primitive data through the ArrayMapping
class. This is similar to DirectCollectionMapping
—it represents a collection of primitives in Java. However, the ArrayMapping
class does not require an additional table to store the values in the collection.
OracleAS TopLink supports arrays of aggregate structures through the ObjectArrayMapping
class.
OracleAS TopLink supports nested tables through the NestedTableMapping
class.
Array mappings are instances of the ArrayMapping
class and require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The field to be mapped, set by sending the setFieldName()
message
The name of the array, set by sending the setStructureName()
message
Example 3-37 Creating an Array Mapping for the Employee Source Class and Registering It with the Descriptor
// Create a new mapping and register it with the source descriptor. ArrayMapping arrayMapping = new ArrayMapping(); arrayMapping.setAttributeName("responsibilities"); arrayMapping.setStructureName("Responsibilities_t"); arrayMapping.setFieldName("RESPONSIBILITIES"); descriptor.addMapping(arrayMapping);
In addition to the API illustrated in Example 3-37, other common APIs for use with implement array mapping include:
setReferenceClass(Class referenceClass)
: to set the parent class
setGetMethodName(String name)
and setSetMethodName(String name)
: to provide method access
For more information about the available methods for ArrayMapping
, see the Oracle Application Server TopLink API Reference.
In an object-relational data-model, object arrays allow for an array of object types or structures to be embedded into a single column in a database table or an object table.
OracleAS TopLink supports object array mappings to define a collection-aggregated relationship in which the target objects share the same row as the source object.
Object array mappings are instances of the ObjectArrayMapping
class. You must associate this mapping to an attribute in the parent class. Object array mappings require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The field to be mapped, set by sending the setFieldName()
message
The name of the array, set by sending the setStructureName()
message
Use the optional setGetMethodName()
and setSetMethodName()
messages to access the attribute through user defined methods, rather than directly.
Example 3-38 Creating an Object Array Mapping for the Insurance Source Class and Registering It with the Descriptor
// Create a new mapping and register it with the source 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"); descriptor.addMapping(phonesMapping);
For more information about the available methods for ObjectArrayMapping
, see the Oracle Application Server TopLink API Reference.
In an object-relational data-model, structures are user defined data types or object-types. This is similar to a Java class—it defines attributes or fields in which each attribute is either:
A primitive data type
Another structure
Reference to another structure
OracleAS TopLink maps each structure to a Java class defined in your object model and defines a descriptor for each class. A StructureMapping
maps nested structures, similar to an AggregateObjectMapping
. However, the structure mapping supports null values and shared aggregates without requiring additional settings (because of the object-relational support of the database).
Structure mappings are instances of the StructureMapping
class. You must associate this mapping to an attribute in each of the parent classes. Structure mappings require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The field to be mapped, set by sending the setFieldName()
message
The target (child) class, set by sending the setReferenceClass()
message
Use the optional setGetMethodName()
and setSetMethodName()
message to access the attribute through user-defined methods, rather than directly.
Make the following changes to the target (child) class descriptor:
Send the descriptorIsAggregate()
message to indicate that it is not a root level.
Remove table or primary key information.
Example 3-39 Creating a Structure Mapping for the Employee Source Class and Registering It with the Descriptor
// Create a new mapping and register it with the source descriptor. StructureMapping structureMapping = new StructureMapping(); structureMapping.setAttributeName("address"); structureMapping.setReferenceClass(Address.class); structureMapping.setFieldName("address"); descriptor.addMapping(structureMapping);
Example 3-40 Creating the Descriptor of the Address Aggregate Target Class
The aggregate target descriptor does not need a mapping to its parent, or any table or primary key information.
// Create a descriptor for the aggregate class. The table name and primary key are not specified in the aggregate descriptor. ObjectRelationalDescriptor descriptor = new ObjectRelationalDescriptor (); descriptor.setJavaClass(Address.class); descriptor.setStructureName("ADDRESS_T"); descriptor.descriptorIsAggregate(); // Define the field ordering descriptor.addFieldOrdering("STREET"); descriptor.addFieldOrdering("CITY"); ... // Define the attribute mappings or relationship mappings. ...
In addition to the API illustrated in Example 3-40, other common APIs for use with structure mapping include:
readWrite()
readOnly()
setIsReadOnly(boolean readOnly)
For more information about the available methods for StructureMapping
, see the Oracle Application Server TopLink API Reference.
In an object-relational data-model, structures reference each other through refs—not through foreign keys (as in a traditional data model). Refs are based on the ObjectID
of the target structure.
OracleAS TopLink supports refs through the ReferenceMapping
. They represent an object reference in Java, similar to a OneToOneMapping
. However, the reference mapping does not require foreign key information.
Reference mappings are instances of the ReferenceMapping
class. You must associate this mapping to an attribute in the source class. Reference mappings require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The field to be mapped, set by sending the setFieldName()
message
The target class, set by sending the setReferenceClass ()
message
Use the optional setGetMethodName()
and setSetMethodName()
messages to access the attribute through user-defined methods, rather than directly.
Example 3-41 Creating a Reference Mapping for the Employee Source Class and Registering It with the Descriptor
// Create a new mapping and register it with the source descriptor. ReferenceMapping referenceMapping = new ReferenceMapping(); referenceMapping.setAttributeName("manager"); referenceMapping.setReferenceClass(Employee.class); referenceMapping.setFieldName("MANAGER"); descriptor.addMapping(refrenceMapping);
In addition to the API illustrated in Example 3-41, other common APIs for use with reference mappings include:
useBasicIndirection()
: implements OracleAS TopLink valueholder indirection
dontUseIndirection()
readWrite()
readOnly()
setIsReadOnly(boolean readOnly)
For more information about the available methods for ReferenceMapping
, see the Oracle Application Server TopLink API Reference.
Nested table types model an unordered set of elements. These elements may be built-in or user-defined types. You can view a nested table as a single-column table or, if the nested table is an object type, as a multi-column table (with a column for each attribute of the object type).
Nested tables represent a one-to-many or many-to-many relationship of references to another independent structure. They support querying and joining better than Varrays
that are inlined to the parent table.
OracleAS TopLink supports nested tables through the NestedTableMapping
. They represent a collection of object references in Java, similar to a OneToManyMapping
or ManyToManyMapping
. However, the nested table mapping does not require foreign key information (such as a one-to-many mapping) or the relational table (such as a many-to-many mapping).
Nested table mappings are instances of the NestedTableMapping
class. This mapping is associated to an attribute in the parent class. Nested table mappings require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The field to be mapped, set by sending the setFieldName()
message
The name of the array structure, set by sending the setStructureName()
message
Use the optional setGetMethodName()
and setSetMethodName()
messages to allow OracleAS TopLink to access the attribute through user-defined methods, rather than directly.
Example 3-42 Creating a Nested Table Mapping for the Insurance Source Class and Registering It with the Descriptor
// Create a new mapping and register it with the source descriptor. NestedTableMapping policiesMapping = new NestedTableMapping(); policiesMapping.setAttributeName("policies"); policiesMapping.setGetMethodName("getPolicies"); policiesMapping.setSetMethodName("setPolicies"); policiesMapping.setReferenceClass(Policy.class); policiesMapping.dontUseIndirection(); policiesMapping.setStructureName("POLICIES_TYPE"); policiesMapping.setFieldName("POLICIES"); policiesMapping.privateOwnedRelationship(); policiesMapping.setSelectionSQLString("select p.* from policyHolders ph, table(ph.policies) t, policies p where ph.ssn=#SSN and ref(p) = value(t)"); descriptor.addMapping(policiesMapping);
In addition to the API illustrated in Example 3-42, other common APIs for use with nested table mappings include:
useBasicIndirection()
: implements OracleAS TopLink valueholder indirection
dontUseIndirection()
setUsesIndirection(boolean usesIndirection)
independentRelationship()
privateOwnedRelationship()
setIsPrivateOwned(Boolean isPrivateOwned)
For more information about the available methods for NestedTableMapping
, see the Oracle Application Server TopLink API Reference.
Direct map mappings store instances that implement java.util.Map
. Unlike one-to-many or many-to-many mappings, the keys and values of the map in this type of mapping are Java objects that do not have descriptors. The object type stored in the key and the value of direct map mappings are Java primitive wrapper types such as String objects.
Support for primitive data types such as int
is not provided because Java maps hold only objects.
Direct map mappings are instances of the DirectMapMapping
class and require the following elements:
The attribute to be mapped, set by sending the setAttributeName()
message
The database table that holds the keys and values to be stored in the map, set by sending the setReferenceTableName()
message
The field in the reference table from which the keys are read and placed into the map; this is called the direct key field and is set by sending the setDirectKeyFieldName()
message
The foreign key information, which you specify by sending the setReferenceKeyFieldName()
message and passing the name of the field that is a foreign reference to the primary key of the source object
Note: If the target primary key is composite, send theaddReferenceKeyFieldName() message for each of the fields that make up the key.
|
The field in the reference table from which the values are read and placed into the map; this is called the direct field and is set by sending the setDirectFieldName()
message
The Java type of key in map from which the keys are converted from keys are read from the database placed into the map; this is set by sending the setKeyClass()
message
The Java type of value in map from which the values are converted from values are read from the database placed into the map; this is set by sending the setValueClass()
message
Example 3-43 Creating a Simple Direct Map Mapping
DirectMapMapping directMapMapping = new DirectMapMapping(); directMapMapping.setAttributeName("cities"); directMapMapping.setReferenceTableName("CITY_TEMP"); directMapMapping.setReferenceKeyFieldName("RECORD_ID"); directMapMapping.setDirectKeyFieldName("CITY"); directMapMapping.setDirectFieldName("TEMPERATURE"); directMapMapping.setKeyClass(String.class); directMapMapping.setValueClass(Integer.class); descriptor.addMapping(directMapMapping);
In addition to the API illustrated in Example 3-43, other common APIs for use with direct map mappings include:
useBasicIndirection()
: implements OracleAS TopLink valueholder indirection
useTransparentCollection()
: if you use transparent indirection, this element places a special collection in the attribute of the source object
dontUseIndirection()
: implements no indirection
For more information about the available methods for DirectMapMapping
, see the Oracle Application Server TopLink API Reference.