As Published In
Oracle Magazine
November/December 2005

DEVELOPER: Frameworks


Working with Master/Detail Data

By Steve Muench Oracle ACE

Navigating, joining, and presenting related data in an easier way

This column ventures beyond the single-table examples of the past few columns to study the basics of working with data in two or more related tables. I’ll show you how to navigate the web of relationships in the data at runtime, how to join data from multiple tables, and how to present complex master/detail hierarchies of information to end users. You’ll see that the functionality provided by Oracle Application Development Framework (ADF) in this area is a superset of what’s possible to achieve in Oracle Forms using relationships between data blocks.

Using Associations to Create Entity Object Relationships

In a recent column, I showed that an Oracle ADF entity object is a business domain object that encapsulates application logic for rows in a particular database table. For a given type of entity object, such as an Order , Customer , or InventoryItem , a primary key uniquely identifies each instance and corresponds to the primary key of its underlying database row. Primary keys are reflected in the Oracle ADF layer, which helps make entity objects easy to understand and use. For example, if you know the key value for any entity object, you can easily find the instance at runtime using the findByPrimaryKey() method on the entity object’s definition class.

Oracle ADF also provides constructs to manage relationships across your business data. At the database level, you express relationships between rows in a source table and rows in a target table by using foreign key constraints. Oracle ADF uses an analogous concept, called an association , to capture relationships between two entity objects. Using the Create Association wizard in Oracle JDeveloper, you can easily create associations by first picking the corresponding attributes from source and target entity objects to define a relationship, and then indicating a cardinality (such as one-to-many).

However, you can make the process even easier by letting Oracle JDeveloper automatically create your associations using the Business Components from Tables wizard. This wizard reverse-engineers a set of Oracle ADF entity objects from your existing tables, giving you an entity object for each table—with its primary key set appropriately—along with an association relating each pair of entity objects whose underlying tables are related by foreign key constraints.

Unlike entity objects themselves, which comprise both XML component metadata and an optional custom entity Java class, associations are metadata only. This metadata lets the Oracle ADF runtime framework make additional association attributes available on an entity object. These attributes allow you to navigate from one entity instance to either another entity instance or a collection of related instances, depending on the cardinality of the association in question. For example, if you had an instance of an Order entity object, you could directly access its associated Customer entity object by using getAttribute("Customer") , and you could also access a collection of LineItem entity objects for this order by using getAttribute("LineItems") . Of course, you could choose the names of the association attributes as part of the association metadata, by using the Association Properties panel of the Association editor.

Code Listing 1: Validation method 

public boolean validateDiscountAmount() {
  return getDiscount().getValue() <= 0.05 || 
  getOrder().getCustomer().getStatus().equals("Gold");
}


Using Association Accessor Methods to Simplify Writing Business Rules

If you choose to generate the optional Java classes for your entity objects, Oracle JDeveloper will create corresponding type-safe accessor methods for association attributes, as it does for all attributes. These optional classes and accessor methods are created by default in Oracle JDeveloper. As a result, the two examples above could also be performed by calling the getCustomer() and getLineItems() methods, respectively.

These methods can greatly simplify the task of writing business rules. For example, suppose a LineItem entity object must enforce a business rule specifying that a discount cannot exceed 5 percent unless the customer placing the order is a gold customer. I can write a validation method like the one in Listing 1.

The method in Listing 1 returns true either when the discount is 5 percent or less, or when the customer is a gold customer. Notice the use of chained association accessors: first to getOrder() , then to getCustomer() , and then to getStatus() to get the status of that customer. If the related entity objects are already in the cache, this association navigation will execute instantly. If an associated entity is not yet in the cache when performing the association navigation, the Oracle ADF framework will fault it into the cache automatically by using the appropriate findByPrimaryKey() method discussed above to load all of the entity object’s attributes into the cache.

Leveraging Associations in Join View Objects

Associations do more than just simplify inter-entity navigation. They also make it easy to create view objects that join information from multiple tables. When you create a view object using the Create View Object wizard, you can select multiple entity objects to participate in the view object. If associations exist between those entities, the view object’s SQL query will automatically reflect the tables related to the entity objects involved, and its WHERE clause will already contain the correct join clauses. This is possible because each association captures all the metadata needed about the one or more pairs of entity attributes that relate the two entity objects in question, and each entity object knows how its entity attributes relate to columns of its underlying database table.

But association definitions provide another helpful feature related to join view objects. Associations provide for an automatic lookup of associated entity information when the value of the associated key is changed. For example, imagine a join view object named LineItems that includes a ProductId attribute from the LineItem entity and a ProductName attribute from the Product entity. If there is an association between LineItem and Product entities, then when the user enters or changes the value of the ProductId attribute, the ProductName will automatically update to reflect the product name with the new ProductId value.

In Oracle JDeveloper, you enable this reference feature when you select entity objects associated with a view object (using either the Create View Object wizard or the View Object editor on an existing view object). For each entity object you select, you’ll see a checkbox called reference. This reference flag indicates whether the selected entity object name is participating as reference information in the current view object. If the reference flag is checked for a given entity participating in the view object, and if an association exists between the primary entity in the view and this reference entity, then the framework will keep the reference entity’s information in sync with changes made to the foreign key value in the primary entity.

Using Oracle ADF View Links to Handle Master/Detail Queries

There are two basic approaches you can use to work with data from two tables in a one-to-many relationship. If your goal is to present data in the Many table alongside reference information from the One table in the same row, then a join view object is the right approach. The LineItems example above demonstrates this approach, by showing LineItem information such as ProductId and Quantity being ordered alongside reference information such as the ProductName , all in the same row.

If, however, your goal is to create something with a master/detail feel, where for each row in the One table, you want to show all of the rows in the Many table—perhaps not even displaying the detail information until the user drills down to see it—then you’ll want to use the second approach. In this case, you’ll want to create two separate view objects and link them in master/detail style using an Oracle ADF view link.

A view link is similar to an association. However, instead of relating two entity objects, a view link relates two view objects based on one or more pairs of source and target view attributes. View links can be directly based on underlying entity associations, or they can be defined by hand between any pairs of matching attributes. View links also let you customize the WHERE clause that’s appended at runtime to the detail view object to filter its results based on the current row in the master view object. This feature lets you declaratively capture more complex types of parameterized collections of related data. 

Next Steps


READ more about
Oracle JDeveloper 10g and Oracle ADF

DOWNLOAD
Oracle JDeveloper 10g

View links work similarly to associations, in that when you define a view link between two view objects, additional view link attributes become available at runtime on the view rows. These view link attributes let you navigate programmatically between source and target rows.

If you’re displaying both master and detail information in your user interface, view links also provide another convenient feature. When you add a detail view object to your application module’s data model as a child view object, the Oracle ADF framework will perform active master/detail coordination between the linked view object instances. As a result, whenever the current row in the master view object changes, the framework will actively execute the query in the detail view object, binding the primary key value for the new current master row, to retrieve the matching detail rows.

In Oracle JDeveloper, you set up this active master/detail coordination in the Data Model panel of the application module editor (it also appears in Step 2 of the Create Application Module wizard). In the Available list on the left, you see all of the view objects in your workspace. If any view object is involved in a view link, you'll see the corresponding detail view object indented beneath the master view object in the list. To define a data model with active master/detail coordination, first add an instance of the master view object to the data model. Next, click on that instance in the Selected list. Finally, select the desired detail view object that's indented under your master view object in the Available list, and add an instance of that object to the data model. At this point, the detail view object instance will be indented beneath the master view object instance in the Selected list.

You can repeat these steps to create master/detail hierarchies of any complexity, including any combination of: 

  • multi-level master/detail/detail

  • master with multiple (peer) details

  • detail with multiple masters

After designing the data model to your needs, you can bind data from any level to pages or panels in your user interface. And you don't have to worry about writing code to maintain master/detail relationships as users navigate your screens—the framework handles all the details for you.

Conclusion

You've seen in this column that by capturing the relationships between entity objects and view objects in metadata, the Oracle ADF framework can simplify many common tasks for you. You can combine the use of association, join view object, and view link techniques discussed here to achieve the exact kind of data navigation and end-user data model that your application requires.


Steve Muench is a consulting product manager for Oracle JDeveloper and an Oracle ACE. In his more than 15 years at Oracle, he has supported and developed Oracle tools and XML technologies and continues to evangelize them. He authored Building Oracle XML Applications (O'Reilly Media, 2000) and shares tips and tricks on OTN and his "Dive into BC4J and ADF" Weblog.


Send us your comments