Oracle® Application Development Framework Developer's Guide For Forms/4GL Developers
10g Release 3 (10.1.3.0) B25947-01 |
|
![]() Previous |
![]() Next |
It is extremely common in business applications to supplement information from a primary business domain object with secondary reference information to help the end user understand what foreign key attributes represent. Take the example of the ServiceRequest
entity object. It contains foreign key attributes of type Number
like:
CreatedBy
, representing the user who created the request
AssignedTo
, representing the user to whom the request is assigned
ProdId
, representing the product to which the request pertains
From experience, you know that showing an end user exclusively these "raw" numerical values won't be very helpful. Ideally, reference information from the related User
and Product
entity objects should be displayed to improve the application's usability. One typical solution involves performing a join query that retrieves the combination of the primary and reference information. Alternatively, developers populate "dummy" fields in each queried row with reference information based on extra queries against the lookup tables. When the end user can change the foreign key values as she edits the data, this presents an additional challenge.
For example, when reassigning a service request from one technician to another, the end user expects the reference information to stay in sync. Luckily, entity-based view objects support easily including reference information that's always up to date. The key requirement to leverage this feature is the presence of associations between the entity object that act as the view object's primary entity usage and the entity objects that contribute reference information.
This section describes how to modify the default ServiceRequests
view object created above to include reference information from the User
and Product
entity objects.
To include reference entities in a view object, open the View Object Editor on an entity-based view object that already has a single entity usage, and open the Entity Objects page. The first entity usage in the Selected list on this page is known as the primary entity usage for the view object. The list is not limited to a single entity usage, however. To use additional entity objects in the view object, select them in the Available list and shuttle them to the Selected list.
Figure 7-8 shows the result of adding three additional reference entity usages to the existing ServiceRequests
view object: one for the Product
and two separate usages of the User
entity. When you click on an entity usage in the Selected list, the state of the Reference checkbox indicates that the second and subsequent entity usages added to a view object are marked as reference information by default. Similarly, the secondary entity usages default to being not updatable, as the unchecked state of their Updatable checkbox confirms.
Note: When adding secondary entity usages, they default to having their Updatable flag false and their Reference flag true. This is by far the most common usage pattern. In Section 27.9, "Creating a View Object with Multiple Updatable Entities", you'll explore the less common, yet still useful, situation of having a join view object with multiple, updatable entity usages. |
The Association dropdown list shows you the name of the association that relates the selected entity usage to the primary one. The Alias field allows you to give a more meaningful name to the entity usage when the default name is not clear. For example, after shuttling two entity usages for the User
entity object into the Selected list, initially the alias for the usages was User1
and User2
. You can see in the figure that renaming these to be Technician
and Customer
instead greatly clarifies what reference information they are contributing to the view object. Importantly, the figure also illustrates that when you add multiple entity usages for the same entity, you need to use the Association dropdown list to select which association represents that usage's relationship to the primary entity usage. For the Technician
entity usage select the ServiceRequestsAssignedToUser
association, and for the Customer
entity usage select the ServiceRequestsCreatedByUser
association.
After adding these secondary entity usages, switch to the Attributes page of the View Object Editor and select the specific, additional attributes from these new usages that you want to include in the view object. Figure 7-9 illustrates the result of shuttling the following extra attributes into the Selected list:
The Name
attribute from the Product
entity usage
The Email
attribute from the Technician
entity usage
The Email
attribute from the Customer
entity usage
Notice that even if you didn't intend to include them, JDeveloper automatically verifies that the primary key attribute from each entity usage is part of the Selected list. If it's not already present in the list, JDeveloper adds it for you.
Selecting the SQL Statement page, you can see that JDeveloper has included the new columns in the SELECT statement and has updated the Where field to include the appropriate join clauses of:
((ServiceRequest.PROD_ID = Product.PROD_ID) AND (ServiceRequest.ASSIGNED_TO = Technician.USER_ID)) AND (ServiceRequest.CREATED_BY = Customer.USER_ID)
Expanding the Attributes node in the tree at the left of the View Object Editor, you can see the additional attributes are added at the end of the list. Since the default attribute names are not as clear as they could be, by selecting each one in turn, you can rename them as follows:
Name
-> ProductName
ProdId1
-> PKProdId
(Primary Key from Product
entity usage)
Email
-> TechnicianEmail
UserId
-> PKTechnicianUserId
(Primary Key from Technician
entity usage)
Email1
-> CustomerEmail
UserId1
-> PKCustomerUserId
(Primary Key from Customer
entity usage)
The view object attribute corresponding to the primary key attribute of the primary entity usage acts at the primary key for identifying the view row. When you add secondary entity usages, JDeveloper also marks the view object attributes corresponding to their primary key attributes as part of the view row key as well. When your view object consists of a single updatable primary entity usage and a number of reference entity usages, the primary key attribute from the primary entity usage already is enough to uniquely identify the view row. These additional key attributes are unneeded and you should toggle their Key Attribute setting to false
. For the view object created above, toggle this setting to false
for the following attributes so that Key Attribute is no longer checked: PKProdId
, PKTechnicianUserId
, and PKCustomerUserId
.
Since you generally won't want to display the primary key attributes that were automatically added to the view object, you can set their Display Hint property on the UI Control Hints page to Hide as shown in Figure 7-10.
Figure 7-10 Setting an Attribute Control Hint to Hide Primary Key Attributes from Reference Entity Usages
Click OK to save your changes to the view object.
When you include secondary entity usages by reference in a view object, JDeveloper updates the view object's XML component definition to include information about the additional entity usages. For example, if you look at the ServiceRequests.xml
file for the view object that was enhanced above to include three additional reference entity usages, you will see this information recorded in the multiple <EntityUsage>
elements in that file. For example, you'll see an entry for the primary entity usage like this:
<EntityUsage Name="ServiceRequest" Entity="devguide.model.entities.ServiceRequest"/>
The secondary reference entity usages will have a slightly different entry like this, including information about the association that relates it to the primary entity usage:
<EntityUsage Name="Product" Entity="devguide.model.entities.Product" Association= "devguide.model.entities.associations.ServiceRequestsForProduct" AssociationEnd= "devguide.model.entities.associations.ServiceRequestsForProduct.Product" SourceUsage="devguide.model.queries.ServiceRequests.ServiceRequest" ReadOnly="true" Reference="true"/>
Each attribute entry in the XML indicates which entity usage it references. This entry for the ProblemDescription
attribute shows that it's related to the ServiceRequest
entity usage:
<ViewAttribute Name="ProblemDescription" IsNotNull="true" EntityAttrName="ProblemDescription" EntityUsage="ServiceRequest" AliasName="PROBLEM_DESCRIPTION" > </ViewAttribute>
While the CustomerEmail
attribute is related to the Customer
entity usage.
<ViewAttribute Name="CustomerEmail" IsUpdatable="false" IsNotNull="true" EntityAttrName="Email" EntityUsage="Customer" AliasName="EMAIL1" > </ViewAttribute>
The View Object Editor uses this association information at design time to automatically build the view object's join WHERE clause. It uses the information at runtime to enable keeping the reference information up to date when the end user changes foreign key attribute values.
{para}?>If your view objects reference multiple entity objects, these are displayed as separate entity usages on a business components diagram. Note that you can also modify the default inner join clause to be an outer join when appropriate.
Section 6.4, "Creating an Entity Diagram for Your Business Layer" explained how to create a Business Components Diagram to visualize your business domain layer. In addition to supporting entity objects, JDeveloper's UML diagramming support allows you to drop view objects onto diagram as well to visualize their structure and entity usages. If you create a new Business Components Diagram named SRService Data Model
in the devguide.model.design
package, and drag the ServiceRequests
view object from the Application Navigator onto the diagram, you'll see what's shown in Figure 7-11. When viewed as an expanded node, the diagram shows a compartment containing the view objects entity usages.
When JDeveloper creates the WHERE clause for the join between the table for the primary entity usage and the tables for secondary entity usages that are related to it, by default it always creates inner joins. Study the WHERE clause of the ServiceRequests
view object more closely:
((ServiceRequest.PROD_ID = Product.PROD_ID) AND (ServiceRequest.ASSIGNED_TO = Technician.USER_ID)) AND (ServiceRequest.CREATED_BY = Customer.USER_ID)
When service requests are not yet assigned to a technician, their AssignedTo
attribute will be null
. The default inner join condition generated above will not retrieve these unassigned service requests. Assuming that you want unassigned service requests to be viewable and updatable through the ServiceRequests
view object, you'll need to revisit the SQL Statement page of the View Object Editor to change the query into an outer join to the USER table for the possibly null ASSIGNED_TO column value. The updated WHERE clause shown below includes the additional (+)
operator on the side of the equals sign for the related table whose data is allowed to be missing in the join:
((ServiceRequest.PROD_ID = Product.PROD_ID) AND (ServiceRequest.ASSIGNED_TO = Technician.USER_ID (+) )) AND (ServiceRequest.CREATED_BY = Customer.USER_ID)