Thursday, June 2, 2011

ADF Entity associations with constants

This post discusses two approaches for creating entity object associations when you need to use constants in your relationship query; this can commonly come up when you have a child entity that can have different types of parents. 

Let's start by laying out a simple example where we have a company selling products and services such that we either have an ORDER or a durational CONTRACT.  For some reason we've chosen to model these  entities separately, however in each case we are selling PRODUCTs and we'd like to share a common entity for the product lines.  So an ORDER has PRODUCTs and a CONTRACT has PRODUCTs.  To model this we'll give our PRODUCT entity two attributes:
  • ParentEntityId - the primary key of our parent
  • ParentEntityType - the type of our parent, either 'Order' or 'Contract'
For these I would have created the following EOs in my ADF model project:
  • OrderEO
  • ContractEO
  • ProductEO
And I would like the following associations:
  • OrderEOToProductEO
  • ContractEOToProductEO
How should I build these associations? 

Option 1: Build an EO Association based on ID and modify the generated association query

When you create the association you will choose the relationship between the OrderEO.OrderId and ProductEO.ParentEntityId.  You will then need to manually modify the query expression to add a condition for ParentEntityType.  

The query from source to destination would be: 
(:Bind_OrderId = ProductEO.PARENT_ENTITY_ID) AND ('Order' = ProductEO.PARENT_ENTITY_TYPE)

And from destination to source:
(:Bind_ParentEntityId = OrderEO.ORDER_ID) AND (:Bind_ParentEntityType = 'Order')

The advantage of this approach is that only the EO association is hampered with the details of how these entities are related.  The disadvantage is that you've manually changed the query and if you alter the relationship of these entities in the future (or someone else does), the query may need manual intervention to include this clause for the parent entity code.  

Option 2:  Use a transient attribute on the parent entities

Create a transient attribute in Order and Contract called "ParentEntityType" and set it to be "Derived from SQL Expression".  For OrderEO the attribute will have a value of "Order", and for ContractEO "Contract".  For example (from OrderEO.xml):

  Attribute
    Name="ParentEntityType"
    IsQueriable="false"
    IsPersistent="false"
    ColumnName="none"
    SQLType="VARCHAR"
    Type="java.lang.String"
    ColumnType="VARCHAR2"
    DefaultValue="Order"
    Precision="255"
    Expression="'Order'"

Then when you create your EO assocation you can select both attributes for the relationship.  You select OrderEO.OrderId = ProductEO.ParentEntityId and OrderEO.ParentEntityType = ProductEO.ParentEntityType.  

The query from source to destination would be: 
(:Bind_OrderId = ProductEO.PARENT_ENTITY_ID) AND (:Bind_ParentEntityType = ProductEO.PARENT_ENTITY_TYPE)

And from destination to source:
(:Bind_ParentEntityId = OrderEO.ORDER_ID) AND (:Bind_ParentEntityType = 'Order')

The advantage of this approach is that the query is generated automatically by the framework and any changes you make in the future to the association will auto-generate without manual intervention.  You've also included the constant as an attribute of the EO which could be used across multiple associations/etc. The disadvantage is that you've added an attribute to your EOs to store a constant that is probably only used in this relationship.  And if you don't want these constants in your VOs then you have to manually remove them so they only show up in the EO.

Conclusion

Either way works and I've done both, but I recommend Option 1 as this isolates the association specific logic in the EOAssociation and does not taint your EO/VO with attributes that are just for constants.  Also note that if you can model your relationship with VOs and View Links then this becomes easier because the view link will use a view criteria.



1 comment:

  1. That's a really good comprehensive description of the two approaches. Very useful.

    ReplyDelete