Skip Headers

Oracle9iAS TopLink Mapping Workbench Reference Guide
Release 2 (9.0.3)

Part Number B10063-01
Go To Documentation Library
Home
Go To Solution Area
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Go to previous page Go to next page

4
Understanding Descriptors

TopLink uses descriptors to store the information that describes how an instance of a particular class can be represented in a relational database. Most descriptor information can be defined by the Mapping Workbench and read from a project file to be registered with a TopLink Mapping Workbench session.

For complete information on the Oracle9iAS TopLink API, refer to the online API guide installed in the default TopLink directory.


Note:

In this document, descriptors refers to TopLink descriptors; deployment descriptors refers to EJB deployment descriptors.


Working with Descriptors

A descriptor stores all of the information describing how an instance of a particular class can be represented in a relational database. The Mapping Workbench reads a project .mwp file to load all of a project's information (including descriptor information).

You may need to amend a descriptor (for example, to specify a property not supported by the Mapping Workbench) after reading a project file (see "Amending Descriptors After Loading"). However, do not modify any descriptors after registering them with the session.

TopLink descriptors contain the following information:

Understanding Persistent Classes

Any class that registers a descriptor with a TopLink Mapping Workbench database session is called a persistent class. TopLink does not require that persistent classes provide public accessor methods for any private or protected attributes stored in the database.

See Appendix A, "Object Model Requirements" for more information on persistent classes object model requirements.

Specifying Descriptor Types

TopLink descriptors can be a class descriptor, an aggregate descriptor, or an EJB descriptor. After creating a descriptor, use this procedure to change the descriptor type.


Note:

An EJB descriptor cannot be an aggregate.


To specify a descriptor's type:
  1. Choose the descriptor in the Project Tree pane.

  2. Click on the appropriate descriptor icon (Class Class Descriptor button. , Aggregate  Aggregate Descriptor button. , or EJB EJB Descriptor button.  ) in the mapping toolbar.

    You can also specify descriptor type by choosing the descriptor and selecting Selected > Descriptor Type > specific descriptor type from the menu or by right-clicking on the descriptor in the Project Tree pane and selecting Descriptor Type > specific descriptor type from the pop-up menu.


    Note:

    EJB 2.0 descriptors are created only by reading the ejb-jar.xml file. See "Mapping EJB 2.0 Entities" for more information.


When changing a descriptor's type, the Mapping Workbench will add or remove property tabs, as needed.

Mapping Descriptors

Descriptors define mappings between classes and tables. To display the attributes in a specific class, expand the descriptor item in the Project Tree pane.

Use the mapping toolbar to choose a mapping type for each attribute.

To map a descriptor:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

  2. On the Descriptor Info tab, associate the descriptor with a database table (see "Setting Descriptor Information").

  3. In the Project Tree pane, expand the descriptor to display its attributes.

  4. Select an attribute and click on the appropriate mapping button in the Mapping toolbar.

Continue with "Working with Mappings" to modify the mapping.

Automapping Descriptors

The Mapping Workbench can automatically map class attributes to a similarly named database field. This Automap function only creates mappings for unmapped attributes - it does not change previously defined mappings.

You can automap classes for an entire project or for specific tables.


Note:

You must associate a descriptor with a database table before using the Automap function. See "Setting Descriptor Information".


To automap attributes:

To automap all descriptors in a project, right-click on the project icon in the Project Tree pane and select Automap from the pop-up menu or select Selected > Automap from the menu.

or

To automap a specific descriptor or attribute select the descriptor/attribute(s). Right-click and select Automap from the pop-up menu or select Selected > Automap from the menu.

Generating Java Code for Descriptors

Use this procedure to generate the Java class code for the selected descriptor or package.

To generate Java code:
  1. Right-click on the descriptor or package and select Generate Code from the pop-up menu. The Choose a Directory dialog box appears.

    You can also generate Java code by selecting Selected > Generate Code from the menu.

  2. Browse to the directory in which to save the Java code and click on Save. TopLink creates the <DescriptorName>.java file in the specified directory.

Working with Descriptor Properties

Each descriptor in the Mapping Workbench contains tabs and specific properties. By default, descriptors contain the following properties:

Use the Set Advanced Properties function (see "Working with Advanced Properties") to specify additional properties for each descriptor.

Setting Descriptor Information

Use the Descriptor Info tab to map a descriptor to a specific table in the database, define primary key(s), specify sequencing information, and set caching options.

To map a descriptor to a table:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

  2. Click on the Descriptor Info tab.

    Figure 4-1 Descriptor Info Tab

    Text description of desinfo.gif follows.

    Text description of the illustration desinfo.gif

  3. Use this table to enter data in each field:

    Field Description

    Associated Table

    Use the drop-down list to select a database table for the descriptor.

    Primary Keys

    Specify the primary key(s) for the table.

    Use Sequencing

    Specify if this descriptor uses sequencing. If selected, specify the Name, Table, and Field for sequencing. See "Working with Sequencing" for more information.

    Read Only

    Specify if this descriptor is read-only.

    Conform Results in Unit of Work

    Specify to use the conformResultsInUnitOfWork() method for any read object or read all query.

    Refer to the Oracle9iAS TopLink: Foundation Library Guide for more information.

    Refreshing Cache

      Default

    Use the project's default caching options.

      Always Refresh

    Refreshes the objects in the cache on all queries.

    Note: Using this property may impact performance.

      Disable Cache Hits

    Disables the cache hits on primary key read object queries.

      Only Refresh if Newer

    Refreshes the cache only if the object in the database is newer than the object in the cache (as determined by the Optimistic Locking field). See "Working with Optimistic Locking" for more information.


    Note:

    Use the caching options to specify how descriptors refresh the objects in the cache during queries. This ensures that queries against the session will refresh the objects from the row data.


Setting Class Information

After generating classes and descriptors, use the Class tab to:

To specify class info:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

  2. Click on the Class info tab in the Properties pane.

  3. Select the appropriate tab:

Class Tab

To add a new interface to implement, click on Add.

To delete an interface, select the interface and click on Remove.

To generate source code for the descriptor, click on Generate Source Code.

Figure 4-2 Class Info Tab

Text description of clinclas.gif follows.

Text description of the illustration clinclas.gif

Use this table to enter data in each field:

Field Description

Name

Name of the class. This field is for display only.

Superclass

Click on the Browse button and select a class and package.

Access Modifiers

Specify if the class is accessible publicly or only within its own package. Non-public classes are not accessible to the Mapping Workbench.

Other Modifiers

Specify if the class is Final and/or Abstract. Final classes are not included in the superclass selection lists for other classes to extend.

Interfaces Implemented

To add an interface, click on Add and select the interface and package.

Attributes Tab

To add a new attribute, click on Add.

To delete an existing attribute, select the attribute and click on Remove.

To generate a get or set method for an attribute, click on Generate Get/Set Methods.

Figure 4-3 Attributes Tab

Text description of clinatt.gif follows.

Text description of the illustration clinatt.gif

Select an attribute then use this table to enter data in each field.

Field Description

Name

Name of the attribute.

Type

Use the browse button to select a class and package for the attribute.

Item Type

Specify the item's type on the collection. This field applies only if Type is an instance of java.util.

Array Dimensionality

Specify the length of an array. This field applies only if Type is an array.

Access Modifiers

Specify how the attribute is accessible:

  • Public

  • Protected - Public only within its own package

  • Private - Public only for subclasses

  • Default - Public only within its own package

Other Modifiers

Specify if the attribute is Final, Static, Transient, or Volatile.

Note: Selecting some modifiers may disable others.

Methods Tab

To add a new method, click on Add.

To delete an existing method, select the method and click on Remove.

Figure 4-4 Methods Tab

Text description of clinmeth.gif follows.

Text description of the illustration clinmeth.gif

User-interface components called out in Figure 4-4:

  1. Available methods

  2. Properties of selected method

Select a method then use this table to enter data in each field:

Field Description

Name

Name of the method.

Return Type

Use the browse button and select a class and package.

Array Dimensionality

Specify the length of the array (Return Type).

Access Modifier

Specify how the attribute is accessible:

  • Public

  • Protected - Public only within its own package

  • Private - Public only for subclasses

  • Default - Public only within its own package

Other Modifier

Specify if the attribute is Abstract, Final, Static, Native, or Synchronized.

Note: Selecting some modifiers may disable others.

Parameters

Click on Add to include parameter(s) for the method.

Note: The parameters are loaded in the order listed.

Query Keys

The Mapping Workbench uses query keys as an alias for a field name. With an alias, TopLink expressions can use the Java names instead of DBMS-specific field names.

Use the Query Keys tab to create user-defined queries or to work with automatically generated query keys.

Specifying Query Keys

Use the Query keys tab to specify a query key for a descriptor.

To specify query keys:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

  2. Click on the Query Keys tab in the Properties pane.

    Figure 4-5 Query Keys Tab

    Text description of querykey.gif follows.

    Text description of the illustration querykey.gif

    User-interface components called out in Figure 4-5:

    1. Defined query keys

    2. New query key information

  3. Click on New Query Key to create a new query.

  4. Use this table to enter data in each field:

    Field Description

    Name

    Name of the query.

    Table

    Database table used by the query.

    Field

    Field in the table used by the query.

Specifying Queries

Use the Queries tab to specify EJBQL and SQL queries and finders to use for database access. The Queries tab contains two additional tabs: Named Queries and Custom SQL.

For 2.0 CMP projects, the ejb-jar.xml files stores query lists. You can define the queries in the file and then read them into the Mapping Workbench, or define them on the Queries tab and write them to the file. See "Writing to the ejb-jar.xml File" for more information.

To create queries:
  1. In the Project Tree pane, select a descriptor.

  2. Click on the Queries tab in the Properties pane.

  3. Select the appropriate tab:

SQL Queries

Use this procedure to create custom SQL queries in the Mapping Workbench. For 2.0 CMP projects, the SQL is not written to the ejb-jar.xml file.

To create custom SQL queries:
  1. In the Project Tree pane, select a descriptor.

  2. Click on the Queries tab in the Properties pane.

  3. Click on the Custom SQL tab.

    Figure 4-6 Queries Custom SQL Tab

    Text description of qrsqltab.gif follows.

    Text description of the illustration qrsqltab.gif

  4. Click on the appropriate SQL function tab (Insert, Update, etc.) and type the SQL code to execute.


    Note:

    The Mapping Workbench does not validate the SQL code that you enter.


Named Queries

Use named queries to specify SQL or EJBQL queries to access the database. EJBQL is a declarative language used to present queries from an object-model perspective. Refer to the EJB specification for detailed information.

To create a named query:
  1. In the Project Tree pane, select a descriptor.

  2. Click on the Queries tab in the Properties pane.

  3. Click on the Named Queries tab in the Queries tab.

    Figure 4-7 Named Queries Tab

    Text description of qrnmdfnd.gif follows.

    Text description of the illustration qrnmdfnd.gif

  4. Click on Add to create a new named query. The Add Queries window appears.

  5. Select the query type, enter the query name, and press Enter. The Mapping Workbench adds the query to the Named Query tab.

  6. Use this table to enter data in each field on the tab.

    Field Description

    Descriptor Alias

    Alias for the descriptor class. This field applies for EJB finders only.

    Name

    Name of the query. The prefix of the query name specifies the query type:

    • find - EJB 2.0

    • ejbSelect - EJB Select

    TopLink Reserved Finder names cannot be changed.

    Type

    Use the drop-down list to specify if this is a ReadObject or ReadAll query.

    Query Format

    Specify if this is an EJB QL or SQL query. For TopLink Reserved Finders, the query will be generated at runtime.

    Query String

    Enter the query string.

    Note: The mapping workbench does not validate the query string.

  7. To add additional parameters to the finder, click on the Parameters tab and click Add.


    Note:

    You can only add parameters for non-EJB descriptors.


    Figure 4-8 Named Queries Parameters Tab

    Text description of qrfndpar.gif follows.

    Text description of the illustration qrfndpar.gif

  8. Select a class and package to add to this finder.

  9. Click on the Options tab to add additional options.

    Figure 4-9 Named Queries Options Tab

    Text description of qrfndopt.gif follows.

    Text description of the illustration qrfndopt.gif


    Note:

    If the options on this panel are disabled, the Mapping Workbench uses the options specified in the parent.


  10. Use this table to enter data in each field:

    Field Description

    Cache Statement

    Specify the cacheStatement() method for the query.

    Bind Parameters

    Specify the bindAllParameters() method for the query.

    Maintain Cache

    Specify maintainCache() for the query.

    Refresh Results

    Specify the refreshIdentityMapResults() method to refresh the attributes of the object resulting from the query.

    Cache Usage

    Select how the query checks the cache before accessing the database.

    Pessimistic Locking

    Select how the pessimistic locking policy acquires locks.


    Note:

    These options are not available for findOneByQuery and findManyByQuery.


Refer to the Oracle9iAS TopLink Foundation Library Guide for additional information.

Displaying EJB descriptor Information

Use the EJB Info tab to display the EJB descriptor's information (from the ejb-jar.xml file). This tab is available only for EJB descriptors.

To display EJB descriptor information:
  1. In the Project Tree pane, select an EJB descriptor.

  2. Click on the EJB Info tab in the Properties pane.

    Figure 4-10 EJB Info Tab

    Text description of ejbinfo.gif follows.

    Text description of the illustration ejbinfo.gif

  3. Use this table to identify each field:

    Field Description

    EJB Name

    Base name. When using EJB 2.0, this is specified in the <ejb-name> element of the ejb-jar.xml file.

    Primary Key Class

    Primary key. When using EJB 2.0, this is specified in the <prim-key-class> element of the ejb-jar.xml file.

    Local Interface

    Local interface. When using EJB 2.0, this is specified in the <local> element of the ejb-jar.xml file.

    Local Home Interface

    Local home interface. When using EJB 2.0, this is specified in the <local-home> element of the ejb-jar.xml file.

    Remote Interface

    Remote interface. When using EJB 2.0, this is specified in the <remote> element of the ejb-jar.xml file.

    Remote Home Interface

    Remote interface. When using EJB 2.0, this is specified in the <home> element of the ejb-jar.xml file.


    Note:

    When using EJB 2.0 persistence, these fields are for display only.


Working with Advanced Properties

You can also specify the following advanced properties for each descriptor:

To display advanced properties:

Right-click on a descriptor in the Project Tree pane and select Set Advanced Properties > specific property from the pop-up menu or select Selected > Set Advanced Properties > specific property from the menu.

Amending Descriptors After Loading

Some TopLink features cannot be configured from the workbench. To use these features, you must write a Java method to amend the descriptor after it is loaded as part of the project. This method takes the descriptor as a single parameter. You can then send messages to the descriptor or any of its specific mappings to configure advanced features.

To a specify a method to execute after loading the descriptor:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

    If the After load advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > After Load from pop-up menu or from the Selected menu.

  2. Click on the After load tab in the Properties pane.

    Figure 4-11 After Load Tab

    Text description of aftrload.gif follows.

    Text description of the illustration aftrload.gif

  3. Use this table to enter data in each field:

    Field Description

    After Loading...

    Specify if the Mapping Workbench should execute a method after loading the descriptor.

    Class

    Click on the browse button and select the class of the method to execute.

    Static Method

    Use the Static Method drop-down list to select the method to execute.

Specifying Events

Use the Events tab to specify a descriptor's method to execute when certain events occur.

To specify an event method:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

    If the Events advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Events from pop-up menu or from the Selected menu.

  2. Click on the Event tab in the Properties pane.

    Figure 4-12 Events Tab

    Text description of events.gif follows.

    Text description of the illustration events.gif

  3. Use this table to enter data in each field:

    Field Description

    Events Choice

    Select an event for this descriptor.

    Methods

    Select a method for each event.

    Note: The methods available will vary, depending on the selected event.

See "Supported Events" for a complete list of events and methods.

Specifying Identity Mapping

TopLink Mapping Workbench specifies the default identity mapping for each descriptor in the project options (see "Working with Default Properties"). Use the Identity tab to specify identity map and existence checking information for a descriptor.


Note:

Changing the project's default identity policy does not affect descriptors that already exist in the project.


To specify an identity map for a descriptor:
  1. In the Project Tree pane, select a descriptor.

    If the Identity advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Identity from the pop-up menu or from the Selected menu.

  2. Click on the Identity tab.

    Figure 4-13 Identity Tab

    Text description of identity.gif follows.

    Text description of the illustration identity.gif

  3. Use this table to enter data in each field:

    Field Description

    Type

    Use the Type drop-down list to select the identity map (see Table 4-2 for details).

    Size

    Size of the identity map.

    Existence Checking

    Specify the method of existence checking.

Specifying Inheritance

Use the Inheritance tab to specify the descriptor's inheritance properties as either a root or subclass (branch class or leaf class).


Note:

When using an aggregate descriptor in an inheritance, all the descriptors in the inheritance tree must be aggregates. Aggregate and Class descriptors cannot exist in the same inheritance tree.


Creating a Root Class

Use this procedure to create a root class.

To specify a root class:
  1. In the Project Tree pane, choose the descriptor you wish to specify as the root.

  2. Select the Inheritance tab in the Property pane.

    If the Inheritance tab is not visible, right-click on the descriptor and choose Set Advanced Properties > Inheritance.

    Figure 4-14 Creating a Root Class

    Text description of inhroot.gif follows.

    Text description of the illustration inhroot.gif

  3. To instantiate the descriptor's subclasses when queried, enable the Read Subclasses on Query checkbox. Select a database view to use for reading subclasses if desired.


    Note:

    The view can be used for root or branch classes that have subclasses spanning multiple tables. The view must outer-join or union all of the subclass tables.


  4. Enable the Is Root Descriptor checkbox.

  5. You may use a class extraction method or a class indicator field to specify which class to instantiate on querying. Choose the option and select the appropriate method or field.

  6. If you use a class indicator field, you may use the class name as the indicator, or you may use a class indicator dictionary. Choose which option you wish to use and specify the necessary information.

  7. If you choose to use an indicator dictionary, choose the indicator type and set the indicator values for each subclass.


    Note:

    A list of subclasses and their indicator values appears when the subclasses have set their parent descriptor. Abstract roots are not in the list.


  8. If you want instances of the subclasses to be instantiated when the root class is queried, enable the Read Subclasses on Query checkbox. Do not enable this checkbox for leaf classes.

Creating Branch and Leaf Classes

After setting up the root class for inheritance, you must also specify properties for branch and leaf classes.

To create branch and leaf classes:
  1. In the Project Tree pane, choose the descriptor for which to specify inheritance information.

  2. If the Inheritance advanced property has not been added to the descriptor, right-click on the descriptor and choose Set Advanced Properties > Inheritance.

  3. Select the Inheritance tab of the properties window.

  4. Ensure that Is Root Descriptor is not selected. The Parent Descriptor drop-down list is now enabled and the class indicator information is disabled.

    Figure 4-15 Creating Branch and Leaf Classes

    Text description of inhbr_lf.gif follows.

    Text description of the illustration inhbr_lf.gif

  5. Select the parent descriptor from the Parent Descriptor drop-down list. This may be the root class or a branch class.

  6. Enable the Read Subclasses on Query option if this is a branch class and you want its subclasses to be instantiated when it is queried. Choose a database view for reading subclasses, if desired. Do not enable this checkbox for leaf classes.

Specifying Optimistic Locking

Use the Locking tab to specify if the descriptor uses optimistic locking.

To specify a descriptor's locking policy:
  1. In the Project Tree pane, select a descriptor.

    If the Locking advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Locking from the pop-up menu or from the Selected menu.

  2. Click on the Locking tab.

    Figure 4-16 Locking Tab

    Text description of locking.gif follows.

    Text description of the illustration locking.gif

  3. Use this table to enter data in each field:

    Field Description

    Optimistic Locking

    Specify if the descriptor uses optimistic locking.

    Field

    Use the Field drop-down list to select the correct field.

    Version Locking

    Specify the descriptor uses version locking.

    Timestamp Locking

    Specify the descriptor uses timestamp locking.

    Store Version in Cache

    Specify if you want to store the version information in the cache.

Specifying an Interface Alias

Use the Interface Alias tab to specify a descriptor's alias. Each descriptor may have one interface alias. Use the interface in queries and relationship mappings.


Note:

If you use an interface alias, do not associate an interface descriptor with the interface.


To specify an interface alias:
  1. In the Project Tree pane, select a descriptor.

    If the Interface Alias advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Interface Alias from pop-up menu or from the Selected menu.

  2. Click on the Interface Alias tab.

    Figure 4-17 Interface Alias Tab

    Text description of intralis.gif follows.

    Text description of the illustration intralis.gif

  3. Click on the browse button and select an interface.

Working with Primary Keys

A primary key is a column (or a combination of columns) that contains a unique identifier for every record in the table. In the Mapping Workbench, every table that stores persistent objects must have a primary key. Tables that require multiple columns to create an identifier use a composite primary key. Setting the primary key for a table also sets the primary key for the descriptor that uses the table.

The Mapping Workbench implements primary keys using sequence numbers (see "Working with Sequencing").

Each descriptor must provide mappings for its primary key. These mappings may be direct, transformation or one-to-one. The Mapping Workbench does not require you to define a primary key constraint in the database - only that the fields specified for the primary key are unique.


Note:

Primary keys for classes in an inheritance hierarchy or for descriptors that map to multiple tables have special requirements. Refer to"Working with Inheritance" and "Working with Multiple Tables" for more information.


Setting a Primary Key for Descriptors

Use this procedure to set a primary key for a descriptor.

To set a primary key:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

  2. Click on the Descriptor Info tab.

    Figure 4-18 Primary Keys

    Text description of despk.gif follows.

    Text description of the illustration despk.gif

  3. Select the field(s) to set as the primary key.

Working with Sequencing

Sequence numbers are artificial keys that uniquely identify the records in a table. When you define a sequence number field for a descriptor, the Mapping Workbench automatically generates a new sequence number every time you insert a new record into the table.

Use the project's Sequencing tab or the Sequencing area of a descriptor's Descriptor Info tab to specify sequencing information

Database tables often use a sequence number as the primary key. The Mapping Workbench can use the database's native support or a sequence table to maintain sequence numbers.


Tip:

Oracle recommends using sequence numbers for primary keys since they are single, guaranteed, unique values.


Other data values may require composite primary keys to make up a unique value, which is less optimal. Additionally, non-artificial values may need to change, and this is not allowed for primary keys.

Using Sequence Numbers with Entity Beans

When implementing sequencing for Entity Beans, you must provide create() methods and the corresponding ejbCreate() and ejbPostCreate() methods for your bean home and bean class.

TopLink creates the primary key value when you first insert the bean in the database. The key value is not passed as a parameter to the create() methods because they do not set the primary key value (the key is generated).


Note:

Be careful when using transactions with these create methods. If you create an Entity Bean within a transaction and you use native sequencing in Sybase, SQL Server or Informix, the bean's key is not initialized until the transaction commits and bean is persisted to the database for the first time.


Using Native Sequencing

Oracle, Sybase, SQL Server and Informix databases support native sequencing in which the DBMS generates the sequence numbers. However, the Mapping Workbench must still tell the DBMS to assign sequence number values.

Using Sequence Tables

If your database does not use native sequencing, you must manually create the sequence table (named SEQUENCE). Use this table to store each table, as illustrated below:

Field name Field format Description

SEQ_NAME

CHAR

Name of the sequence number

SEQ_COUNT

NUMERIC

Current value

After creating the table, you must initialize the table within the application. The value of the SEQ_COUNT field for each sequence should be zero (0) as in the following table.

SEQ_NAME SEQ_COUNT

EMP_SEQ

0

PROJ_SEQ

0

Pre-allocating Sequence Numbers

To increase the speed of database inserts, obtain a block of sequence numbers (by setting an allocation size) instead of executing a corresponding SELECT statement to obtain the newly assigned sequence number each time you create an object.

TopLink uses a default pre-allocation size of 50 when using a sequence table and 1 when using native sequencing.

Creating the Sequence Table on the Database

Normally, the database administrator defines the sequence table or sequencing object. However, you can use TopLink's schema manager to define the sequence numbers using:

You should only execute this command once. The SchemaManager creates a sequence entry for each registered descriptor.

Refer to the TopLink: Foundation Library Guide for more information on using the schema manager to create number information in the database.

Working with Inheritance

Inheritance describes how a child class inherits the characteristics of its parent class. TopLink provides multiple methods to preserve the inheritance relationships. You can override mappings that have been specified in a superclass or map attributes that have not been mapped at all in the superclass.


Note:

When using an aggregate descriptor in an inheritance, all the descriptors in the inheritance tree must be aggregates. Aggregate and Class descriptors cannot exist in the same inheritance tree.


Using Inheritance with EJBs

Although inheritance is a standard tool in object-oriented modeling, the current EJB specification contains only general information regarding inheritance. You should fully understand the current EJB specification before implementing inheritance.


Caution:

Use caution when using inheritance. The next EJB specification may dictate inheritance guidelines that are not supported by the various servers.


Mapping Inherited Attributes in One Descriptor

If you are mapping only one class in an inheritance hierarchy, you may map attributes that it inherits from any of its superclasses.

To map attributes in one descriptor:
  1. In the Project Tree pane, choose a descriptor.

  2. Right-click on the descriptor and select Map Inherited Attributes > specific location from the pop-up menu. You can also map the attributes by choosing Selected > Map Inherited Attributes from the menu.

    You can map inherited attributes to:

    • Superclass

    • Root minus one

    • Selected class

  3. Map the now visible attributes as though they belonged to this descriptor.

You may also do this if you have a common superclass that stores little or no persistent data. For example, if you were mapping subclasses of java.rmi.RemoteObject, each subclass could be mapped independently.

Supporting Inheritance Using One Table

You can store classes with multiple levels of inheritance in a single table to optimize database access speeds.

Example 4-1 Vehicle Object Model

The following diagram illustrates the Vehicle object model.

Figure 4-19 Supporting Inheritance Using One Table

Text description of javainhr.gif follows.

Text description of the illustration javainhr.gif

The entire inheritance hierarchy can share the same table, as in Figure 4-20. The FueledVehicle and NonFueledVehicle subclasses can share the same table even though FueledVehicle has some attributes that NonFueledVehicle does not. The NonFueledVehicle instances waste database resources because the database must still allocate space for the unused portion of its row. However, this approach saves on accessing time because there is no need to join to another table to get the additional FueledVehicle information.

Figure 4-20 Inheritance Using a Superclass Table with Optional Fields

Text description of inhtable.gif follows.

Text description of the illustration inhtable.gif

Supporting Inheritance Using Multiple Tables

For subclasses that require additional attributes, you can use multiple tables instead of a single superclass table. This optimizes storage space because there are no unused fields in the database. However, this may affect performance because TopLink must read from more than one table before it can instantiate the object. TopLink first looks at the class indicator field to determine the class of object to create, then uses the descriptor for that class to read from the subclass tables.

Example 4-2 Inheritance Example

Figure 4-21 illustrates the TopLink implementation of the FUELEDVHCL, CAR, and BICYCLE tables. All objects are stored in the VEHICLE table. FueledVehicle, Car, and Bicycle information is also stored in the secondary table.

Figure 4-21 Inheritance Using Separate Tables for Each Subclass

Text description of inhsepar.gif follows.

Text description of the illustration inhsepar.gif


Note:

Because NonFueledVehicle does not hold any attributes or relationships, it does not need a secondary table. For performance considerations, this design is inefficient because it requires multiple table fetching.


Finding Subclasses

An inheritance mapping for a root class must be able to locate its subclasses by using one of the following methods:

Providing a Class Indicator Field

Use a class indicator field in the table of the root class table to indicate which subclass should be instantiated. The indicator field should not have an associated direct mapping unless it is set to read-only.


Note:

If the indicator field is part of the primary key, define a write-only transformation mapping for the indicator field. Refer to "Working with Transformation Mappings" for more information.


You can use strings or numbers as values in the class indicator field. The root class descriptor must specify how the value in the class indicator field translates into the class to be instantiated. The following table illustrates the class indicator mapping from the Vehicle class containing four entries.

Table 4-1 Class Indicator Mapping from the Vehicle Class
Key Value

F

FueledVehicle

N

NonFueledVehicle

C

Car

B

Bicycle

When working with hierarchies more than two levels deep, the class indicator field and the class indicator mapping can only be in the root class.


Note:

All concrete classes in the hierarchy must have a defined indicator value.


Understanding Root, Branch, and Leaf Classes in an Inheritance Hierarchy

TopLink allows three types of classes in an inheritance hierarchy:

Specifying Primary Keys in an Inheritance Hierarchy

TopLink assumes that all of the classes in an inheritance hierarchy have the same primary key, as set in the root descriptor. Child descriptors associated with tables that have different primary keys must define the mapping between the root primary key and the local one.

For more information on primary keys in an inheritance hierarchy, see "Specifying Multi-table Info".

Mapping Inherited Attributes in a Subclass

If you are defining the descriptor for a class that inherits attributes from another class, you can create mappings for those attributes. If you re-map an attribute that was already mapped in the superclass, the new mapping applies to the subclass only. Any other subclasses that inherit the attribute are unaffected.

To view and map attributes inherited from a superclass:
  1. In the Project Tree pane, right-click a descriptor and choose Map Inherited Attributes > selected class from the pop-up menu or choose Selected > Map Inherited Attributes from the menu.

    The mappings list now includes all the attributes from the superclass of this class.

  2. Map any desired attributes. See "Working with Mappings".

    If you leave inherited attributes unmapped, TopLink will use the mapping (if any) from the superclass, if the superclass's descriptor has been designated as the parent descriptor.

Working with Interfaces

An interface is a collection of method declarations and constants used by one or more classes of objects. Domain classes can implement interfaces or can reference existing interfaces. TopLink supports interfaces in the following methods:

Understanding Interface Descriptors

An interface descriptor is a descriptor whose reference class is an interface. Each domain class specified in TopLink has a related descriptor. A descriptor is a set of mappings that describe how an object's data is represented in a relational database. It contains mappings from the class instance variable to the table's fields, as well as the transformation routines necessary for storing and retrieving attributes. The descriptor acts as the link between the Java object and its database representation.

An interface is simply a collection of abstract behavior that other classes can use. There is no representation of interfaces on the relational database; an interface is purely a Java object concept. Therefore, a descriptor defined for the interfaces does not map any relational entities on the database.


Note:

You cannot create or edit interface descriptors in the Mapping Workbench.


The components defined in the interface descriptor are:

An interface descriptor does not define any mappings, because there is no concrete data or table associated with it. A list of abstract query keys is defined so that one can issue queries on the interfaces. A read query on the interface results in reading one or more of its implementors.

Example 4-3 Interface Examples

The following illustration shows an interface implemented by two descriptors.

Figure 4-22 Classes Implement an Interface

Text description of impintr.gif follows.

Text description of the illustration impintr.gif

Following is the sample code implementation for the descriptors for Email and Phone:

Descriptor descriptor = new Descriptor();
   descriptor.setJavaInterface(Contact.class);
   descriptor.addAbstractQueryKey("id");
   return descriptor;

Descriptor descriptor = new Descriptor();
   descriptor.setJavaClass(Email.class);
   descriptor.addDirectQueryKey("id", "E_ID");
   descriptor.getInterfacePolicy().addParentInterface(Contact.class);
   descriptor.setTableName("INT_EML");
   descriptor.setPrimaryKeyFieldName("E_ID");
   descriptor.setSequenceNumberName("SEQ");
   descriptor.setSequenceNumberFieldName("E_ID");
   descriptor.addDirectMapping("emailID", "E_ID");
   descriptor.addDirectMapping("address", "ADDR");
   return descriptor;

Descriptor descriptor = new Descriptor();
   descriptor.setJavaClass(Phone.class);
   descriptor.getInterfacePolicy().addParentInterface(Contact.class);
   descriptor.addDirectQueryKey("id", "P_ID");
   descriptor.setTableName("INT_PHN");
   descriptor.setPrimaryKeyFieldName("P_ID");
   descriptor.setSequenceNumberName("SEQ");
   descriptor.setSequenceNumberFieldName("P_ID");
   descriptor.addDirectMapping("phoneID", "P_ID");
   descriptor.addDirectMapping("number", "P_NUM");
   return descriptor;

If the Contact interface extended another interface, you would call the following method to set its parent:

descriptor.getInterfacePolicy().addParentInterface(Interface.class);

Single Implementor Interfaces

Use single implementor interfaces for applications where only the domain objects' interface is visible. Each domain class has its own unique interface and no other domain class implements it. The references to other domain objects are also through interfaces.

In such applications, defining a descriptor for each interface would be expensive and may be unnecessary. TopLink does not force you to define descriptors for such interfaces. The descriptors are defined for the domain classes and the parent interface is set as usual.

During the initializing of a descriptor, the interface is given the descriptor of its implementor. This process allows queries on both the domain class and its interface. The only restriction is that each interface should have a unique implementor. In other words, a descriptor is not needed for an interface unless it has multiple implementors.

Implementing an Interface

One-to-one mappings that reference interfaces that have multiple implementors are known as variable one-to-one mappings. For more information, see Chapter 6, "Understanding Relationship Mappings", and Chapter 4, "Understanding Descriptors".

Use this procedure to implement an interface.

To configure an interface descriptor
  1. In the Project Tree pane, choose an interface.

  2. On the Implementors tab in the Properties pane, choose the descriptors that implement this interface and share at least one common query key.

    Figure 4-23 Implementors Tab

    Text description of intrprop.gif follows.

    Text description of the illustration intrprop.gif

The Common Query Keys area displays all of the query keys for the interface's implementors.

To specify a class descriptor as a single implementor of an interface:
  1. In the Project Tree pane, select the descriptor that will be the sole implementor of an interface.

  2. If the Interface Alias advanced descriptor property is not visible for this descriptor, select Set Advanced Properties > Interface Alias from the Selected menu or the pop-up menu to create the Interface Alias page.

  3. Select the interface that will serve as an alias for this descriptor on the Interface Alias page. This interface does not have to have a descriptor in the project, and in fact, if an associated descriptor exists, it will be removed. Every instance of the interface will now be treated as an instance of this class as well.

Working with Multiple Tables

Descriptors can use multiple tables in mappings. Use multiple tables when:

When a descriptor has multiple tables, you must be able to join a row from the primary table to all of the additional tables. By default, TopLink assumes that the primary key of the first, or primary, table is included in the additional tables, thereby joining the tables.

TopLink also supports custom methods for joining tables.

Specifying Multi-table Info

Use the Multi-table Info tab to define multiple tables for a descriptor in the Mapping Workbench.

To associate multiple tables with a descriptor:
  1. In the Project Tree pane, select a descriptor.

    If the Multi-table Info advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Multi-table Info from pop-up menu or from the Selected menu.

  2. Click on the Multi-table info tab.

    Figure 4-24 Multi-table Info Tab

    Text description of multiinf.gif follows.

    Text description of the illustration multiinf.gif

  3. Use this table to enter data in each field:

    Field Description

    Primary Table

    The primary table for this descriptor. This field is for display only.

    Additional Tables

    Use the Add and Remove buttons to add or remove additional tables.

    Associated Via

    Specify if each Additional Table is associated by its Primary or Foreign key.

When associating a table via Primary Key, additional options appear on the Multi-table Info tab. Continue with "Primary Keys Match" or "Primary Keys are Named Differently" to assign the primary key.

Figure 4-25 Associating Multiple Tables via Primary Key

Text description of multipk.gif follows.

Text description of the illustration multipk.gif

When associating a table via Foreign Key, additional options (shown in Figure 4-25) appear. You must choose a reference that relates the relates the correct fields in the primary table to the primary keys in the selected table. Continue with "Tables are Related by Foreign Key in Primary Table" to assign the foreign key.

Figure 4-26 Associating Multiple Tables via Foreign Key

Text description of multifk.gif follows.

Text description of the illustration multifk.gif

Primary Keys Match

When associating a descriptor with multiple tables in which the primary key field names are identically, you do not have to specify any additional information. Simply select the tables from the list of available tables on the Multi-table Info tab. The Mapping Workbench automatically selects the Primary Keys Have the Same Names option.

Primary Keys are Named Differently

If the primary keys of the additional table(s) are the same but named differently, you must specify how they relate to the primary key(s) of the default/primary table.

  1. Select the associated table, and select Associated Via Primary Key.

  2. Select Primary Keys Have Different Names.

  3. In the Primary Key Reference area (Figure 4-25) Choose a table reference that relates how the primary keys of the primary table relate to the primary keys of the selected table. Use the drop-down list to select a primary key association.

Tables are Related by Foreign Key in Primary Table

If the primary keys of the additional table are not the same as the primary keys of the primary table, but are instead related to a different set of fields, you must set up a foreign key relation between the tables.

  1. Select the associated table, and select Associated Via Foreign Key.

  2. Use the drop-down list to select a foreign key reference that relates the correct fields in the primary table to the primary keys in the selected table. Click on the browse button to create a reference.

Working with a Copy Policy

The TopLink unit of work feature must be able to clone persistent objects. TopLink supports two ways of copying objects:

Setting the Copy Policy

Use the Copying tab to specify how TopLink copies objects. TopLink supports the following methods:

To specify a copy method:
  1. Choose a descriptor in the Project Tree pane. Its properties appear in the Properties pane.

    If the Copying advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Copying from pop-up menu or from the Selected menu.

  2. Click on the Copying tab in the Properties pane.

    Figure 4-27 Copying Tab

    Text description of copying.gif follows.

    Text description of the illustration copying.gif

  3. Use this table to enter data in each field:

    Field Description

    Use instantiation policy

    Specifies to create a new instance of the object using the descriptor's instantiation policy.

    Use clone method

    Specifies to calls the clone() method of the object.

    Method

    Select the clone method from the drop-list. Click on Create New Method to create a new method.

Working with Instantiation Policy

TopLink supports several ways to instantiate objects:

You can use custom Java code to override the instantiation policy. Refer to Oracle9iAS TopLink Foundation Library Guide for details.

Setting Instantiation Policy

Use the Instantiation tab to specify if objects are instantiated by the default constructor, a specific method, or a factory.

To set the instantiation policy:
  1. In the Project Tree pane, select a descriptor.

    If the Instantiation advanced property is not visible for the descriptor, right-click on the descriptor and choose Set Advanced Properties > Instantiation from pop-up menu or from the Selected menu.

  2. Click on the Instantiation tab.

    Figure 4-28 Instantiation Tab

    Text description of instant.gif follows.

    Text description of the illustration instant.gif

  3. Use this table to enter data in each field:

    Field Description

    Use Default Constructor

    The default constructor of the class instantiates a new instance.

    Use Method

    Specify a Method to execute to create objects from the database.

      Method

    Name of a method to be executed to create objects from the database. The method must be a public, static method on the descriptor's class and must return a new instance of the object.

    Use Factory

    Refer to Oracle9iAS TopLink Foundation Library Guide for more information.

      Factory Class

    The class of the factory object that creates the new instances

      Factory Method

    The message to be sent to obtain a factory object

      Instantiation Method

    The method to be sent to the factory object to obtain a new instance that will be populated with data from the database

Working with a Wrapper Policy

TopLink allows you to use "wrappers" (or proxies) in cases where the persistent class is not the same class that is to be presented to users.

For example, in the Enterprise JavaBeans specification, the Entity bean class (the class that implements javax.ejb.EntityBean) is persistent but is hidden from users who interact with a class that implements javax.ejb.EJBObject (the "remote interface" class). In this example, the EJBObject acts as a proxy or wrapper for the EntityBean.

In cases where such a wrapper is used, TopLink continues to make the class specified in the descriptor persistent, but returns the appropriate instance of the wrapper whenever a persistent object is requested.

Use a "wrapper policy" to tell TopLink how to create wrappers for a particular persistent class, and how to obtain the underlying persistent object from a given wrapper instance.

If you specify a wrapper policy, TopLink uses the policy to "wrap" and "unwrap" persistent objects as required:

Setting the Wrapper Policy Using Java Code

The Descriptor class provides methods that are used in conjunction with the wrapper policy:

Refer to the Oracle9iAS TopLink Foundation Library Guide for detailed information.

Working with Optimistic Locking

When using caching to provide performance benefits, you should also use a locking policy to manage database record modification in multi-user environments. Without a locking policy, it may be possible for users to see data stored in the cache that is no longer valid (sometimes called stale data).

Databases typically support the following locking policies:

Oracle recommends using optimistic locking to ensure that all users are working with valid data before committing changes. TopLink supports multiple locking policies for optimistic locking:

Using Version Locking Policies

For each of the following version locking policies, you must add a specific database field.

TopLink records the version as it reads an object from a table. When the client attempts to write the object, TopLink compares the version of the object with the version in the table record.

The two version locking policies have different ways of writing to database:

For both policies, the values of the write lock field can be the writable mapping within the object.

If the value is stored in the identity map, then by default an the version field. If the application does map the field, it must make mappings read-only to allow TopLink to control writing the fields.

Using Field Locking Policies

The following locking policies, included in TopLink, do not require any additional fields:

All of these policies compare the current values of certain mapped previous values. When using these policies, a UnitOfWork must be used for updating the database. Each policy handles its specific way the policy.

Whenever any update fails because optimistic locking has been an OptimisticLockException is thrown. This should be handled by the application when performing any database modification The must refresh the object and reapply its changes.

Specifying Advanced Optimistic Locking Policies

The TopLink optimistic locking policies (described in "Working with Optimistic Locking") implement the OptimisticLockingPolicy interface, referenced throughout the TopLink code. You can create more policies by implementing this interface and implementing the methods defined.

Use the Locking tab (see Figure 4-16) to specify locking policies for the Mapping Workbench, or refer to the Oracle9iAS TopLink Foundation Library Guide for more information.

Working with Identity Maps

TopLink uses identity maps to cache objects for performance and maintain object identity. The Mapping Workbench provides the following identity map types on the Identity tab (see Figure 4-13):

Table 4-2 Identity Maps
Identity Map Description

Full identity map

Provides full caching and guaranteed identity. Caches all objects and does not remove them. This may be memory intensive when many objects are read.

Do not use on batch type operations.

Soft cache weak identity map

(default with JDK 1.2, available since JDK 1.2)

Similar to the weak identity map except that it maintains a most-frequently-used sub-cache. The size of the sub-cache is proportional to the size of the identity map as specified by descriptor's setIdentityMapSize() method. The sub-cache uses soft references to ensure that these objects are garbage-collected only if the system is low on memory.

Hard cache weak identity map
(available since JDK 1.2)

Identical to the soft cache weak identity map except that it uses hard references in the sub-cache. This should be used if soft references do not behave properly on your platform.

Weak identity map (available since JDK 1.2) 

Similar to the full identity map except that the map holds the objects using weak references. This allows for full garbage collection. It also provides full caching and guaranteed identity.

Cache identity map

Provides caching and identity, but does not guarantee identity. A cache identity map maintains a fixed number of objects specified by the application. Objects are removed from the cache on a least-recently-used basis. This method allows object identity for the most commonly used objects.

No identity map

Does not preserve object identity and does not cache objects.

Identity Map Size

The default identity map size is 100.

Design Guidelines

Use the following guidelines when using an identity map:

Using Object Identity

In a Java application, object identity is preserved if each object in memory is represented by one and only one object instance. Multiple retrievals of the same object return references to the same object instance - not multiple copies of the same object.

Maintaining object identity is extremely important when the application's object model contains circular references between objects. You must ensure that two are referencing each other directly, rather copies of each other. Object identity is important when multiple parts of the application may be modifying the same object simultaneously.

Identity can be turned off when object identity is not important (for example, for read-only objects).

Caching Objects

Identity maps maintain client-side object caches which boost by minimizing the number of database reads.

When the cache fills up, TopLink cleans up the cache based on the identity map policy.

Working with Query Keys

Use a direct query key as an alias for a field name. Query keys allow TopLink expressions to refer to a field using Java attribute names (such as firstName) rather than DBMS-specific names (such as F_NAME).

Use query keys to:

Automatically-generating Query Keys

TopLink automatically defines direct query keys for all direct mappings a special query key type for each mapping. Typically, use query keys to access fields that do not have direct mappings, such as the version field used for optimistic locking or the type field used for inheritance.

TopLink displays automatically generated query Query Keys tab of the Properties pane (see Figure 4-5). You cannot change these keys.

Example 4-4 Automatically Generated Query Key

For example, consider the Employee class in the TopLink tutorial: When you define a direct-to-field mapping from the Employee class, attribute firstName to the EMPLOYEE table, field F_NAME, you get a query key for free - it is automatically generated.

The following code example illustrates using an automatically-generated query key within the TopLink expression framework.

Vector employees = session.readAllObjects(Employee.class, new 
ExpressionBuilder().get("firstName").equal("Bob"));

Creating a User-defined Query Key

In addition to the automatically generated query keys, you can define query keys for descriptors.

To use define a query key:
  1. In the Project Tree pane, choose a descriptor.

  2. In the Properties pane, click on the Query Keys tab.

  3. Click on the New Query Key button.

    Figure 4-29 The Add Query Key Window

    Text description of querykey.gif follows.

    Text description of the illustration querykey.gif

    User-interface items called out in Figure 4-29:

    1. Existing query keys

    2. New query key fields

  4. Use this table to enter data in each field:

    Field Description

    Name

    Unique name of the query key. The Name must be different from any previously defined or automatically generated key.

    Table

    Table referenced by this query key.

    Field

    Field referenced by this query key.

  5. Click the Add to List button. The new query key appears in the list in the Query Keys area of the tab.

Using Query Keys in Interface Descriptors

Interface descriptors are defined only with query keys that are shared among their implementors. In the descriptor for the interface, only the name of the query key is specified.

In each implementor descriptor, the key must be defined and with appropriate field from one of the implementor descriptor's tables.

This ensures that a single query key can be used to specify foreign key information from a descriptor that contains a mapping to the interface, even if the field names differ.

Consider an Employee that contains a contact, of type Contact. Contact is an interface with two implementors: Phone and EmailAddress. Each class has two attributes. The following figure illustrates the generated keys:

Figure 4-30 Auto-generated Query Keys for Phone and Email

Text description of atgenkey.gif follows.

Text description of the illustration atgenkey.gif


Note:

Both classes have an attribute, id, that is directly mapped to fields that have different names. However, a query key is generated for this attribute. For the Contact interface descriptor simply indicate that the id query key must be defined for each of the implementors, as shown in Figure 4-31.


Figure 4-31 Contact interface Descriptor with Common Query Key id

Text description of conintds.gif follows.

Text description of the illustration conintds.gif


Note:

If either of the implementor classes did not have the id query key defined, that descriptor would be flagged as deficient.


Now that a descriptor with a commonly-shared query key has been defined for Contact, you can use it as the reference class for a variable one-to-one mapping. For example, you can now create a one-to-one mapping for the contact attribute of Employee. When you edit the foreign key field information for the mapping, you must match the Employee descriptor's tables to query keys from the Contact interface descriptor.

For more information see "Working with Interfaces" and "Working with Relationship Mappings".

Relationship Query Keys

TopLink supports query keys for relationship mappings and automatically defines them for all relationship mappings. You can use these keys to join across a relationship. One-to-one query keys define a joining relationship and are accessed through the get() method in expressions.

One-to-many and many-to-many query keys define a distinct join across a collection relationship and accessed through the anyOf() method in expressions. You can also define relationship query keys manually if mapping does not exist for the relationship. The relationship defined by the query key is data-level expressions.

Example 4-5 One-to-one Query Key

The following code example illustrates using a one-to-one query key within the TopLink expression framework

ExpressionBuilder employee = new ExpressionBuilder();
Vector employees = session.readAllObjects(Employee.class, 
employee.get("address").get("city").equal("Ottawa"));

Defining Relationship Query Keys by Amending a Descriptor

Relationship query keys are not supported directly in the Mapping Workbench. To define a relationship query key, you must specify and write an amendment method. Register query keys by sending the addQueryKey() message.

Example 4-6 Defining One-to-one Query Key Example

The following code example illustrates how to define a one-to-one query key.

// Static amendment method in Address class, addresses do not know their owners 
in the object-model, however you can still query on their owner if a 
user-defined query key is defined
public static void addToDescriptor(Descriptor descriptor)
{
OneToOneQueryKey ownerQueryKey = new OneToOneQueryKey();
ownerQueryKey.setName("owner"); 
ownerQueryKey.setReferenceClass(Employee.class);
ExpressionBuilder builder = new ExpressionBuilder();
ownerQueryKey.setJoinCriteria(builder.getField("EMPLOYEE.ADDRESS_
ID").equal(builder.getParameter("ADDRESS.ADDRESS_ID")));
descriptor.addQueryKey(ownerQueryKey);
}

Working with Events

Use the event manager to specify specific events to occur whenever TopLink performs a read, update, delete, or insert on the database.


Note:

TopLink uses the Java event model.


Applications can receive descriptor events in the following ways:

Objects that implement the DescriptorEventListener interface can be registered with the descriptor event manager to be notified when any event occurs for that descriptor.

Alternately, you may wish to use the DescriptorEventAdapter class if your application does not require all of the methods defined in the interface. The DescriptorEventAdapter implements the DescriptorEventListener interface and defines an empty method for each method in the interface. To use the adapter, you must subclass it and then register your new object with the descriptor event manager.

Descriptor events can be used in many ways, including:

Use the descriptor's Event tab (see Figure 4-12) to specify events for a descriptor.

Example 4-7 Event

For example, if you want to invoke a method called postBuild() for an Employee object, the postBuild() method must be implemented in the Employee class. This method must also accept one parameter that is an instance of DescriptorEvent fully qualified with a package name.

Registering an Event with a Descriptor

A persistent class can register a public method as an event method. A descriptor calls the event method when a particular database operation occurs.

Event methods:

Example 4-8 Registering an Event

The following code illustrates an event method definition.

Supported Events

Events supported by the DescriptorEventManager include:

Post-X Methods:
Updating Methods:
Inserting Methods:
Writing Methods:
Deleting Methods:

Working with Finders

In TopLink, use named queries to represent SQL or EJBQL finders to use in database accesses. You can create these finders within the mapping workbench.

When you create a finder for an EJB, the Mapping Workbench creates a named query and populates the descriptor alias with information from the ejb-jar.xml file.

Reserved finders are valid for projects with CMP persistence.

Working with Object-relational Descriptors

The object-relational paradigm extends traditional relational databases with object-oriented functionality. Oracle, IBM DB2, Informix and other DBMS databases allow users to store, access, and use complex data in more sophisticated ways.

The object-relational standard is an evolving standard and is mainly concerned with extending the database data structures and the SQL language (SQL 3).

The new features include:

Coinciding with object-relational changes, most database vendors are also extending their server architectures to support features such as:

This section describes how the object-relational features affect TopLink descriptors and mappings. The server architecture changes are discussed in the Oracle9iAS TopLink: Foundation Library Guide.

Effect on TopLink

Object-relational databases introduce several new features that allow more complex data to be stored and accessed. One advantage of object-relational databases is that the differences between the object model and data model can be reduced to the point that the two are almost identical. Although this makes the object-relational mapping process easier, it does not reduce the need for a persistence framework such as TopLink. Although the JDBC standard has been improved to take advantage of object-relational features in JDBC 2.0, it still remains a very low-level database interface. On top of JDBC, frameworks such as TopLink can provide applications with much more sophisticated functionality, including units of work, identity maps, expressions, querying, complex mappings, three-tier and enterprise application support.

TopLink provides object-relational support through a new type of descriptor object and several new types of mappings. See Chapter 7, "Understanding Object Relational Mappings" for more information.

Databases Supported

TopLink supports any JDBC 2.0 driver that complies with JDBC's 2.0 object-relational extensions. Contact your database and JDBC vendor to determine which object-relational features they support.

Defining Object-relational Descriptors

The TopLink Mapping Workbench does not currently support the object-relational descriptor and mappings. Support will be added to the Mapping Workbench in future releases.

You should be able to import most of the simple object-relational table structures into TopLink. Also, you can define the standard non-object-relational descriptor properties and mappings. You can use amendment methods to add any object-relational mappings and features to the descriptors.

Working with Mappings

In TopLink, mappings define how an object's attributes are represented in the database.

All of the mapping classes are derived from the DatabaseMapping class, as illustrated in Figure 4-32.

Figure 4-32 Mapping Classes Hierarchy

Text description of mapclass.gif follows.

Text description of the illustration mapclass.gif

Working with Common Mapping Properties

TopLink associates each mapping with the attribute whose persistence it describes. To create a mapping in the Mapping Workbench, select the attribute to map from the Project Tree pane and then click on the appropriate button in the mapping toolbar (see Figure 1-5).

Use the mapping's Properties pane to enter specific information for the mapping. Some mappings require more information that others and have multiple tabs in the Properties pane.

Figure 4-33 Sample Properties for a Mapping

Text description of 1mmapgen.gif follows.

Text description of the illustration 1mmapgen.gif

Mapping properties called out in Figure 4-33:

  1. Specify if read-only

  2. Specify access method

Specifying Direct Access and Method Access

By default, TopLink uses direct access to access public attributes. Alternatively, you can use accessor methods to access object attributes when writing the attributes of the object to the database or reading the attributes of the object from the database. This is called method access.

The attribute's visibility (public, protected, private or package visibility) and the supported version of JDK may restrict the type of access that you can use.

Starting in JDK 1.2, the Java Core Reflection API provides a means to suppress default Java language access control checks when using reflection. TopLink uses reflection to access the application's persistent objects. This means that if you are using a VM that supports the API, then TopLink can access an attribute directly, regardless of its declared visibility.


Note:

Private variable access under JDK 1.2 requires you to enable the security setting. Consult the JDK documentation for more information.


Oracle recommends using direct access whenever possible to improve performance and avoid executing any application-specific behavior while building objects.

Setting the Access Type

Use the General tab of the mapping Properties pane (see Figure 4-33) to set the access type as direct or method-based

To change the default access type used by all new mappings, use Defaults tab on the project Properties pane. See "Working with Default Properties" for more information.


Note:

If you change the access default, existing mappings retain their current access settings but new mappings will be created with the new default.


Specifying Read-only Settings

Use the Read Only check-box on the General tab of the mapping Properties pane (see Figure 4-33) to set a mapping to be read only. TopLink will not consider attributes associated with read-only mappings during update, and delete operations.

Because these operations are not actually performed for the mapping, any processes that are dependent on these operations (such as custom SQL or descriptor events) are not called for read-only. The attributes are still used for read operations.


Note:

The primary key mappings must not be read-only.


Mappings defined for the write-lock or class indicator field must be read-only, unless the write-lock is configured not to be stored in the cache and the class indicator is part of the primary key.

Defaulting Null Values

Direct mappings include a nullValue attribute. Use this attribute to convert database null values to application-specific values (if application does not allow null values). This applies when typed as primitives. The null value must be set to the desired value, not the database value.

Null values translate in two directions: from null values read from the database to the specified value and from the specified value back to null when writing or querying. You can also use TopLink to set global default null values on a per-class basis. For more information, refer to the Oracle9iAS TopLink: Foundation Library Guide.

Select the Use Default Value when Database Field is Null option on the General tab (see Figure 4-33) and the Type and Value drop-down lists to specify the null value.


Note:

You must specify the Type and Value in the mapping form.


Maintaining Bidirectional Relationships

Use the Maintain Bidirectional Relationship Only check-box on the General tab of the mapping Properties pane (see Figure 4-33) to maintain a bidirectional relationship for a one-to-one or one-to-many mapping. You can also specify the relationship partner.

Specifying Field Names and Multiple Tables

When defining mappings in code, TopLink assumes all mappings are in first table specified by the descriptor's setTableName() or addTableName() method. If the persistent class stores information in multiple tables, any messages sent that require field names should implemented to pass fully qualified names (that include the table name). Use the following syntax to fully qualify a field:

someMessage("tablename.fieldname");

Specifying Collection Properties

Some relationship mapping types (direct collection, one-to-many, and many-to-many) contain a Collection Options tab to allow you to specify collection options.

TopLink can populate a collection in ascending or descending order upon your specification. Query keys are automatically created for and with the same name as all attributes mapped as direct-to-field, type conversion, object type, and serialized object mappings.

Figure 4-34 Collection Options

Text description of collects.gif follows.

Text description of the illustration collects.gif

Use this table to enter data in each field:

Field Description

Java 2 Collections:

    Collection or Map Class

    Key Method

Select the collection or map class to use for this collection mapping.

Order Query Results

Specify how the collection results are sorted for queries.

Specifying Mapping information in ejb-jar.xml File

For 2.0 CMP projects, the ejb-jar.xml files stores information on bean-to-bean relationships (i.e., mappings) in the <relationship> element. By updating this information in the ejb-jar.xml, the Mapping Workbench will create new mappings. You can then update the mapping information (such as reference tables).

If the information does not exist in the ejb-jar.xml file, you can build the mappings in the Mapping Workbench, then write the information to the file. See "Writing to the ejb-jar.xml File" for more information.


Go to previous page Go to next page
Oracle
Copyright © 2002 Oracle Corporation.

All Rights Reserved.
Go To Documentation Library
Home
Go To Solution Area
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index