Oracle® Application Server TopLink Application Developer's Guide
10g Release 2 (10.1.2) Part No. B15901-01 |
|
Previous |
Next |
Inheritance enables you to share attributes between objects such that a subclass inherits attributes from its parent class. OracleAS TopLink provides several methods to preserve inheritance relationships, and enables you to override mappings that are specified in a superclass, or to map attributes that are not mapped in the superclass. Subclasses must include the same database field (or fields) as the parent class for their primary key (although the primary key can have different names in these two tables). As a result, when you are mapping relationships to a subclass stored in a separate table, the subclass table must include the parent table primary key, even if the subclass primary key differs from the parent primary key.
This section describes OracleAS TopLink inheritance, and introduces several topics and techniques to leverage inheritance in your own applications, including:
For more information about implementing inheritance in code, see "Implementing Inheritance in Java".
Consider a simple database used by a courier company. It contains registration information for three types of vehicles: trucks, cars, and bicycles. For each vehicle type, your application requires the following information:
VID (Vehicle Identification)
LastMaint (mileage since last maintenance)
LoadCap (load capacity)
If these are all the attributes shared by all vehicles in the application, then these attributes must all appear in the super class, Vehicle. You can then build subclasses for each of the vehicle types that reflects their differences. For example, the Truck class may have an attribute indicating whether the local department of transportation considers it to be a commercial vehicle (NumAxles), the Car class may require a NumPass (number of passengers) attribute, and the Bicycle class, by virtue of its more limited range, may require a Location attribute. Through inheritance, each vehicle automatically inherits the basic vehicle information, but by being separate subclasses, also have unique characteristics.
You can represent inheritance in the database in one of two ways:
Multiple tables that represent the parent class and each child class
A single table that comprises the parent and all child classes
Figure 3-7 Inheritance in the Database in Individual Tables
If your database already represents the objects in the inheritance hierarchy this way, you can map the objects and relationships without modifying the tables. However, it is most efficient to represent all classes from a given inheritance hierarchy in a single table, because it substantially reduces the number of table reads and eliminates joins when querying on objects in the hierarchy.
Figure 3-8 Inheritance in the Database in a Single Table
To consolidate tables in the database this way, determine the class type of the objects represented by the rows in the table. There are two ways to determine class type:
If you can add columns to the database table, add a class indicator column that represents the vehicle class type (Truck, Car, or Bicycle).
For more information about class indicators, see "Class Indicators".
If you cannot modify the table, build a class extraction method that executes an appropriate login to determine the class type.
For more information about class extraction methods, see "Class Extraction Methods".
The OracleAS TopLink inheritance hierarchy includes three types of classes:
The root class stores information for all instantiable classes in its subclass hierarchy. By default, queries performed on the root class return instances of the root class and its instantiable subclasses. However, you can also configure the root class to return only instances of itself, without instances of its subclasses when queried. All class types beneath the root class inherit from the root class.
Branch classes have a persistent superclass and subclasses. By default, queries performed on the branch class return instances of the branch class and any of its subclasses. As with the root class, you can configure the branch class to return only instances of itself, without instances of its subclasses when queried. All classes below the branch class inherit attributes from the branch class, including any attributes the branch class inherits from classes above it in the hierarchy.
A class indicator is a mechanism for determining the class or type of an object. For example, a Person table may include an indication of whether the person represented by the table row is an Employee or a Manager. Use the class indicator to select the appropriate subclass to be instantiated from a set of available subclasses.
A class indicator field is a number or string stored in a database table that indicates the class or type of an object. OracleAS TopLink uses this information to determine the correct type of object to instantiate when building an object from that data in the row. For example, an EMPLOYEE
table may contain a field, the value of which indicates whether the employee is permanent or contract, and determines whether OracleAS TopLink instantiates a PermanentEmployee
object or a ContractEmployee
object.
You can use strings or numbers as values in the class indicator field in the database. The root class descriptor must specify how the value in the class indicator field translates into the class to be instantiated.
Class indicator fields do not have an associated direct mapping unless the mapping is set to 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.
For more information about transformation mappings, see "Transformation Mappings".
Class extraction enables you to determine the correct class type to instantiate from a table that includes several classes. Unlike a class indicator, however, a class extraction method does not rely on a single column in the table to determine class type. Instead, you can apply logic to the information in several fields to determine class type.
This method is useful when you use a legacy database with a new application. Table 3-1 illustrates a sample use of the class extraction method.
Table 3-1 Sample Use of the Class Extraction Method
ID | NAME | JOB_TYPE | JOB_TITLE |
---|---|---|---|
732 | Bob Jones | 1 | Manager |
733 | Sarah Smith | 3 | Technical Writer |
734 | Ben Ng | 2 | Director |
735 | Sally Johnson | 3 | Programmer |
The inheritance hierarchy is designed such that Employee is the root class, and Director is a branch class that inherits from Employee. All employees, other than directors, are represented as instances of Employee, but directors must be represented by an instance of the Director class. Because values other than 2 can appear in the JOB_TYPE field, you cannot use the class indicator mechanism of OracleAS TopLink for mapping this data.
To resolve this, add a class extraction method to the root class, Employee. The method executes custom logic to determine the correct class to instantiate. The method is static, returns a Class object, and takes DatabaseRow
as a single parameter.
Example 3-24 Simple Class Extraction Method
// Return the Director class for TYPE values of 2, // Employee class for any other value public static Class getClassFromRow(DatabaseRow row) { if (row.get("JOB_TYPE").equals(new Integer(2)) { return Director.class; } else { return Employee.class; } }
This simple case enables you to determine whether the selected person is of the Director class or the Employee class. You can also implement complex logic that combines information from several columns in the table to infer class type. For example, consider a table that represents vehicles in a municipal vehicle pool.
Table 3-2 Gross Vehicle Weight and Number of Axles Example
Gross Vehicle Weight | Number Of Axles |
---|---|
2650 | 3 |
800 | 2 |
2730 | 2 |
2400 | 2 |
3580 | 4 |
Although there is no direct indication of vehicle type in the data, you can build logic into a class extraction method to infer the vehicle type. This is made easier if you are familiar with the available types in the database. In this example, you can use a class extraction method to implement the following logic:
If NumberOfAxles
is greater than 2, then return the class HeavyTruck
.
If NumberOfAxles
is 2 or less and GrossVehicleWeight
is greater than 1000, then return the class type PassengerVehicle
.
In all other cases, return the class Motorcycle
.
Example 3-25 Complex Class Extraction Method
public static Class getClassFromRow(DatabaseRow row) { if (row.get("NumberOfAxles").intValue()>2){ return HeavyTruck.class; } else { if (row.get("GrossVehicleWeight").intValue()>1000) { return PassengerVehicle.class; } else { return Motorcycle.class; } } }
In addition to implementing logic to determine object class, you can use class extraction methods to execute other methods unrelated to class determination. This is an unusual use for class extraction methods, but, provided that the method ultimately returns a class type, it is possible.
To implement the class extraction method in OracleAS TopLink Mapping Workbench, open the inheritance settings for the root descriptor in the subclass hierarchy (EMPLOYEE
in this case), and select the class extraction method in the Use Class Extraction Method box.
The following restrictions apply to entity beans when using inheritance:
The Home
interfaces cannot inherit. The findByPrimaryKey
method must be overloaded to have the correct return type, but this is not allowed. Because of this, inheritance is not applicable to the Home
interfaces.
The primary key of the subclass must be the same as that of the parent class.
The Application Server EJB 1.1 and 2.0 CMP Advanced Examples illustrate inheritance. For more information, see the OracleAS TopLink Examples at <ORACLE_HOME>
\toplink\doc\examples.htm
.