Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Introduction to Relational Mappings (ELUG)"

m (One-to-Many Mapping)
(Aggregate Collection Mappings and Inheritance)
 
(14 intermediate revisions by 3 users not shown)
Line 12: Line 12:
  
 
==Relational Mapping Types==
 
==Relational Mapping Types==
 
 
EclipseLink supports the relational mappings listed in the following table.
 
EclipseLink supports the relational mappings listed in the following table.
  
 
<span id="Table 32-1"></span>
 
<span id="Table 32-1"></span>
''''' EclipseLink Relational Mapping Types'''''
 
  
 
{| class="RuleFormalWideMax" dir="ltr" title="EclipseLink Relational Mapping Types" summary="This table describes the relational mapping types." width="100%" border="1" frame="border" rules="all" cellpadding="3" frame="border" rules="all"
 
{| class="RuleFormalWideMax" dir="ltr" title="EclipseLink Relational Mapping Types" summary="This table describes the relational mapping types." width="100%" border="1" frame="border" rules="all" cellpadding="3" frame="border" rules="all"
Line 26: Line 24:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r2c1-t2" headers="r1c1-t2" align="left" |
 
| id="r2c1-t2" headers="r1c1-t2" align="left" |
Direct-to-field (see [[#Direct-to-Field Mapping]])
+
[[#Direct-to-Field Mapping|Direct-to-field ]]
 
| headers="r2c1-t2 r1c2-t2" align="left" |
 
| headers="r2c1-t2 r1c2-t2" align="left" |
 
Map a Java attribute directly to a database field.
 
Map a Java attribute directly to a database field.
Line 35: Line 33:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r3c1-t2" headers="r1c1-t2" align="left" |
 
| id="r3c1-t2" headers="r1c1-t2" align="left" |
Direct-to-XMLType (see [[#Direct-to-XMLType Mapping]])
+
[[#Direct-to-XMLType Mapping|Direct-to-XMLType ]]
 
| headers="r3c1-t2 r1c2-t2" align="left" |
 
| headers="r3c1-t2 r1c2-t2" align="left" |
 
Map Java attributes to an <tt>XMLType</tt> column in an Oracle Database (introduced in version 9.2.0.1).
 
Map Java attributes to an <tt>XMLType</tt> column in an Oracle Database (introduced in version 9.2.0.1).
Line 44: Line 42:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r4c1-t2" headers="r1c1-t2" align="left" |
 
| id="r4c1-t2" headers="r1c1-t2" align="left" |
One-to-one (see [[#One-to-One Mapping]])
+
[[#One-to-One Mapping|One-to-one ]]
 
| headers="r4c1-t2 r1c2-t2" align="left" |
 
| headers="r4c1-t2 r1c2-t2" align="left" |
 
Map a reference to another persistent Java object to the database.
 
Map a reference to another persistent Java object to the database.
Line 53: Line 51:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r5c1-t2" headers="r1c1-t2" align="left" |
 
| id="r5c1-t2" headers="r1c1-t2" align="left" |
Variable one-to-one (see [[#One-to-One Mapping]])
+
[[#One-to-One Mapping|Variable one-to-one ]]
 
| headers="r5c1-t2 r1c2-t2" align="left" |
 
| headers="r5c1-t2 r1c2-t2" align="left" |
 
Map a reference to an interface to the database.
 
Map a reference to an interface to the database.
Line 62: Line 60:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r6c1-t2" headers="r1c1-t2" align="left" |
 
| id="r6c1-t2" headers="r1c1-t2" align="left" |
One-to-many (see [[#One-to-Many Mapping]])
+
[[#One-to-Many Mapping|One-to-many ]]
 
| headers="r6c1-t2 r1c2-t2" align="left" |
 
| headers="r6c1-t2 r1c2-t2" align="left" |
 
Map Java collections of persistent objects to the database.
 
Map Java collections of persistent objects to the database.
Line 71: Line 69:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r7c1-t2" headers="r1c1-t2" align="left" |
 
| id="r7c1-t2" headers="r1c1-t2" align="left" |
Many-to-many (see [[#Many-to-Many Mapping]])
+
[[#Many-to-Many Mapping|Many-to-many ]]
 
| headers="r7c1-t2 r1c2-t2" align="left" |
 
| headers="r7c1-t2 r1c2-t2" align="left" |
 
Use an association table to map Java collections of persistent objects to the database.
 
Use an association table to map Java collections of persistent objects to the database.
Line 80: Line 78:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r8c1-t2" headers="r1c1-t2" align="left" |
 
| id="r8c1-t2" headers="r1c1-t2" align="left" |
Aggregate collection (see [[#Collection Mapping]])
+
[[#Collection Mapping|Aggregate collection ]]
 
| headers="r8c1-t2 r1c2-t2" align="left" |
 
| headers="r8c1-t2 r1c2-t2" align="left" |
 
Map Java collections of persistent objects to the database.
 
Map Java collections of persistent objects to the database.
Line 89: Line 87:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r9c1-t2" headers="r1c1-t2" align="left" |
 
| id="r9c1-t2" headers="r1c1-t2" align="left" |
Direct collection (see [[#Direct Collection Mapping]])
+
[[#Direct Collection Mapping|Direct collection ]]
 
| headers="r9c1-t2 r1c2-t2" align="left" |
 
| headers="r9c1-t2 r1c2-t2" align="left" |
 
Map Java collections of objects that do not have descriptors.
 
Map Java collections of objects that do not have descriptors.
Line 98: Line 96:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r10c1-t2" headers="r1c1-t2" align="left" |
 
| id="r10c1-t2" headers="r1c1-t2" align="left" |
Direct map (see [[#Direct Map Mapping]])
+
[[#Direct Map Mapping|Direct map ]]
 
| headers="r10c1-t2 r1c2-t2" align="left" |
 
| headers="r10c1-t2 r1c2-t2" align="left" |
 
Direct map mappings store instances that implement <tt>java.util.Map</tt>.
 
Direct map mappings store instances that implement <tt>java.util.Map</tt>.
Line 107: Line 105:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r11c1-t2" headers="r1c1-t2" align="left" |
 
| id="r11c1-t2" headers="r1c1-t2" align="left" |
Aggregate object (see [[#Aggregate Object Mapping]])
+
[[#Aggregate Object Mapping|Aggregate object ]]
 
| headers="r11c1-t2 r1c2-t2" align="left" |
 
| headers="r11c1-t2 r1c2-t2" align="left" |
 
Create strict one-to-one mappings that require both objects to exist in the same database row.
 
Create strict one-to-one mappings that require both objects to exist in the same database row.
Line 116: Line 114:
 
|- align="left" valign="top"
 
|- align="left" valign="top"
 
| id="r12c1-t2" headers="r1c1-t2" align="left" |
 
| id="r12c1-t2" headers="r1c1-t2" align="left" |
Transformation (see [[#Transformation Mapping]])
+
[[#Transformation Mapping|Transformation ]]
 
| headers="r12c1-t2 r1c2-t2" align="left" |
 
| headers="r12c1-t2 r1c2-t2" align="left" |
 
Create custom mappings where one or more fields can be used to create the object to be stored in the attribute.
 
Create custom mappings where one or more fields can be used to create the object to be stored in the attribute.
Line 125: Line 123:
 
|}
 
|}
  
==Relational Mapping Concepts==
 
  
 +
 +
==Relational Mapping Concepts==
 
This section introduces direct mapping concepts unique to EclipseLink, including the following:
 
This section introduces direct mapping concepts unique to EclipseLink, including the following:
 
* [[#Directionality|Directionality]]
 
* [[#Directionality|Directionality]]
 
* [[#Converters and Transformers|Converters and Transformers]]
 
* [[#Converters and Transformers|Converters and Transformers]]
 
  
  
 
===Directionality===
 
===Directionality===
 
 
The direction of a relationship may be either unidirectional or bidirectional. In a unidirectional relationship, only one entity bean has a relationship field that refers to the other. All EclipseLink relational mappings are unidirectional, from the class being described (the ''source'' class) to the class with which it is associated (the ''target'' class). The target class does not have a reference to the source class in a unidirectional relationship.
 
The direction of a relationship may be either unidirectional or bidirectional. In a unidirectional relationship, only one entity bean has a relationship field that refers to the other. All EclipseLink relational mappings are unidirectional, from the class being described (the ''source'' class) to the class with which it is associated (the ''target'' class). The target class does not have a reference to the source class in a unidirectional relationship.
  
 
In a bidirectional relationship, each entity bean has a relationship field that refers to the other bean. Through the relationship field, an entity bean's code can access its related object. To implement a bidirectional relationship (classes that reference each other), use two unidirectional mappings with the sources and targets reversed.
 
In a bidirectional relationship, each entity bean has a relationship field that refers to the other bean. Through the relationship field, an entity bean's code can access its related object. To implement a bidirectional relationship (classes that reference each other), use two unidirectional mappings with the sources and targets reversed.
 
  
  
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
| align="left" |
 
| align="left" |
'''Note:''' Maintenance of bidirectional relationships presents a number of technical challenges. For more information, see the following:
+
'''Note:''' Maintenance of bidirectional relationships presents a number of technical challenges.  
* [[Configuring%20a%20Mapping%20(ELUG)|Configuring Bidirectional Relationship]]
+
 
* [[Introduction%20to%20Mappings%20(ELUG)|Indirection (Lazy Loading)]]
+
For more information, see the following:
 +
* [[Configuring%20a%20Mapping%20(ELUG)#Configuring Bidirectional Relationship|Configuring Bidirectional Relationship]]
 +
* [[Introduction%20to%20Mappings%20(ELUG)#Indirection (Lazy Loading)|Indirection (Lazy Loading)]]
 
|}
 
|}
 +
  
 
===Converters and Transformers===
 
===Converters and Transformers===
 
 
You can store object attributes directly in a database table as follows:
 
You can store object attributes directly in a database table as follows:
 
+
* [[#Using a Direct Mapping|Direct mapping ]]
* Direct mapping (see [[#Using a Direct Mapping]])
+
* [[#Using a Converter Mapping|Converter Mapping ]]
* Converter Mapping (see [[#Using a Converter Mapping]])
+
* [[#Using a Transformation Mapping|Transformation mapping ]]
* Transformation mapping (see [[#Using a Transformation Mapping]])
+
 
+
  
  
 
====Using a Direct Mapping====
 
====Using a Direct Mapping====
 
+
If the attribute type is comparable to a database type, the information can be stored directly simply by using a [[#Direct-to-Field Mapping|Direct-to-Field Mapping]].
If the attribute type is comparable to a database type, the information can be stored directly simply by using a direct-to-field mapping (see [[#Direct-to-Field Mapping|Direct-to-Field Mapping]]).
+
 
+
  
  
 
====Using a Converter Mapping====
 
====Using a Converter Mapping====
 
+
If the attribute type is comparable to a database type but requires conversion, the information can be stored directly by using a [[#Direct-to-Field Mapping|Direct-to-Field Mapping]] and an appropriate <tt>Converter</tt> instance.
If the attribute type is comparable to a database type but requires conversion, the information can be stored directly by using a direct-to-field mapping (see [[#Direct-to-Field Mapping]]) and an appropriate <tt>Converter</tt> instance.
+
 
+
In the previous release, EclipseLink provided subclasses of <tt>DirectToFieldMapping</tt> for object type direct mappings, serialized object direct mappings, and type conversion direct mappings. In this release, these subclasses are deprecated. In their place, we recommend that you use the <tt>DirectToFieldMapping</tt> method <tt>setConverter</tt> and the corresponding <tt>Converter</tt> instance. This table summarizes these changes.
+
 
+
 
+
 
+
<span id="Table 32-2"></span>
+
''''' Using a Converter for Direct-to-Field Mappings'''''
+
 
+
{| class="HRuleFormal" dir="ltr" title="Using a Converter for Direct-to-Field Mappings" summary="This table summarizes the replacement Converter instances you use instead of the deprecated subclasses of DirectToFieldMapping." width="100%" border="1" frame="hsides" rules="rows" cellpadding="3" frame="hsides" rules="rows"
+
|- align="left" valign="top"
+
! id="r1c1-t4" align="left" valign="bottom" | '''Deprecated DirectToFieldMapping subclass...'''
+
! id="r1c2-t4" align="left" valign="bottom" | '''Replaced by Converter instance...'''
+
|- align="left" valign="top"
+
| id="r2c1-t4" headers="r1c1-t4" align="left" |
+
<tt>ObjectTypeMapping</tt>
+
| headers="r2c1-t4 r1c2-t4" align="left" |
+
<tt>ObjectTypeConverter</tt> (see [[Introduction%20to%20Mappings%20(ELUG)|Object Type Converter]])
+
|- align="left" valign="top"
+
| id="r3c1-t4" headers="r1c1-t4" align="left" |
+
<tt>SerializedObjectMapping</tt>
+
| headers="r3c1-t4 r1c2-t4" align="left" |
+
<tt>SerializedObjectConverter</tt> (see [[Introduction%20to%20Mappings%20(ELUG)|Serialized Object Converter]])
+
|- align="left" valign="top"
+
| id="r4c1-t4" headers="r1c1-t4" align="left" |
+
<tt>TypeConversionMapping</tt>
+
| headers="r4c1-t4 r1c2-t4" align="left" |
+
<tt>TypeConversionConverter</tt> (see [[Introduction%20to%20Mappings%20(ELUG)|Type Conversion Converter]]
+
|}
+
 
+
 
+
  
 
If the application's objects contain attributes that cannot be represented as direct-to-field with an existing converter, use a direct-to-field mapping with a custom converter.
 
If the application's objects contain attributes that cannot be represented as direct-to-field with an existing converter, use a direct-to-field mapping with a custom converter.
 
  
  
 
====Using a Transformation Mapping====
 
====Using a Transformation Mapping====
 
 
If there is no database primitive type that is logically comparable to the attribute's type, or, if an attribute requires data from multiple fields, it must be transformed on its way to and from the database.
 
If there is no database primitive type that is logically comparable to the attribute's type, or, if an attribute requires data from multiple fields, it must be transformed on its way to and from the database.
  
In this case, use a transformation mapping (see [[#Transformation Mapping]]).
+
In this case, use a [[#Transformation Mapping| transformation mapping]].
  
  
  
 
==Direct-to-Field Mapping==
 
==Direct-to-Field Mapping==
 
 
Use direct-to-field mappings to map primitive object attributes, or non persistent regular objects, such as the JDK classes. For example, use a direct-to-field mapping to store a <tt>String</tt> attribute in a <tt>VARCHAR</tt> field.
 
Use direct-to-field mappings to map primitive object attributes, or non persistent regular objects, such as the JDK classes. For example, use a direct-to-field mapping to store a <tt>String</tt> attribute in a <tt>VARCHAR</tt> field.
  
Line 218: Line 178:
 
''''' Direct-to-Field Mapping Example'''''
 
''''' Direct-to-Field Mapping Example'''''
  
[[#Figure 32-1|Direct-to-Field Mapping]] illustrates a direct-to-field mapping between the Java attribute <tt>city</tt> and the relational database column <tt>CITY</tt>. Similarly, direct-to-field mappings could be defined from <tt>country</tt> to <tt>COUNTRY</tt>, <tt>id</tt> to <tt>ADDRESS_ID</tt>, <tt>established</tt> to <tt>EST_DATE</tt>, and <tt>province</tt> to <tt>PROVINCE</tt>.
+
The [[#Figure 32-1|Direct-to-Field Mapping]] figure illustrates a direct-to-field mapping between the Java attribute <tt>city</tt> and the relational database column <tt>CITY</tt>. Similarly, direct-to-field mappings could be defined from <tt>country</tt> to <tt>COUNTRY</tt>, <tt>id</tt> to <tt>ADDRESS_ID</tt>, <tt>established</tt> to <tt>EST_DATE</tt>, and <tt>province</tt> to <tt>PROVINCE</tt>.
  
  
Line 228: Line 188:
 
You can use a direct-to-field mapping with any of the following <tt>Converter</tt> instances:
 
You can use a direct-to-field mapping with any of the following <tt>Converter</tt> instances:
  
* [[Introduction%20to%20Mappings%20(ELUG)|Object Type Converter]]
+
* [[Introduction%20to%20Mappings%20(ELUG)#Object Type Converter|Object Type Converter]]
* [[Introduction%20to%20Mappings%20(ELUG)|Serialized Object Converter]]
+
* [[Introduction%20to%20Mappings%20(ELUG)#Serialized Object Converter|Serialized Object Converter]]
* [[Introduction%20to%20Mappings%20(ELUG)|Type Conversion Converter]]
+
* [[Introduction%20to%20Mappings%20(ELUG)#|Type Conversion Converter|Type Conversion Converter]]
  
You can use a direct-to-field mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Change Policy|Configuring Change Policy]].
+
You can use a direct-to-field mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]].
  
 
See [[Configuring%20a%20Relational%20Direct-to-Field%20Mapping (ELUG)|Configuring a Relational Direct-to-Field Mapping]] for more information.
 
See [[Configuring%20a%20Relational%20Direct-to-Field%20Mapping (ELUG)|Configuring a Relational Direct-to-Field Mapping]] for more information.
 +
 +
  
 
==Direct-to-XMLType Mapping==
 
==Direct-to-XMLType Mapping==
Line 245: Line 207:
  
 
See [[Configuring%20a%20Relational%20Direct-to-XMLType%20Mapping (ELUG)|Configuring a Relational Direct-to-XMLType Mapping]] for more information.
 
See [[Configuring%20a%20Relational%20Direct-to-XMLType%20Mapping (ELUG)|Configuring a Relational Direct-to-XMLType Mapping]] for more information.
 +
 +
  
 
==One-to-One Mapping==
 
==One-to-One Mapping==
Line 250: Line 214:
 
One-to-one mappings represent simple pointer references between two Java objects. In Java, a single pointer stored in an attribute represents the mapping between the source and target objects. Relational database tables implement these mappings using foreign keys.
 
One-to-one mappings represent simple pointer references between two Java objects. In Java, a single pointer stored in an attribute represents the mapping between the source and target objects. Relational database tables implement these mappings using foreign keys.
  
[[#Figure 32-2|One-to-One Mappings]] illustrates a one-to-one relationship from the <tt>address</tt> attribute of an <tt>Employee</tt> object to an <tt>Address</tt> object. To store this relationship in the database, create a one-to-one mapping between the <tt>address</tt> attribute and the <tt>Address</tt> class. This mapping stores the <tt>id</tt> of the <tt>Address</tt> instance in the <tt>EMPLOYEE</tt> table when the <tt>Employee</tt> instance is written. It also links the <tt>Employee</tt> instance to the <tt>Address</tt> instance when the <tt>Employee</tt> is read from the database. Because an <tt>Address</tt> does not have any references to the <tt>Employee</tt>, it does not have to provide a mapping to <tt>Employee</tt>.
+
The [[#Figure 32-2|One-to-One Mappings]] figure illustrates a one-to-one relationship from the <tt>address</tt> attribute of an <tt>Employee</tt> object to an <tt>Address</tt> object. To store this relationship in the database, create a one-to-one mapping between the <tt>address</tt> attribute and the <tt>Address</tt> class. This mapping stores the <tt>id</tt> of the <tt>Address</tt> instance in the <tt>EMPLOYEE</tt> table when the <tt>Employee</tt> instance is written. It also links the <tt>Employee</tt> instance to the <tt>Address</tt> instance when the <tt>Employee</tt> is read from the database. Because an <tt>Address</tt> does not have any references to the <tt>Employee</tt>, it does not have to provide a mapping to <tt>Employee</tt>.
  
For one-to-one mappings, the source table normally contains a foreign key reference to a record in the target table. In [[#Figure 32-2|One-to-One Mappings]], the <tt>ADDR_ID</tt> field of the <tt>EMPLOYEE</tt> table is a foreign key.
+
For one-to-one mappings, the source table normally contains a foreign key reference to a record in the target table. In the [[#Figure 32-2|One-to-One Mappings]] figure, the <tt>ADDR_ID</tt> field of the <tt>EMPLOYEE</tt> table is a foreign key.
  
  
Line 260: Line 224:
 
[[Image:onetoone_map_fig.gif|One-to-One Mappings]]
 
[[Image:onetoone_map_fig.gif|One-to-One Mappings]]
  
You can also implement a one-to-one mapping where the target table contains a foreign key reference to the source table. In [[#Figure 32-2|One-to-One Mappings]], the database design would change such that the <tt>ADDRESS</tt> row would contain the <tt>EMP_ID</tt> to identify the <tt>Employee</tt> to which it belonged. In this case, the target must also have a relationship mapping to the source.
+
You can also implement a one-to-one mapping where the target table contains a foreign key reference to the source table. In the [[#Figure 32-2|One-to-One Mappings]] figure, the database design would change such that the <tt>ADDRESS</tt> row would contain the <tt>EMP_ID</tt> to identify the <tt>Employee</tt> to which it belonged. In this case, the target must also have a relationship mapping to the source.
  
The update, insert and delete operations, which are normally done for the target before the source for privately owned one-to-one relationships, are performed in the opposite order when the target owns the foreign key. Target foreign keys normally occur in bidirectional one-to-one mappings (see [[#Directionality]]), because one side has a foreign key and the other shares the same foreign key in the other's table.
+
The update, insert and delete operations, which are normally done for the target before the source for privately owned one-to-one relationships, are performed in the opposite order when the target owns the foreign key. Target foreign keys normally occur in bidirectional one-to-one mappings (see [[#Directionality|Directionality]]), because one side has a foreign key and the other shares the same foreign key in the other's table.
  
 
Target foreign keys can also occur when large cascaded composite primary keys exist (that is, one object's primary key is composed of the primary key of many other objects). In this case it is possible to have a one-to-one mapping that contains both foreign keys and target foreign keys.
 
Target foreign keys can also occur when large cascaded composite primary keys exist (that is, one object's primary key is composed of the primary key of many other objects). In this case it is possible to have a one-to-one mapping that contains both foreign keys and target foreign keys.
Line 272: Line 236:
 
In a bidirectional relationship where the two classes in the relationship reference each other, only one of the mappings should have a foreign key. The other mapping should have a target foreign key. If one of the mappings in a bidirectional relationship is a one-to-many mapping, see [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)|Configuring a Relational Variable One-to-One Mapping]] for details.
 
In a bidirectional relationship where the two classes in the relationship reference each other, only one of the mappings should have a foreign key. The other mapping should have a target foreign key. If one of the mappings in a bidirectional relationship is a one-to-many mapping, see [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)|Configuring a Relational Variable One-to-One Mapping]] for details.
  
You can use a one-to-one mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Change Policy]].
+
You can use a one-to-one mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]].
  
 
See [[Configuring%20a%20Relational%20One-to-One%20Mapping%20(ELUG)|Configuring a Relational One-to-One Mapping]] for more information.
 
See [[Configuring%20a%20Relational%20One-to-One%20Mapping%20(ELUG)|Configuring a Relational One-to-One Mapping]] for more information.
 +
 +
  
 
==Variable One-to-One Mapping==
 
==Variable One-to-One Mapping==
Line 284: Line 250:
 
EclipseLink supports variable relationships only in one-to-one mappings. It handles this relationship in two ways:
 
EclipseLink supports variable relationships only in one-to-one mappings. It handles this relationship in two ways:
  
* Through the class indicator field (see [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)|Configuring Class Indicator]]).
+
* Through the class indicator field (see [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)#Configuring Class Indicator|Configuring Class Indicator]]).
* Through unique primary key values among target classes implementing the interface (see [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)|Configuring Unique Primary Key]]).
+
* Through unique primary key values among target classes implementing the interface (see [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)#Configuring Unique Primary Key|Configuring Unique Primary Key]]).
  
  
Line 293: Line 259:
 
[[Image:v11mapfig.gif|Variable One-to-One Mappings with Class Indicator]]
 
[[Image:v11mapfig.gif|Variable One-to-One Mappings with Class Indicator]]
  
See [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)|Chapter 37, "Configuring a Relational Variable One-to-One Mapping"]] for more information.
+
See [[Configuring%20a%20Relational%20Variable%20One-to-One%20Mapping%20(ELUG)|Configuring a Relational Variable One-to-One Mapping]] for more information.
  
==One-to-Many Mapping==
 
  
 +
 +
==One-to-Many Mapping==
 
One-to-many mappings are used to represent the relationship between a single source object and a collection of target objects. They are a good example of something that is simple to implement in Java using a <tt>Collection</tt> (or other collection types) of target objects, but difficult to implement using relational databases.
 
One-to-many mappings are used to represent the relationship between a single source object and a collection of target objects. They are a good example of something that is simple to implement in Java using a <tt>Collection</tt> (or other collection types) of target objects, but difficult to implement using relational databases.
  
Line 302: Line 269:
  
 
The purpose of creating this one-to-one mapping in the target is so that the foreign key information can be written when the target object is saved. Alternatives to the one-to-one mapping back reference include the following:
 
The purpose of creating this one-to-one mapping in the target is so that the foreign key information can be written when the target object is saved. Alternatives to the one-to-one mapping back reference include the following:
 
 
* Use a direct-to-field mapping to map the foreign key and maintain its value in the application. Here the object model does not require a back reference, but the data model still requires a foreign key in the target table.
 
* Use a direct-to-field mapping to map the foreign key and maintain its value in the application. Here the object model does not require a back reference, but the data model still requires a foreign key in the target table.
 
* Use a many-to-many mapping to implement a logical one-to-many. This has the advantage of not requiring a back reference in the object model and not requiring a foreign key in the data model. In this model the many-to-many relation table stores the collection. It is possible to put a constraint on the join table to enforce that the relation is a logical one-to-many relationship.
 
* Use a many-to-many mapping to implement a logical one-to-many. This has the advantage of not requiring a back reference in the object model and not requiring a foreign key in the data model. In this model the many-to-many relation table stores the collection. It is possible to put a constraint on the join table to enforce that the relation is a logical one-to-many relationship.
Line 311: Line 277:
  
 
[[Image:onetomany_map_fig.gif|One-to-Many Relationships]]
 
[[Image:onetomany_map_fig.gif|One-to-Many Relationships]]
 +
  
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
| align="left" |
 
| align="left" |
'''''Note''''': The <tt>phone</tt> attribute shown in [[#Figure 32-4|One-to-Many Relationships]] is of type <tt>Vector</tt>. You can use a <tt>Collection</tt> interface (or any class that implements the <tt>Collection</tt> interface) for declaring the collection attribute. See [[Configuring%20a%20Mapping%20(ELUG)#Configuring Container Policy|Configuring Container Policy]] for details.
+
'''''Note''''': The <tt>phone</tt> attribute shown in the [[#Figure 32-4|One-to-Many Relationships]] is of type <tt>Vector</tt>. You can use a <tt>Collection</tt> interface (or any class that implements the <tt>Collection</tt> interface) for declaring the collection attribute. See [[Configuring%20a%20Mapping%20(ELUG)#Configuring Container Policy|Configuring Container Policy]] for details.
 
|}
 
|}
  
  
 
+
You can use a many-to-many mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]].
You can use a many-to-many mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|Configuring Change Policy]].
+
  
 
See [[Configuring%20a%20Relational%20One-to-Many%20Mapping (ELUG)|Configuring a Relational One-to-Many Mapping]] for more information.
 
See [[Configuring%20a%20Relational%20One-to-Many%20Mapping (ELUG)|Configuring a Relational One-to-Many Mapping]] for more information.
 +
 +
  
 
==Many-to-Many Mapping==
 
==Many-to-Many Mapping==
 
 
Many-to-many mappings represent the relationships between a collection of source objects and a collection of target objects. They require the creation of an intermediate table for managing the associations between the source and target records.
 
Many-to-many mappings represent the relationships between a collection of source objects and a collection of target objects. They require the creation of an intermediate table for managing the associations between the source and target records.
  
Line 334: Line 301:
  
 
[[Image:mmmapfig.gif|Many-to-many Relationships]]
 
[[Image:mmmapfig.gif|Many-to-many Relationships]]
 +
  
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
| align="left" |
 
| align="left" |
'''''Note''''': The <tt>projects</tt> attribute shown in [[#Figure 32-5|Many-to-many Relationships]] is of type <tt>Vector</tt>. You can use a <tt>Collection</tt> interface (or any class that implements the <tt>Collection</tt> interface) for declaring the collection attribute. See [[Configuring%20a%20Mapping%20(ELUG)|Configuring Container Policy]] for details.
+
'''''Note''''': The <tt>projects</tt> attribute shown in the [[#Figure 32-5|Many-to-many Relationships]] figure is of type <tt>Vector</tt>. You can use a <tt>Collection</tt> interface (or any class that implements the <tt>Collection</tt> interface) for declaring the collection attribute. See [[Configuring%20a%20Mapping%20(ELUG)#Configuring Container Policy|Configuring Container Policy]] for details.
 
|}
 
|}
 
  
  
Line 346: Line 313:
 
The target class does not have to implement any behavior for the many-to-many mappings. If the target class also creates a many-to-many mapping back to its source, then it can use the same relation table, but one of the mappings must be set to read-only. If both mappings write to the table, they can cause collisions.
 
The target class does not have to implement any behavior for the many-to-many mappings. If the target class also creates a many-to-many mapping back to its source, then it can use the same relation table, but one of the mappings must be set to read-only. If both mappings write to the table, they can cause collisions.
  
Indirection (lazy loading) is enabled by default in a many-to-many mapping, which requires that the attribute have the <tt>ValueHolderInterface</tt> type or transparent collections. For more information on indirection, see [[Introduction%20to%20Mappings%20(ELUG)|Indirection (Lazy Loading)]].
+
Indirection (lazy loading) is enabled by default in a many-to-many mapping, which requires that the attribute have the <tt>ValueHolderInterface</tt> type or transparent collections. For more information on indirection, see [[Introduction%20to%20Mappings%20(ELUG)#Indirection (Lazy Loading)|Indirection (Lazy Loading)]].
  
You can use a many-to-many mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Change Policy]].
+
You can use a many-to-many mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]]).
  
See [[Configuring%20a%20Relational%20Many-to-Many%20(ELUG)|Chapter 39, "Configuring a Relational Many-to-Many Mapping"]] for more information.
+
See [[Configuring%20a%20Relational%20Many-to-Many%20Mapping (ELUG)#Configuring Change Policy|Configuring a Relational Many-to-Many Mapping]] for more information.
  
==Aggregate Collection Mapping==
 
  
 +
 +
==Aggregate Collection Mapping==
 
Aggregate collection mappings are used to represent the aggregate relationship between a single-source object and a collection of target objects. Unlike the EclipseLink one-to-many mappings, in which there should be a one-to-one back reference mapping from the target objects to the source object, there is no back reference required for the aggregate collection mappings, because the foreign key relationship is resolved by the aggregation.
 
Aggregate collection mappings are used to represent the aggregate relationship between a single-source object and a collection of target objects. Unlike the EclipseLink one-to-many mappings, in which there should be a one-to-one back reference mapping from the target objects to the source object, there is no back reference required for the aggregate collection mappings, because the foreign key relationship is resolved by the aggregation.
 
  
  
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
| align="left" |
 
| align="left" |
'''Note'''<nowiki>:</nowiki> To use aggregate collections with Workbench, you must use an amendment method (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Amendment Methods]]), or manually edit the project source to add the mapping.
+
'''Note'''<nowiki>:</nowiki> To use aggregate collections with Workbench, you must use an amendment method (see [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Amendment Methods|Configuring Amendment Methods]]), or manually edit the project source to add the mapping.
 
|}
 
|}
  
  
 
+
Although aggregate collection mappings are similar to one-to-many mappings, they are not replacements for one-to-many mappings. Use aggregate collections only in situations where the target collections are of a reasonable size and if having a many-to-one back mapping is difficult.
Although aggregate collection mappings are similar to one-to-many mappings, they are not replacements for one-to-many mappings. Use aggregate collections only in situations where the target collections are of a reasonable size and if having a one-to-one back mapping is difficult.
+
  
 
Because one-to-many relationships offer better performance and are more robust and scalable, consider using a one-to-many relationship rather than an aggregate collection. In addition, aggregate collections are privately owned by the source of the relationship and must not be shared or referenced by other objects.
 
Because one-to-many relationships offer better performance and are more robust and scalable, consider using a one-to-many relationship rather than an aggregate collection. In addition, aggregate collections are privately owned by the source of the relationship and must not be shared or referenced by other objects.
  
 
This section describes the following:
 
This section describes the following:
 +
* [[#Aggregate Collection Mappings and Inheritance|Aggregate Collection Mappings and Inheritance]]
 +
* [[#Aggregate Collection Mappings and EJB|Aggregate Collection Mappings and EJB]]
 +
* [[#How to Implement Aggregate Collection Mapping|How to Implement Aggregate Collection Mappings]]
  
* [[#Aggregate Collection Mappings and Inheritance]]
+
See [[Configuring%20a%20Relational%20Aggregate%20Collection%20Mapping%20(ELUG)|Configuring a Relational Aggregate Collection Mapping]] for more information.
* [[#Aggregate Collection Mappings and EJB]]
+
* [[#How to Implement Aggregate Collection Mappings]]
+
 
+
See [[Configuring%20a%20Relational%20Aggregate%20Collection%20Mapping%20(ELUG).|Configuring a Relational Aggregate Collection Mapping]] for more information.
+
 
+
  
  
 
===Aggregate Collection Mappings and Inheritance===
 
===Aggregate Collection Mappings and Inheritance===
 
 
Aggregate collection descriptors can use inheritance. You must also declare subclasses as aggregate collection. The subclasses can have their own mapped tables, or share the table with their parent class. See [[Introduction%20to%20Descriptors%20(ELUG)|Descriptors and Inheritance]] for more information on inheritance.
 
Aggregate collection descriptors can use inheritance. You must also declare subclasses as aggregate collection. The subclasses can have their own mapped tables, or share the table with their parent class. See [[Introduction%20to%20Descriptors%20(ELUG)|Descriptors and Inheritance]] for more information on inheritance.
 
In a Java <tt>Collection</tt>, the owner references its parts. In a relational database, the parts reference their owners. Relational databases use this implementation to make querying more efficient.
 
 
Aggregate collection mappings require a target table for the target objects.
 
 
To implement an aggregate collection mapping, the following must take place:
 
 
* The descriptor of the target class must declare itself as an aggregate collection object. Unlike the aggregate object mapping, in which the target descriptor does not have a specific table to associate with, there must be a target table for the target object.
 
* The descriptor of the source class must add an aggregate collection mapping that specifies the target class.
 
 
 
  
 
===Aggregate Collection Mappings and EJB===
 
===Aggregate Collection Mappings and EJB===
 
 
You can use aggregate collection mappings with entity beans if the source of the relationship is an entity bean or Java object, and the mapping targets are regular Java objects. Entity beans cannot be the target of an aggregate object mapping.
 
You can use aggregate collection mappings with entity beans if the source of the relationship is an entity bean or Java object, and the mapping targets are regular Java objects. Entity beans cannot be the target of an aggregate object mapping.
 
  
  
 
===How to Implement Aggregate Collection Mappings===
 
===How to Implement Aggregate Collection Mappings===
 +
 +
In a Java <tt>Collection</tt>, the owner references its parts. In a relational database, the parts reference their owners. Relational databases use this implementation to make querying more efficient.
 +
 +
Aggregate collection mappings require a target table for the target objects.
  
 
To implement an aggregate collection mapping, the following must take place:
 
To implement an aggregate collection mapping, the following must take place:
Line 408: Line 362:
  
 
==Direct Collection Mapping==
 
==Direct Collection Mapping==
 
 
Direct collection mappings store collections of Java objects that are not EclipseLink-enabled. The object type stored in the direct collection is typically a Java type, such as <tt>String</tt>.
 
Direct collection mappings store collections of Java objects that are not EclipseLink-enabled. The object type stored in the direct collection is typically a Java type, such as <tt>String</tt>.
  
Line 415: Line 368:
 
Support for primitive data types such as <tt>int</tt> is not provided, because Java <tt>Collection</tt> holds only objects.
 
Support for primitive data types such as <tt>int</tt> is not provided, because Java <tt>Collection</tt> holds only objects.
  
[[#Figure 32-6|Direct Collection Mappings]] illustrates how a direct collection is stored in a separate table with two fields. The first field is the reference key field, which contains a reference to the primary key of the instance owning the collection. The second field contains an object in the collection and is called the direct field. There is one record in the table for each object in the collection.
+
The [[#Figure 32-6|Direct Collection Mappings]] figure illustrates how a direct collection is stored in a separate table with two fields. The first field is the reference key field, which contains a reference to the primary key of the instance owning the collection. The second field contains an object in the collection and is called the direct field. There is one record in the table for each object in the collection.
  
  
Line 422: Line 375:
  
 
[[Image:dcmapfig.gif|Direct Collection Mappings ]]
 
[[Image:dcmapfig.gif|Direct Collection Mappings ]]
 +
  
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
| align="left" |
 
| align="left" |
'''''Note''''': The <tt>responsibilities</tt> attribute shown in [[#Figure 32-6|Direct Collection Mappings]] is of type <tt>Vector</tt>. You can use a <tt>Collection</tt> interface (or any class that implements the <tt>Collection</tt> interface) for declaring the collection attribute. See [[Configuring%20a%20Mapping%20(ELUG)|Configuring Container Policy]] for details.
+
'''''Note''''': The <tt>responsibilities</tt> attribute shown in the [[#Figure 32-6|Direct Collection Mappings]] figure is of type <tt>Vector</tt>. You can use a <tt>Collection</tt> interface (or any class that implements the <tt>Collection</tt> interface) for declaring the collection attribute. See [[Configuring%20a%20Mapping%20(ELUG)#Configuring Container Policy|Configuring Container Policy]] for details.
 
|}
 
|}
 
  
  
Line 433: Line 386:
  
 
You can use a direct collection mapping with any of the following <tt>Converter</tt> instances:
 
You can use a direct collection mapping with any of the following <tt>Converter</tt> instances:
 +
* [[Introduction%20to%20Mappings%20(ELUG)#Object Type Converter|Object Type Converter]]
 +
* [[Introduction%20to%20Mappings%20(ELUG)#Serialized Object Converter|Serialized Object Converter]]
 +
* [[Introduction%20to%20Mappings%20(ELUG)#Type Conversion Converter|Type Conversion Converter]]
  
* [[Introduction%20to%20Mappings%20(ELUG)|Object Type Converter]]
+
You can use a direct collection mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]]).
* [[Introduction%20to%20Mappings%20(ELUG)|Serialized Object Converter]]
+
* [[Introduction%20to%20Mappings%20(ELUG)|Type Conversion Converter]]
+
  
You can use a direct collection mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Change Policy]]).
+
See [[Configuring%20a%20Relational%20Direct%20Collection%20Mapping (ELUG)|Configuring a Relational Direct Collection Mapping]] for more information.
  
See [[Configuring%20a%20Relational%20Direct%20Collection%20(ELUG)|Chapter 41, "Configuring a Relational Direct Collection Mapping] for more information.
 
  
==Direct Map Mapping==
 
  
 +
==Direct Map Mapping==
 
Direct map mappings store instances that implement <tt>java.util.Map</tt>. 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 are Java primitive wrapper types such as <tt>String</tt> objects.
 
Direct map mappings store instances that implement <tt>java.util.Map</tt>. 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 are Java primitive wrapper types such as <tt>String</tt> objects.
  
[[#Figure 32-7|Direct Map Mappings]] illustrates how a direct map is stored in a separate table with three fields. The first field (<tt>EMPID</tt>) is the reference key field, which contains a reference to the primary key of the instance owning the collection. The second field (<tt>ADDRESS</tt>) contains an object in the collection and is called the direct value field. The third field (<tt>TYPE</tt>) contains the direct key field. In this example, the direct map uses a object type converter for the direct key field, converting the single character '''W''' in the database to the full string '''Work''' in the object (and '''H''' to '''Home''').
+
The [[#Figure 32-7|Direct Map Mappings]] figure illustrates how a direct map is stored in a separate table with three fields. The first field (<tt>EMPID</tt>) is the reference key field, which contains a reference to the primary key of the instance owning the collection. The second field (<tt>ADDRESS</tt>) contains an object in the collection and is called the direct value field. The third field (<tt>TYPE</tt>) contains the direct key field. In this example, the direct map uses a object type converter for the direct key field, converting the single character '''W''' in the database to the full string '''Work''' in the object (and '''H''' to '''Home''').
  
  
Line 455: Line 408:
  
 
You can use a direct collection mapping with any of the following <tt>Converter</tt> instances:
 
You can use a direct collection mapping with any of the following <tt>Converter</tt> instances:
 +
* [[Introduction%20to%20Mappings%20(ELUG)#Object Type Converter|Object Type Converter]]
 +
* [[Introduction%20to%20Mappings%20(ELUG)#Serialized Object Converter|Serialized Object Converter]]
 +
* [[Introduction%20to%20Mappings%20(ELUG)#|Type Conversion Converter|Type Conversion Converter]]
  
* [[Introduction%20to%20Mappings%20(ELUG)|Object Type Converter]]
+
You can use a direct map mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]]).
* [[Introduction%20to%20Mappings%20(ELUG)|Serialized Object Converter]]
+
* [[Introduction%20to%20Mappings%20(ELUG)|Type Conversion Converter]]
+
  
You can use a direct map mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Change Policy]]).
+
See [[Configuring%20a%20Relational%20Direct%20Map%20Mapping%20(ELUG)|Configuring a Relational Direct Map Mapping]] for more information.
 
+
See [[Configuring%20a%20Relational%20Direct%20Map%20Mapping%20(ELUG)|Chapter 43, "Configuring a Relational Direct Map Mapping"]] for more information.
+
  
  
  
 
==Aggregate Object Mapping==
 
==Aggregate Object Mapping==
 
 
Two objects–a source (parent or owning) object and a target (child or owned) object–are related by aggregation if there is a strict one-to-one relationship between them and all the attributes of the target object can be retrieved from the same table(s) as the source object. This means that if the source object exists, then the target object must also exist and if the source object is destroyed, then the target object is also destroyed.
 
Two objects–a source (parent or owning) object and a target (child or owned) object–are related by aggregation if there is a strict one-to-one relationship between them and all the attributes of the target object can be retrieved from the same table(s) as the source object. This means that if the source object exists, then the target object must also exist and if the source object is destroyed, then the target object is also destroyed.
  
 
An aggregate mapping allows you to associate data members in the target object with fields in the source object's underlying database tables.
 
An aggregate mapping allows you to associate data members in the target object with fields in the source object's underlying database tables.
  
You configure the aggregate mapping in the source object's descriptor. However, before doing so, you must designate the target object's descriptor as an aggregate (see [[Configuring%20a%20Relational%20Descriptor%20(ELUG)|Configuring a Relational Descriptor as a Class or Aggregate Type]]).
+
You configure the aggregate mapping in the source object's descriptor. However, before doing so, you must designate the target object's descriptor as an aggregate (see [[Configuring%20a%20Relational%20Descriptor%20(ELUG)#Configuring a Relational Descriptor as a Class or Aggregate Type|Configuring a Relational Descriptor as a Class or Aggregate Type]]).
  
 
Aggregate objects are privately owned and should not be shared or referenced by other objects.
 
Aggregate objects are privately owned and should not be shared or referenced by other objects.
Line 480: Line 431:
 
You can configure such mappings from an aggregate target object to another nonaggregate object. If you configure a one-to-many mapping from an aggregate target object to another nonaggregate object, you must configure a one-to-one mapping from the other object back to the source object that owns the aggregate (instead of to the aggregate target object itself). This is because the source object contains the table and primary key information of the aggregate target.
 
You can configure such mappings from an aggregate target object to another nonaggregate object. If you configure a one-to-many mapping from an aggregate target object to another nonaggregate object, you must configure a one-to-one mapping from the other object back to the source object that owns the aggregate (instead of to the aggregate target object itself). This is because the source object contains the table and primary key information of the aggregate target.
  
You can configure inheritance for a descriptor designated as an aggregate (see [[Introduction%20to%20Descriptors%20(ELUG)|Descriptors and Inheritance]]), however, in this case, ''all'' the descriptors in the inheritance tree must be aggregates. Aggregate and class descriptors cannot exist in the same inheritance tree.
+
You can configure inheritance for a descriptor designated as an aggregate (see [[Introduction%20to%20Descriptors%20(ELUG)#Descriptors and Inheritance|Descriptors and Inheritance]]), however, in this case, ''all'' the descriptors in the inheritance tree must be aggregates. Aggregate and class descriptors cannot exist in the same inheritance tree.
  
 
This section describes the following:
 
This section describes the following:
  
* [[#Aggregate Object Mappings with a Single Source Object]]
+
* [[#Aggregate Object Mappings with a Single Source Object|Aggregate Object Mappings with a Single Source Object]]
* [[#Aggregate Object Mappings with Multiple Source Objects]]
+
* [[#Aggregate Object Mappings with Multiple Source Objects|Aggregate Object Mappings with Multiple Source Objects]]
* [[#How to Implement an Aggregate Object Relationship Mapping]]
+
* [[#How to Implement an Aggregate Object Relationship Mapping|How to Implement an Aggregate Object Relationship Mapping]]
  
You can use an aggregate object mapping with a change policy (see [[Configuring%20a%20Descriptor%20(ELUG)|Configuring Change Policy]].
+
You can use an aggregate object mapping with a [[Configuring%20a%20Descriptor%20(ELUG)#Configuring Change Policy|change policy]].
 
+
For more information on configuring an aggregate object relationship mapping, see [[Configuring%20a%20Relational%20Aggregate%20Object%20|Configuring a Relational Aggregate Object Mapping]].
+
  
 +
For more information on configuring an aggregate object relationship mapping, see [[Configuring%20a%20Relational%20Aggregate%20Object%20Mapping (ELUG)|Configuring a Relational Aggregate Object Mapping]].
  
  
 
===Aggregate Object Mappings with a Single Source Object===
 
===Aggregate Object Mappings with a Single Source Object===
 
+
The [[#Figure 32-8|Aggregate Object Mapping with a Single Source Object]] figure shows an example aggregate object mapping between source object <tt>Employee</tt> and target object <tt>Period</tt>. In this example, the target object is not shared by other types of source object.
[[#Figure 32-8|Aggregate Object Mapping with a Single Source Object]] shows an example aggregate object mapping between source object <tt>Employee</tt> and target object <tt>Period</tt>. In this example, the target object is not shared by other types of source object.
+
  
  
Line 505: Line 454:
  
 
Aggregate target classes not shared among multiple source classes can have any type of mapping, including other aggregate object mappings.
 
Aggregate target classes not shared among multiple source classes can have any type of mapping, including other aggregate object mappings.
 
  
  
 
===Aggregate Object Mappings with Multiple Source Objects===
 
===Aggregate Object Mappings with Multiple Source Objects===
 
+
The [[#Figure 32-9|Aggregate Object Mapping with Multiple Source Objects]] figure shows an example aggregate object mapping in which different source objects–<tt>Employee</tt> and <tt>Project</tt>–map instances of the same type of target object, <tt>Period</tt>.
[[#Figure 32-9|Aggregate Object Mapping with Multiple Source Objects]] shows an example aggregate object mapping in which different source objects–<tt>Employee</tt> and <tt>Project</tt>–map instances of the same type of target object, <tt>Period</tt>.
+
  
  
Line 520: Line 467:
 
When you configure the aggregate object mapping in the source object, you choose the source object table for that particular mapping. This allows different source types to store the same target information within their tables. Each source object's table may use different field names. EclipseLink automatically manages the case where multiple source object tables use different field names.
 
When you configure the aggregate object mapping in the source object, you choose the source object table for that particular mapping. This allows different source types to store the same target information within their tables. Each source object's table may use different field names. EclipseLink automatically manages the case where multiple source object tables use different field names.
  
For example, in [[#Figure 32-9|Aggregate Object Mapping with Multiple Source Objects]], The <tt>Employee</tt> attribute <tt>employPeriod</tt> is mapped by an aggregate object mapping to target object <tt>Period</tt>. This mapping associates <tt>Period</tt> attribute <tt>startDate</tt> with <tt>EMPLOYEE</tt> table field <tt>START_DATE</tt>. The <tt>Project</tt> attribute <tt>projectPeriod</tt> is also mapped by an aggregate object mapping to target object <tt>Period</tt>. This mapping associates <tt>Period</tt> attribute <tt>startDate</tt> with <tt>PROJECT</tt> table field <tt>S_DATE</tt>.
+
For example, in the [[#Figure 32-9|Aggregate Object Mapping with Multiple Source Objects]] figure, The <tt>Employee</tt> attribute <tt>employPeriod</tt> is mapped by an aggregate object mapping to target object <tt>Period</tt>. This mapping associates <tt>Period</tt> attribute <tt>startDate</tt> with <tt>EMPLOYEE</tt> table field <tt>START_DATE</tt>. The <tt>Project</tt> attribute <tt>projectPeriod</tt> is also mapped by an aggregate object mapping to target object <tt>Period</tt>. This mapping associates <tt>Period</tt> attribute <tt>startDate</tt> with <tt>PROJECT</tt> table field <tt>S_DATE</tt>.
  
 
Aggregate target classes shared with multiple source classes cannot have one-to-many or many-to-many mappings.
 
Aggregate target classes shared with multiple source classes cannot have one-to-many or many-to-many mappings.
 
  
  
Line 531: Line 477:
  
 
* The descriptor of the target class declares itself to be an aggregate object. Because all its information comes from its parent's table(s), the target descriptor does not have a specific table associated with it. You must, however, choose one or more candidate table(s) from which you can use fields in mapping the target.In the example above, you could choose the <tt>EMPLOYEE</tt> table so that the <tt>START_DATE</tt> and <tt>END_DATE</tt> fields are available during mapping.
 
* The descriptor of the target class declares itself to be an aggregate object. Because all its information comes from its parent's table(s), the target descriptor does not have a specific table associated with it. You must, however, choose one or more candidate table(s) from which you can use fields in mapping the target.In the example above, you could choose the <tt>EMPLOYEE</tt> table so that the <tt>START_DATE</tt> and <tt>END_DATE</tt> fields are available during mapping.
* The descriptor of the source class adds an aggregate object mapping that specifies the target class.In the example above, the <tt>Employee</tt> class has an attribute called <tt>employPeriod</tt> that would be mapped as an aggregate object mapping with <tt>Period</tt> as the reference class.The source class must ensure that its table has fields that correspond to the field names registered with the target class.
+
* The descriptor of the source class adds an aggregate object mapping that specifies the target class.<br>In the example above, the <tt>Employee</tt> class has an attribute called <tt>employPeriod</tt> that would be mapped as an aggregate object mapping with <tt>Period</tt> as the reference class.<br>The source class must ensure that its table has fields that correspond to the field names registered with the target class.
* If a source object has a <tt>null</tt> target reference, EclipseLink writes NULLs to the aggregate database fields (see [[Configuring%20a%20Relational%20Aggregate%20Object%20|Configuring Allowing Null Values]]). When the source is read from the database, it can handle this <tt>null</tt> target in one of two ways:
+
* If a source object has a <tt>null</tt> target reference, EclipseLink writes <tt>null</tt> values to the aggregate database fields (see [[Configuring%20a%20Relational%20Aggregate%20Object%20Mapping (ELUG)#Configuring Allowing Null Values|Configuring Allowing Null Values]]). When the source is read from the database, it can handle this <tt>null</tt> target in one of two ways:
 
** Create an instance of the object with all its attributes equal to <tt>null</tt>.
 
** Create an instance of the object with all its attributes equal to <tt>null</tt>.
 
** Put a <tt>null</tt> reference in the source object without instantiating a target. (This is the default method of handling <tt>null</tt> targets.)
 
** Put a <tt>null</tt> reference in the source object without instantiating a target. (This is the default method of handling <tt>null</tt> targets.)
Line 543: Line 489:
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
{| class="Note oac_no_warn" width="80%" border="1" frame="hsides" rules="groups" cellpadding="3" frame="hsides" rules="groups"
 
| align="left" |
 
| align="left" |
'''Tip'''<nowiki>:</nowiki> Use transformation mappings only when mapping multiple fields into a single attribute. Because of the complexity of transformation mappings, it is often easier to perform the transformation with a converter or getter and setter methods of a direct-to-field mapping. See [[Configuring%20a%20Relational%20Direct-to-Field%20(ELUG)|Configuring a Relational Direct-to-Field Mapping]] for more information.
+
'''Tip'''<nowiki>:</nowiki> Use transformation mappings only when mapping multiple fields into a single attribute. Because of the complexity of transformation mappings, it is often easier to perform the transformation with a converter or getter and setter methods of a direct-to-field mapping. See [[Configuring%20a%20Relational%20Direct-to-Field%20Mapping (ELUG)|Configuring a Relational Direct-to-Field Mapping]] for more information.
 
|}
 
|}
  
[[#Figure 32-10|Transformation Mappings]] illustrates a transformation mapping. The values from the <tt>B_DATE</tt> and <tt>B_TIME</tt> fields are used to create a <tt>java.util.Date</tt> to be stored in the <tt>birthDate</tt> attribute.
+
The [[#Figure 32-10|Transformation Mappings]] figure illustrates a transformation mapping. The values from the <tt>B_DATE</tt> and <tt>B_TIME</tt> fields are used to create a <tt>java.util.Date</tt> to be stored in the <tt>birthDate</tt> attribute.
  
 
<span id="'Figure 32-10"></span>
 
<span id="'Figure 32-10"></span>
'''' Transformation Mappings'''''
+
''''' Transformation Mappings'''''
  
 
[[Image:trmapfig.gif|Transformation Mappings]]
 
[[Image:trmapfig.gif|Transformation Mappings]]
Line 565: Line 511:
  
 
[[Category: EclipseLink User's Guide]]
 
[[Category: EclipseLink User's Guide]]
[[Category: Draft]]
+
[[Category: Release 1]]
 
[[Category: Concept]]
 
[[Category: Concept]]
 +
[[Category: ORM]]

Latest revision as of 05:34, 18 June 2009

Related Topics

A relational mapping transforms any object data member type to a corresponding relational database (SQL) data source representation in any supported relational database. Relational mappings let you map an object model into a relational data model.

Relational mappings transform object data members to relational database fields. Use them to map simple data types including primitives (such as int), JDK classes (such as String), and large object (LOB) values. You can also use them to transform object data members that reference other domain objects by way of association where data source representations require object identity maintenance (such as sequencing and back references) and possess various types of multiplicity and navigability. The appropriate mapping class is chosen primarily by the cardinality of the relationship.

Do not confuse relational mappings with object-relational data type mappings (see Introduction to Object-Relational Data Type Mappings). An object-relational data type mapping transforms certain object data member types to structured data source representations optimized for storage in specialized object-relational data type databases such as Oracle9i Database Server. Object-relational data type mappings let you map an object model into an object-relational data type data model. In general, you can use relational mappings with any supported relational database. You can only use object-relational data type mappings with specialized object-relational data type databases optimized to support object-relational data type data source representations.

For information on mapping concepts and features common to more than one type of EclipseLink mappings, see Introduction to Mappings.


Relational Mapping Types

EclipseLink supports the relational mappings listed in the following table.

Type of Mapping Description EclipseLink Workbench Java

Direct-to-field

Map a Java attribute directly to a database field.

Supported

Supported

Direct-to-XMLType

Map Java attributes to an XMLType column in an Oracle Database (introduced in version 9.2.0.1).

Supported

Supported

One-to-one

Map a reference to another persistent Java object to the database.

Supported

Supported

Variable one-to-one

Map a reference to an interface to the database.

Supported

Supported

One-to-many

Map Java collections of persistent objects to the database.

Supported

Supported

Many-to-many

Use an association table to map Java collections of persistent objects to the database.

Supported

Supported

Aggregate collection

Map Java collections of persistent objects to the database.

Unsupported

Supported

Direct collection

Map Java collections of objects that do not have descriptors.

Supported

Supported

Direct map

Direct map mappings store instances that implement java.util.Map.

Supported

Supported

Aggregate object

Create strict one-to-one mappings that require both objects to exist in the same database row.

Supported

Unsupported

Transformation

Create custom mappings where one or more fields can be used to create the object to be stored in the attribute.

Supported

Supported


Relational Mapping Concepts

This section introduces direct mapping concepts unique to EclipseLink, including the following:


Directionality

The direction of a relationship may be either unidirectional or bidirectional. In a unidirectional relationship, only one entity bean has a relationship field that refers to the other. All EclipseLink relational mappings are unidirectional, from the class being described (the source class) to the class with which it is associated (the target class). The target class does not have a reference to the source class in a unidirectional relationship.

In a bidirectional relationship, each entity bean has a relationship field that refers to the other bean. Through the relationship field, an entity bean's code can access its related object. To implement a bidirectional relationship (classes that reference each other), use two unidirectional mappings with the sources and targets reversed.


Note: Maintenance of bidirectional relationships presents a number of technical challenges.

For more information, see the following:


Converters and Transformers

You can store object attributes directly in a database table as follows:


Using a Direct Mapping

If the attribute type is comparable to a database type, the information can be stored directly simply by using a Direct-to-Field Mapping.


Using a Converter Mapping

If the attribute type is comparable to a database type but requires conversion, the information can be stored directly by using a Direct-to-Field Mapping and an appropriate Converter instance.

If the application's objects contain attributes that cannot be represented as direct-to-field with an existing converter, use a direct-to-field mapping with a custom converter.


Using a Transformation Mapping

If there is no database primitive type that is logically comparable to the attribute's type, or, if an attribute requires data from multiple fields, it must be transformed on its way to and from the database.

In this case, use a transformation mapping.


Direct-to-Field Mapping

Use direct-to-field mappings to map primitive object attributes, or non persistent regular objects, such as the JDK classes. For example, use a direct-to-field mapping to store a String attribute in a VARCHAR field.


Direct-to-Field Mapping Example

The Direct-to-Field Mapping figure illustrates a direct-to-field mapping between the Java attribute city and the relational database column CITY. Similarly, direct-to-field mappings could be defined from country to COUNTRY, id to ADDRESS_ID, established to EST_DATE, and province to PROVINCE.


Direct-to-Field Mapping

Direct-to-Field Mapping

You can use a direct-to-field mapping with any of the following Converter instances:

You can use a direct-to-field mapping with a change policy.

See Configuring a Relational Direct-to-Field Mapping for more information.


Direct-to-XMLType Mapping

Using a direct-to-XMLType mapping, you can map XML data in the form of a String or an org.w3c.dom.Document object to an XMLType column in an Oracle Database (introduced in version 9.2.0.1).

If you plan to use direct-to-XMLType mappings in Workbench and the EclipseLink runtime, you must include the Oracle Database xdb.jar file in the Workbench classpath (see Configuring the Workbench Environment).

The EclipseLink query framework provides a number of expression operators you can use to create queries based on the content of that XML data (see XMLType Functions).

See Configuring a Relational Direct-to-XMLType Mapping for more information.


One-to-One Mapping

One-to-one mappings represent simple pointer references between two Java objects. In Java, a single pointer stored in an attribute represents the mapping between the source and target objects. Relational database tables implement these mappings using foreign keys.

The One-to-One Mappings figure illustrates a one-to-one relationship from the address attribute of an Employee object to an Address object. To store this relationship in the database, create a one-to-one mapping between the address attribute and the Address class. This mapping stores the id of the Address instance in the EMPLOYEE table when the Employee instance is written. It also links the Employee instance to the Address instance when the Employee is read from the database. Because an Address does not have any references to the Employee, it does not have to provide a mapping to Employee.

For one-to-one mappings, the source table normally contains a foreign key reference to a record in the target table. In the One-to-One Mappings figure, the ADDR_ID field of the EMPLOYEE table is a foreign key.


One-to-One Mappings

One-to-One Mappings

You can also implement a one-to-one mapping where the target table contains a foreign key reference to the source table. In the One-to-One Mappings figure, the database design would change such that the ADDRESS row would contain the EMP_ID to identify the Employee to which it belonged. In this case, the target must also have a relationship mapping to the source.

The update, insert and delete operations, which are normally done for the target before the source for privately owned one-to-one relationships, are performed in the opposite order when the target owns the foreign key. Target foreign keys normally occur in bidirectional one-to-one mappings (see Directionality), because one side has a foreign key and the other shares the same foreign key in the other's table.

Target foreign keys can also occur when large cascaded composite primary keys exist (that is, one object's primary key is composed of the primary key of many other objects). In this case it is possible to have a one-to-one mapping that contains both foreign keys and target foreign keys.

In a foreign key, EclipseLink automatically updates the foreign key value in the object's row. In a target foreign key, it does not. In EclipseLink, use the Target Foreign Key option when a target foreign key relationship is defined.

When mapping a relationship, you must understand these differences between a foreign key and a target foreign key, to ensure that the relationship is defined correctly.

In a bidirectional relationship where the two classes in the relationship reference each other, only one of the mappings should have a foreign key. The other mapping should have a target foreign key. If one of the mappings in a bidirectional relationship is a one-to-many mapping, see Configuring a Relational Variable One-to-One Mapping for details.

You can use a one-to-one mapping with a change policy.

See Configuring a Relational One-to-One Mapping for more information.


Variable One-to-One Mapping

Variable class relationships are similar to polymorphic relationships, except that in this case the target classes are not related through inheritance (and thus not good candidates for an abstract table), but through an interface.

To define variable class relationships in Workbench, use the variable one-to-one mapping selection, but choose the interface as the reference class. This makes the mapping a variable one-to-one. When defining mappings in Java code, use the VariableOneToOneMapping class.

EclipseLink supports variable relationships only in one-to-one mappings. It handles this relationship in two ways:


Variable One-to-One Mappings with Class Indicator

Variable One-to-One Mappings with Class Indicator

See Configuring a Relational Variable One-to-One Mapping for more information.


One-to-Many Mapping

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

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

The purpose of creating this one-to-one mapping in the target is so that the foreign key information can be written when the target object is saved. Alternatives to the one-to-one mapping back reference include the following:

  • Use a direct-to-field mapping to map the foreign key and maintain its value in the application. Here the object model does not require a back reference, but the data model still requires a foreign key in the target table.
  • Use a many-to-many mapping to implement a logical one-to-many. This has the advantage of not requiring a back reference in the object model and not requiring a foreign key in the data model. In this model the many-to-many relation table stores the collection. It is possible to put a constraint on the join table to enforce that the relation is a logical one-to-many relationship.


One-to-Many Relationships

One-to-Many Relationships


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


You can use a many-to-many mapping with a change policy.

See Configuring a Relational One-to-Many Mapping for more information.


Many-to-Many Mapping

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

This figure illustrates a many-to-many mapping in Java and in relational database tables.


Many-to-many Relationships

Many-to-many Relationships


Note: The projects attribute shown in the Many-to-many Relationships figure is of type Vector. You can use a Collection interface (or any class that implements the Collection interface) for declaring the collection attribute. See Configuring Container Policy for details.


Many-to-many mappings are implemented using a relation table. This table contains columns for the primary keys of the source and target tables. Composite primary keys require a column for each field of the composite key. The intermediate table must be created in the database before using the many-to-many mapping.

The target class does not have to implement any behavior for the many-to-many mappings. If the target class also creates a many-to-many mapping back to its source, then it can use the same relation table, but one of the mappings must be set to read-only. If both mappings write to the table, they can cause collisions.

Indirection (lazy loading) is enabled by default in a many-to-many mapping, which requires that the attribute have the ValueHolderInterface type or transparent collections. For more information on indirection, see Indirection (Lazy Loading).

You can use a many-to-many mapping with a change policy).

See Configuring a Relational Many-to-Many Mapping for more information.


Aggregate Collection Mapping

Aggregate collection mappings are used to represent the aggregate relationship between a single-source object and a collection of target objects. Unlike the EclipseLink one-to-many mappings, in which there should be a one-to-one back reference mapping from the target objects to the source object, there is no back reference required for the aggregate collection mappings, because the foreign key relationship is resolved by the aggregation.


Note: To use aggregate collections with Workbench, you must use an amendment method (see Configuring Amendment Methods), or manually edit the project source to add the mapping.


Although aggregate collection mappings are similar to one-to-many mappings, they are not replacements for one-to-many mappings. Use aggregate collections only in situations where the target collections are of a reasonable size and if having a many-to-one back mapping is difficult.

Because one-to-many relationships offer better performance and are more robust and scalable, consider using a one-to-many relationship rather than an aggregate collection. In addition, aggregate collections are privately owned by the source of the relationship and must not be shared or referenced by other objects.

This section describes the following:

See Configuring a Relational Aggregate Collection Mapping for more information.


Aggregate Collection Mappings and Inheritance

Aggregate collection descriptors can use inheritance. You must also declare subclasses as aggregate collection. The subclasses can have their own mapped tables, or share the table with their parent class. See Descriptors and Inheritance for more information on inheritance.

Aggregate Collection Mappings and EJB

You can use aggregate collection mappings with entity beans if the source of the relationship is an entity bean or Java object, and the mapping targets are regular Java objects. Entity beans cannot be the target of an aggregate object mapping.


How to Implement Aggregate Collection Mappings

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

Aggregate collection mappings require a target table for the target objects.

To implement an aggregate collection mapping, the following must take place:

  • The descriptor of the target class must declare itself to be an aggregate collection object. Unlike the aggregate object mapping, in which the target descriptor does not have a specific table to associate with, there must be a target table for the target object.
  • The descriptor of the source class must add an aggregate collection mapping that specifies the target class.

Direct Collection Mapping

Direct collection mappings store collections of Java objects that are not EclipseLink-enabled. The object type stored in the direct collection is typically a Java type, such as String.

It is also possible to use direct collection mappings to map a collection of non-String objects. For example, it is possible to have an attribute that contains a collection of Integer or Date instances. The instances stored in the collection can be any type supported by the database and has a corresponding wrapper class in Java.

Support for primitive data types such as int is not provided, because Java Collection holds only objects.

The Direct Collection Mappings figure illustrates how a direct collection is stored in a separate table with two fields. The first field is the reference key field, which contains a reference to the primary key of the instance owning the collection. The second field contains an object in the collection and is called the direct field. There is one record in the table for each object in the collection.


Direct Collection Mappings

Direct Collection Mappings


Note: The responsibilities attribute shown in the Direct Collection Mappings figure is of type Vector. You can use a Collection interface (or any class that implements the Collection interface) for declaring the collection attribute. See Configuring Container Policy for details.


Maps are not supported for direct collection because there is no key value.

You can use a direct collection mapping with any of the following Converter instances:

You can use a direct collection mapping with a change policy).

See Configuring a Relational Direct Collection Mapping for more information.


Direct Map Mapping

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 are Java primitive wrapper types such as String objects.

The Direct Map Mappings figure illustrates how a direct map is stored in a separate table with three fields. The first field (EMPID) is the reference key field, which contains a reference to the primary key of the instance owning the collection. The second field (ADDRESS) contains an object in the collection and is called the direct value field. The third field (TYPE) contains the direct key field. In this example, the direct map uses a object type converter for the direct key field, converting the single character W in the database to the full string Work in the object (and H to Home).


Direct Map Mappings

Direct Map Mappings

You can use a direct collection mapping with any of the following Converter instances:

You can use a direct map mapping with a change policy).

See Configuring a Relational Direct Map Mapping for more information.


Aggregate Object Mapping

Two objects–a source (parent or owning) object and a target (child or owned) object–are related by aggregation if there is a strict one-to-one relationship between them and all the attributes of the target object can be retrieved from the same table(s) as the source object. This means that if the source object exists, then the target object must also exist and if the source object is destroyed, then the target object is also destroyed.

An aggregate mapping allows you to associate data members in the target object with fields in the source object's underlying database tables.

You configure the aggregate mapping in the source object's descriptor. However, before doing so, you must designate the target object's descriptor as an aggregate (see Configuring a Relational Descriptor as a Class or Aggregate Type).

Aggregate objects are privately owned and should not be shared or referenced by other objects.

You cannot configure one-to-one, one-to-many, or many-to-many mappings from a nonaggregate object to an aggregate target object.

You can configure such mappings from an aggregate target object to another nonaggregate object. If you configure a one-to-many mapping from an aggregate target object to another nonaggregate object, you must configure a one-to-one mapping from the other object back to the source object that owns the aggregate (instead of to the aggregate target object itself). This is because the source object contains the table and primary key information of the aggregate target.

You can configure inheritance for a descriptor designated as an aggregate (see Descriptors and Inheritance), however, in this case, all the descriptors in the inheritance tree must be aggregates. Aggregate and class descriptors cannot exist in the same inheritance tree.

This section describes the following:

You can use an aggregate object mapping with a change policy.

For more information on configuring an aggregate object relationship mapping, see Configuring a Relational Aggregate Object Mapping.


Aggregate Object Mappings with a Single Source Object

The Aggregate Object Mapping with a Single Source Object figure shows an example aggregate object mapping between source object Employee and target object Period. In this example, the target object is not shared by other types of source object.


Aggregate Object Mapping with a Single Source Object

Aggregate Object Mapping with a Single Source Object

Aggregate target classes not shared among multiple source classes can have any type of mapping, including other aggregate object mappings.


Aggregate Object Mappings with Multiple Source Objects

The Aggregate Object Mapping with Multiple Source Objects figure shows an example aggregate object mapping in which different source objects–Employee and Project–map instances of the same type of target object, Period.


Aggregate Object Mapping with Multiple Source Objects

Aggregate Object Mapping with Multiple Source Objects

When you configure the aggregate object mapping in the source object, you choose the source object table for that particular mapping. This allows different source types to store the same target information within their tables. Each source object's table may use different field names. EclipseLink automatically manages the case where multiple source object tables use different field names.

For example, in the Aggregate Object Mapping with Multiple Source Objects figure, The Employee attribute employPeriod is mapped by an aggregate object mapping to target object Period. This mapping associates Period attribute startDate with EMPLOYEE table field START_DATE. The Project attribute projectPeriod is also mapped by an aggregate object mapping to target object Period. This mapping associates Period attribute startDate with PROJECT table field S_DATE.

Aggregate target classes shared with multiple source classes cannot have one-to-many or many-to-many mappings.


How to Implement an Aggregate Object Relationship Mapping

You must ensure that the following takes place:

  • The descriptor of the target class declares itself to be an aggregate object. Because all its information comes from its parent's table(s), the target descriptor does not have a specific table associated with it. You must, however, choose one or more candidate table(s) from which you can use fields in mapping the target.In the example above, you could choose the EMPLOYEE table so that the START_DATE and END_DATE fields are available during mapping.
  • The descriptor of the source class adds an aggregate object mapping that specifies the target class.
    In the example above, the Employee class has an attribute called employPeriod that would be mapped as an aggregate object mapping with Period as the reference class.
    The source class must ensure that its table has fields that correspond to the field names registered with the target class.
  • If a source object has a null target reference, EclipseLink writes null values to the aggregate database fields (see Configuring Allowing Null Values). When the source is read from the database, it can handle this null target in one of two ways:
    • Create an instance of the object with all its attributes equal to null.
    • Put a null reference in the source object without instantiating a target. (This is the default method of handling null targets.)


Transformation Mapping

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

Tip: Use transformation mappings only when mapping multiple fields into a single attribute. Because of the complexity of transformation mappings, it is often easier to perform the transformation with a converter or getter and setter methods of a direct-to-field mapping. See Configuring a Relational Direct-to-Field Mapping for more information.

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

Transformation Mappings

Transformation Mappings

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

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

See Configuring a Relational Transformation Mapping for more information.



Copyright Statement

Back to the top