Skip Headers

Oracle TopLink Developer's Guide 10g Release 3 (10.1.3) B13593-01 |
| Home | Solution Area | Contents | Index

Previous | Next |

# Configuring Query Keys

A query key is a schema-independent alias for a database field name. For example, consider a class `Employee` with attribute `firstName` mapped directly to a database field `F_NAME` in database table `EMPLOYEE`. Without a query key, when you create a query or expression that involves `Employee` attribute `firstName`, you must use the database management system-specific field name `F_NAME`. This makes it more difficult to build a query and ties the query to the schema. With a query key, you can refer to this field using a schema-independent alias, such as `firstName`.

Table 28-11 summarizes which descriptors support query keys.

Table 28-11 Descriptor Support for Query Keys

Descriptor | Using TopLink Workbench | Using Java
--- | --- | ---
Relational Descriptors |  |
Object-Relational Descriptors |  |
EIS Descriptors |  |
XML Descriptors |  |

Using query keys offers the following advantages:

- Enhances code readability in TopLink expressions and simplifies expression development. You can compose expressions entirely within the context of your object model.

- Increases portability by making code independent of the database schema. If you rename a field in your schema, you can redefine the query key without changing any code that uses it.

- Query keys used with interface descriptors allow the implementor descriptor's tables to have different field names.

Query keys are automatically generated for all mapped attributes. The name of the query key is the name of the class attribute specified in your object model.

For information on how to use query keys in queries and expressions, see "Query Keys".

When query keys are generated and how you can add or modify query keys depends on the type of mapping or descriptor involved:

- Direct Mappings

- Relationship Mappings

- Interface Descriptors

Direct Mappings

TopLink Workbench automatically generates query keys for all direct mappings at the time you create the mapping.

TopLink Workbench provides support for adding or modifying query keys for simple unmapped attributes that could be mapped by a direct mapping: for example, the `version` field used for optimistic locking or the `type` field used for inheritance. You cannot modify or remove automatically generated query keys.

Relationship Mappings

TopLink automatically generates query keys for all relationship mappings at run time.

For example, if you have a class `Customer` with attribute `orders` mapped in a one-to-many relationship to class `PurchaseOrders`, then the TopLink runtime will generate a query key named `orders` for this `Customer` attribute.

TopLink Workbench does not currently support adding or modifying the query keys for relationship mappings. If you must add or modify such a query key, you must do so in Java code, using a descriptor amendment method.

Interface Descriptors

Interface descriptors (see "Relational Interface Descriptors") define only the query keys that are shared among their implementors. In the descriptor for an interface, only the name of the query key is specified.

TopLink Workbench provides support for choosing the implementors of an interface that share at least one common automatically generated query key (see "Configuring Interface Query Keys").

## Using TopLink Workbench

To add query keys to simple unmapped fields and to view the query keys automatically generated for directly mapped attributes, use this procedure:

1. Select a descriptor in the Navigator. Its properties appear in the Editor.

2. Click the Query Keys tab in the Editor.

   Figure 28-22 Query Keys Tab

To add a new query key, click Add.

To delete an existing query key, select the query key and click Remove.

To rename an existing query key, select the query key and click Rename.

Use the Field list to select the field in the table associated with the query key.

## Using Java

To manually create a relationship query key, implement a descriptor amendment method (see "Configuring Amendment Methods") that uses one of the following `ClassDescriptor` methods to register the query keys:

- `addQueryKey`–specify a query key using an instance of `QueryKey` such as `DirectQueryKey`, `DirectCollectionQueryKey`, `ManyToManyQueryKey`, `OneToManyQueryKey`, or `OneToOneQueryKey`.

- `addDirectQueryKey`–add a query key that maps directly to the given database field.

- `addAbstractQueryKey`–add an abstract query key to an interface descriptor. Any implementors of that interface must define the query key defined by this abstract query key.

Examples (UNKNOWN STEP NUMBER) , (UNKNOWN STEP NUMBER) , and (UNKNOWN STEP NUMBER) illustrate how to define a query key in Java code.

Example 28-3 Defining a Query Key

    // Add a query key for the foreign key field using the direct method
    descriptor.addDirectQueryKey("managerId", "MANAGER_ID");

    // The same query key can also be added through the addQueryKey method
    DirectQueryKey directQueryKey = new DirectQueryKey();
    directQueryKey.setName("managerId");
    directQueryKey.setFieldName("MANAGER_ID");
    descriptor.addQueryKey(directQueryKey);

    /* Add a one-to-one query key for the large project of which the employee is a leader (this assumes only one project) */
    OneToOneQueryKey projectQueryKey = new OneToOneQueryKey();
    projectQueryKey.setName("managedLargeProject");
    projectQueryKey.setReferenceClass(LargeProject.class);
    ExpressionBuilder builder = new ExpressionBuilder();
    projectQueryKey.setJoinCriteria(builder.getField("PROJECT.LEADER_ID").
        equal(builder.getParameter("EMPLOYEE.EMP_ID")));
    descriptor.addQueryKey(projectQueryKey);

Example 28-4 Defining a One-to-Many Query Key

    /* Add a one-to-many query key for the projects where the employee manages multiple projects */
    OneToManyQueryKey projectsQueryKey = new OneToManyQueryKey();
    projectsQueryKey.setName("managedProjects");
    projectsQueryKey.setReferenceClass(Project.class);
    ExpressionBuilder builder = new ExpressionBuilder();
    projectsQueryKey.setJoinCriteria(builder.getField("PROJECT.LEADER_ID").     equal(builder.getParameter("EMPLOYEE.EMP_ID")));
    descriptor.addQueryKey(projectsQueryKey);

Example 28-5 Defining a Many-to-Many Query Key

    /* Add a many-to-many query key to an employee project that uses a join table*/
    ManyToManyQueryKey projectsQueryKey = new ManyToManyQueryKey();
    projectsQueryKey.setName("projects");
    projectsQueryKey.setReferenceClass(Project.class);
    ExpressionBuilder builder = new ExpressionBuilder();
    projectsQueryKey.setJoinCriteria(builder.getTable("EMP_PROJ").getField("EMP_ID").equal(builder.getParameter("EMPLOYEE.EMP_ID").and(builder.getTable("EMP_PROJ").getField("PROJ_ID").equal(builder.getField("PROJECT.PROJ_ID")));
    descriptor.addQueryKey(projectsQueryKey);

Example 28-6 illustrates how to implement a `Descriptor` amendment method to define a one-to-one query key. In this example, the object model for the `Address` class does not include a reference to its owner, an `Employee` object. You can amend the `Address` class descriptor to add a query key named `owner` to make up for this deficiency. At run time, you can compose expressions that select `Address` objects based on this `owner` query key.

Example 28-6 Defining a One-to-One Query Key with an Amendment Method

    /* 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);
    }