Skip Headers
Oracle TopLink Developer's Guide
10g Release 3 (10.1.3)
B13593-01
  Go To Documentation Library
Home
Go To Product List
Solution Area
Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
Next
Next
 

Descriptor Concepts

This section introduces descriptor concepts unique to TopLink, including the following:

Descriptor Architecture

A descriptor stores all the information describing how an instance of a particular object class can be represented in a data source.

TopLink descriptors contain the following information:

  • The persistent Java class it describes and the corresponding data source (database tables, XML complex type, or EIS interaction)

  • A collection of mappings, which describe how the attributes and relationships for that class are stored in the database

  • The primary key information (or equivalent) of the data source

  • A list of query keys (or aliases) for field names

  • Information for sequence numbers

  • A set of optional properties for tailoring the behavior of the descriptor, including support for caching refresh options, identity maps, optimistic locking, the event manager, and the query manager

There is a descriptor type for each data source type that TopLink supports. In some cases, multiple descriptor types are valid for the same data source type. The type of descriptor you use determines the type of mappings that you can define.

Table 26-2 summarizes the relationship between project, descriptor, and mappings.

Descriptors and Inheritance

Inheritance describes how a derived (child) class inherits the characteristics of its superclass (parent). You can use descriptors to describe the inheritance relationships between classes in relational, EIS, and XML projects.

In the descriptor for a child class, you can override mappings that have been specified in the descriptor for a parent class, or map attributes that have not been mapped at all in the parent class descriptor.

For more information, see "Understanding Descriptors and Inheritance".

Descriptors and EJB

You can use descriptors to describe the characteristics of CMP and BMP entity beans.

When mapping EJB, you create a descriptor for the bean class: you do not create a descriptor for the local interface, remote interface, home class, or primary key class.

When using TopLink Workbench, you must define the project with the correct EJB type (such as CMP or BMP) and import the ejb-jar.xml file for the beans into the TopLink Workbench project.

For CMP 2.0 projects, you use the ejb-jar.xml file to define the bean's mapped attributes. A CMP bean descriptor contains a CMP policy used to configure CMP-specific options.

For CMP 3.0 projects, you can use annotations to define the bean's mapped attributes.

This section describes:

Nondeferred Changes

By default, TopLink defers all changes until commit time: this is the most efficient approach that produces the least number of data source interactions.

Alternatively, you can configure an entity bean's descriptor for nondeferred changes. This means that as you change the persistent fields of the entity bean, TopLink CMP modifies the relational schema immediately.

Using nondeferred changes, you can achieve backward compatibility with the native behavior of some CMP containers (such as OC4J). You can also accommodate advanced applications that rely on the database and entity changes being synchronized for such things as triggers or stored procedures based on transient state within the transaction, deletion and creation of rows with the same primary key, or other complex queries that depend on transient transaction state.

Nondeferred changes have the disadvantage of being the least efficient approach: they produce the greatest number of data source interactions.

When you configure TopLink CMP to support nondeferred changes, TopLink will continue to handle constraints for mapped relationships among entity beans with the same deferral setting. However, you are responsible for handling any errors that result from making changes to a class that is not deferred, but related to a class that is deferred when a constraint exists between these two classes.


Note:

When you configure a descriptor for nondeferred changes, TopLink CMP does not apply nondeferred changes to dependent objects. Dependent objects are subject to default deferred changes: the relational schema is not modified until commit.

For more information, see "Configuring a Descriptor With EJB Information".

Creating a New Entity Bean and ejbCreate / ejbPostCreate Methods

When you create a new entity bean, by default, the EJB life cycle can be thought of as follows:

  1. ejbCreate method:

    After the insert, the CMP container retrieves the primary key allocated by the database for the created instance.

    For a relational project:

    1. INSERT INTO ...

    2. SELECT FROM ...

    For an EIS project:

    1. Write object ...

    2. Find object ...

  2. ejbPostCreate method:

    The CMP container updates container-managed relationship (CMR) fields. The CMP container needs the primary key obtained in the ejbCreate method.

    For a relational project:

    1. UPDATE SET ...

    For an EIS project:

    1. Write object ...

However, if you have non-null foreign key constraints in your database, doing a data source modification after the ejbCreate method executes can cause problems. To get around this, some application servers (such as OC4J) allow you to create new objects after the ejbPostCreate method executes, and rely on the container to resolve the foreign key constraint.

For more information, see "Configuring a Descriptor With EJB Information".

Inheritance

Although the EJB 2.0 specification does not define inheritance, TopLink allows you to configure inheritance for CMP descriptors, with some reservations.

For more information, see "Inheritance and EJB".

Fetch Groups

By default, when you execute an object-level read query for a particular object class, TopLink returns all the persistent attributes mapped in the object's descriptor. With this single query, all the object's persistent attributes are defined, and calling their get methods returns the value directly from the object.

When you are interested in only some of the attributes of an object, it may be more efficient to return only a subset of the object's attributes using a fetch group with which you can define a subset of an object's attributes and associate the fetch group with either a ReadObjectQuery or ReadAllQuery query.

For more information see:

Amendment and After-Load Methods

Using TopLink Workbench, you can associate a static Java method that is called when a descriptor is loaded at run time. This method can amend the run-time descriptor instance through the descriptor Java code API. Use this method to make some advanced configuration options that may not be currently supported by TopLink Workbench.Descriptors can only be modified before the session has been connected; descriptors should not be modified after the session has been connected.

For more information, see "Configuring Amendment Methods".

Descriptors and Aggregation

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 data source representation 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.

In this case, the descriptors for the source and target objects must be designated to reflect this relationship as follows:

Aggregate and Composite Descriptors in Relational Projects

In a relational project, you can designate the descriptor as an aggregate (see "Relational Aggregate Descriptors").

This lets you configure an aggregate mapping (see "Configuring a Relational Aggregate Object Mapping") to associate data members in the target object with fields in the source object's underlying database tables.

When you designate a relational descriptor as an aggregate, TopLink lets you specify a mapping type for each field in the target class, but defers associating the field with a database table until you configure the aggregate object mapping in the source descriptor. In other words, the target class descriptor defines how each target class field is mapped, but the source class descriptor defines where each target class field is mapped. This lets you share an aggregate object among many parent descriptors mapped to different tables.

When you designate a relational descriptor as an aggregate, you tell TopLink that the class will be a target of an aggregate object mapping, and this ensures that the TopLink runtime handles the target class as follows:

  • It inserts, updates, and deletes the target class in parallel with its source class.

  • It does not cache the target class on its own; instead, it caches the target class as part of its source class.

  • It does not allow the target class to be read, written, deleted, or registered in a unit of work.

When working with aggregate relational descriptors, consider the following:

For more information, see "Configuring a Relational Descriptor as a Class or Aggregate Type".

Relational Aggregates and Nesting

TopLink supports nested aggregates. In Figure 26-1 source class HockeyPlayer is a normal nonaggregate class descriptor. It owns target class Info which is designated as an aggregate. The Info class itself owns target classes PersonalInfo and TeamInfo which are each designated as aggregates.

Figure 26-1 Nested Aggregates

Description of Figure 26-1  follows
Description of "Figure 26-1 Nested Aggregates"

In EJB 3.0, an aggregate is known as an embeddable. In the EJB 3.0 specification, an embeddable may not contain another embeddable (that is, the EJB 3.0 specification does not support nested aggregates).

However, if you deploy a TopLink-enabled EJB 3.0 CMP application to OC4J, you can take advantage of a TopLink extension of the EJB 3.0 specification to configure nested embeddables. Note that if you do so, your application will not be strictly EJB 3.0 compliant. Example 26-1 shows the classes from Figure 26-1 using EJB 3.0 annotations to take advantage of the TopLink extension of the EJB 3.0 specification to allow Info (an embeddable) to own embeddables TeamInfo and PersonalInfo.

Example 26-1 Nested Embeddables

public class HockeyPlayer implements Serializable {
    private int playerId;
    private Info Info;
    private String lastName;
    private String firstName;
    ...
    @Embedded
    public Info getInfo() {
        return Info;
    }
}
 
@Embeddable
public class Info implements Serializable {
    TeamInfo teamInfo; // TopLink extension of EJB 3.0 allows Embeddable with Embeddable
    PersonalInfo personalInfo;
    
    public Info() {}
    
    @Embedded
    public PersonalInfo getPersonalInfo() {
        return personalInfo;
    }
    
    public void setPersonalInfo(PersonalInfo personalInfo) {
        this.personalInfo = personalInfo;
    }
    
    @Embedded
    public TeamInfo getTeamInfo() {
        return teamInfo;
    }
    
    public void setTeamInfo(TeamInfo teamInfo) {
        this.teamInfo = teamInfo;
    }
}
 
@Embeddable
public class PersonalInfo implements Serializable {
    private int age;
    private double weight;
    private double height;
    ...
}
 
@Embeddable
public class TeamInfo implements Serializable {
    private String position;
    private int jerseyNumber;
    private HockeyTeam hockeyTeam;
    ...
}

Relational Aggregates and Inheritance

You can configure inheritance for a relational 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.

Relational Aggregates and EJB

You can use relational aggregate descriptors in an EJB project, but you cannot configure EJB information for a relational descriptor designated as an aggregate (see "Descriptors and EJB").

For more information on using relational aggregates and EJB 3.0, see "Relational Aggregates and Nesting".

Root and Composite Descriptors in EIS Projects

In an EIS project, you can designate the descriptor as a composites (see "EIS Composite Descriptors").

The type of EIS mapping you whish to create will determine whether you configure an EIS descriptor as a composite or root (see "Composite and Reference EIS Mappings").

For more information, see "Configuring an EIS Descriptor as a Root or Composite Type".

You cannot configure EJB information for an EIS descriptor designated as an composite (see "Descriptors and EJB").

You can configure inheritance for an EIS descriptor designated as a composite (see "Descriptors and Inheritance"), however, in this case, all the descriptors in the inheritance tree must be composites. Composite and root descriptors cannot exist in the same inheritance tree.

Composite Descriptors in XML Projects

In an XML project, descriptors are always composites.

Because XML descriptors are always composites, you can configure inheritance for an XML descriptor without considering its type (see "Descriptors and Inheritance").

Descriptor Event Manager

In relational and EIS projects, TopLink raises various instances of DescriptorEvent (see Table 28-25 and Table 28-27) during the persistence life cycle. Each descriptor owns an instance of DescriptorEventManager that is responsible for receiving these events and dispatching them to the descriptor event handlers registered with it.

Using a descriptor event handler, you can execute your own application specific logic whenever descriptor events occur, allowing you to take customized action at various points in the persistence life-cycle. For example, using a descriptor event handler, you can do the following:

  • Synchronize persistent objects with other systems, services, and frameworks.Maintain nonpersistent attributes of which TopLink is not aware.

  • Notify other objects in the application when the persistent state of an object changes.

  • Implement complex mappings or optimizations not directly supported by TopLink mappings.

For more information, see the following:

Descriptor Query Manager

Each relational and EIS descriptor provides an instance of DescriptorQueryManager that you can use to configure the following:

For more information on using the query manager, see "Descriptor Query Manager Queries".

Descriptors and Sequencing

An essential part of maintaining object identity is managing the assignment of unique values (that is, a specific sequence) to distinguish one object instance from another. For more information, see "Projects and Sequencing".

Sequencing options you configure at the project (or session) level determine the type of sequencing that TopLink uses. In a CMP project, you typically configure the sequence type at the project level (see "Configuring Sequencing at the Project Level"). In a non-CMP project, you can use session-level sequence configuration to override project-level sequence configuration, on a session-by-session basis, if required (see "Configuring Sequencing at the Session Level").

After configuring the sequence type, for each descriptor's reference class, you must associate one attribute, typically the attribute used as the primary key (see "Configuring Primary Keys"), with its own sequence (see "Configuring Sequencing at the Descriptor Level").

Descriptors and Locking

You can configure a descriptor with any of the following locking policies to control concurrent access to a domain object:

  • Optimistic–All users have read access to the data. When a user attempts to make a change, the application checks to ensure the data has not changed since the user read the data (see "Optimistic Version Locking Policies" and "Optimistic Field Locking Policies").

  • Pessimistic–The first user who accesses the data with the purpose of updating it locks the data until completing the update (see "Pessimistic Locking Policy").

  • No locking–The application does not prevent users overwriting each other's changes.

Oracle recommends using optimistic locking for most types of applications to ensure that users do not overwrite each other's changes.

For more information, see the following:

Default Root Element

You must configure EIS root descriptors ("Configuring Default Root Element") and XML descriptors ("Configuring Default Root Element") with a default root element so that the TopLink runtime knows the data source data type associated with the class the descriptor describes.

This section describes what a default root element is and how TopLink uses it.

Consider the Customer and Address classes and their mappings shown in Example 26-2.

Example 26-2 Customer and Address Classes

Class: Customer
Default Root: customer
Attributes and Mappings:
    name:String                Drect Mapping to                name/text()
    billingAddress:Address     Composite Object Mapping to     billing-address
    shippingAddress:Address    Composite Object Mapping to     shipping-address

Class: Address
Default Root: address
Attributes and Mappings:
    street:String              Direct Mapping to               street/text()
    city:String                Direct Mapping to               city/text()

These classes correspond to the XML schema shown in Example 26-3.

Example 26-3 Customer and Address Schema

<xsd:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xsd:complexType name="address-type">
        <xsd:sequence>
            <element name="street" type="xsd:string"/>
            <element name="city" type="xsd:string"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="customer" type="customer-type"/>
    <xsd:complexType name="customer-type">
        <xsd:sequence>
            <xsd:element name="name" type="xsd:string"/>
            <xsd:element name="billing-address" type="address-type"/>
            <xsd:element name="shipping-address" type="address-type"/>
        </xsd:sequence>
    </xsd:complexType>
</xsd:schema>

When an instance of the Customer class is persisted to XML, the TopLink runtime performs the following:

  1. Gets the default root element.

    The Customer class instance corresponds to the root of the XML document. The TopLink runtime uses the default root element specified on the descriptor (customer) to start the XML document. TopLink then uses the mappings on the descriptor to marshal the object's attributes:

    <customer>
        <name>…</name>
    </customer>
    
    
  2. When the TopLink runtime encounters an object attribute such as billingAddress, it checks the mapping associated with it to determine with what element (billing-address) to continue:

    <customer>
        <name>…</name>
        <billing-address/>
    </customer>
    
    

    The TopLink runtime checks the mapping's reference descriptor (Address) to determine what attributes to persist:

    <customer>
        <name>…</name>
        <billing-address>
            <street>…</street>
            <city>…</city>
        </billing-address>
    </customer>