Package org.jaffa.beans.moulding.data.criteria

This contains all the base classes used for Criteria Data Access Objects.

See:
          Description

Class Summary
CriteriaDAO The base class for all Criteria Data Access Objects.
 

Package org.jaffa.beans.moulding.data.criteria Description

This contains all the base classes used for Criteria Data Access Objects.

How to control what is returned in a domain object graph

The CriteriaDAO object supports a setResultGraphRules(java.lang.String[] resultGraphRules) method to control the scope of the domain graph retrieved. This is important for performance reasons, as many Domain Objects have a large number of related objects, and Domain Object Graph based queries can bring back large sets of related domain objects. Sometimes this is required, but many times we only want a subset of that data. By specifying just a subset of data, the number of internal queries that are performed to build the Graph, and the volume of unneeded data being returned can be dramatically reduced, and hence yield a faster response.

The section below explains how with a given domain object graph, these domain object graph filtering rules can be applied.


We will use the following example

The root of this graph is a 'vendor'.

The 'vendor' has the following fields

The 'vendor' has a foreign Object The 'vendor' has related objects

The foreign object 'businessType' has two fields

The 'site' object has the following fields

The 'site' has a related object

The 'contact' object has the following fields

If we now 'list' the total set of fields in this domain object graph, we get the following set of field references. (Note the dot(.) notation is similar to that now used in the JSP 2.0 expression language)

businessType.businessType
businessType.description
cageCode
comments
comments.text
vendorCode
vendorName
vendorSites
vendorSites.addressLine
vendorSites.city
vendorSites.contacts
vendorSites.contacts.addressLine
vendorSites.contacts.city
vendorSites.contacts.contactName
vendorSites.contacts.country
vendorSites.contacts.sequence
vendorSites.contacts.state
vendorSites.contacts.zip
vendorSites.country
vendorSites.methodOfPayment
vendorSites.rating
vendorSites.siteCode
vendorSites.state
vendorSites.taxRate
vendorSites.zip

1. Basic filters

Filters support *, which matches a single field name, or ** which matches multiple property names

We assume all field names match the regular expression [a-zA-Z_0-9]

1.1 The default

The default filter is *, which matches all fields in the primary object.

setRules = null
or
setRules = "*"

The above rules will give the following resulting map

vendorName
vendorCode
businessType
businessType.businessType
cageCode

Note: that we filter out the vendorSites object as this is an array of object, and no fields have requested from this object. The infers the default behavior is that NO one-to-one/one-to-many objects will be automatically included, unless specifically requested.

Note: we have included businessType this is a foreign object, and in this case we need an instance of the businessType object to hold the business type value. However, no other fields in the businessType object will be filled in, unless specifically requested.

1.2 Include the world

We want to include not just the main fields, but all fields on related and foreign objects

setRules = "**" (where "**" mean match 'anything')
or
setRules = "**.*","*" (where "**.*" means any match all fields on 'anything' and "*" also include the fields on the root object too)

The above rules will give the following resulting map

businessType
businessType.businessType
businessType.description
cageCode
comments
comments.text
vendorCode
vendorName
vendorSites
vendorSites.addressLine
vendorSites.city
vendorSites.contacts
vendorSites.contacts.addressLine
vendorSites.contacts.city
vendorSites.contacts.contactName
vendorSites.contacts.country
vendorSites.contacts.sequence
vendorSites.contacts.state
vendorSites.contacts.zip
vendorSites.country
vendorSites.methodOfPayment
vendorSites.rating
vendorSites.siteCode
vendorSites.state
vendorSites.taxRate
vendorSites.zip

1.3 Includes and Excludes

If a rule beings with a '-' (minus) sign it means exclude all fields that match this rule, if a rule beings with '+' (plus) it means include all fields that match this rule. If neither '+' or '-' is used then '+' is assumed, and the rule is inclusive. In this case the default rule set is really '+*'

The rules are processed in the order the are supplied, and once a rule is processed that either included or excludes a field, no more rules are read. If no rule is found that included or excludes a given field, that field will be excluded. To change the default behavior to include any field that is not referenced put a 'catch-all' rule as the last rule (i.e. use either '**' or something similar)

This is an example of how the order works
setRules = "*","+vendorSites.*","-vendorSites.taxRate","-vendorSites.rating"
Will return

vendorName
vendorCode
vendorSites.siteCode
vendorSites.country
vendorSites.taxRate
vendorSites.addressLine
vendorSites.state
vendorSites.methodOfPayment
vendorSites.zip
vendorSites.rating
vendorSites.city
businessType
cageCode

Not the two fields taxRate and rating are still there, since the "+vendorSites.*" rule was first and explicitly included them. The correct way to do this would have been...

setRules = "-vendorSites.taxRate","-vendorSites.rating","+vendorSites.*","*"

Which would have given

vendorName
vendorCode
vendorSites.siteCode
vendorSites.country
vendorSites.addressLine
vendorSites.state
vendorSites.methodOfPayment
vendorSites.zip
vendorSites.city
businessType
cageCode

1.4. Basic includes

We saw that
setRules = "*"
Gives the following

vendorName
vendorCode
businessType
cageCode

The businessType only has the key field in, but we want the description too We should use the following
setRules = "*","businessType.description"
or
setRules = "*","businessType.*"
Gives the following

vendorName
vendorCode
businessType
businessType.businessType
businessType.description
cageCode
We now want just the list of sites as well
setRules = "*","businessType.*","vendorSites.siteCode"
Gives the following
vendorName
vendorCode
vendorSites
vendorSites.siteCode
businessType
businessType.businessType
businessType.description
cageCode

And now per site, we want the contact name and address
setRules = "*","businessType.*","vendorSites.siteCode","vendorSites.contacts.*"
Gives the following

vendorName
vendorCode
vendorSites
vendorSites.contacts
vendorSites.contacts.contactName
vendorSites.contacts.country
vendorSites.contacts.addressLine
vendorSites.contacts.state
vendorSites.contacts.zip
vendorSites.contacts.sequence
vendorSites.contacts.city
vendorSites.siteCode
businessType
businessType.businessType
businessType.description
cageCode

Now i want just the site and contact addresses
setRules = "vendorCode","vendorName","vendorSites.siteCode","vendorSites.contacts.contactName", "**.addressLine","**.city","**.state","**.zip","**.country"
Gives the following

vendorName
vendorCode
vendorSites
vendorSites.contacts
vendorSites.contacts.contactName
vendorSites.contacts.country
vendorSites.contacts.addressLine
vendorSites.contacts.state
vendorSites.contacts.zip
vendorSites.contacts.city
vendorSites.siteCode
vendorSites.country
vendorSites.addressLine
vendorSites.state
vendorSites.zip
vendorSites.city

2. Rules for related objects

Whether the relationship is one-to-many (Array of Objects), or just one-to-one (Object) the related object is no included in the results unless at least one field in the related object is referenced. In the above example referenced to "vendorSites" or "vendorSites.contacts" are meaningless, and will not include those objects. To be included they should be suffixed with a ".*".

So the following scenarios occur

  1. setRules = "vendorSites"
    Will return
    <nothing>
  2. setRules = "vendorSites.*"
    Will return
    vendorSites
    vendorSites.siteCode
    vendorSites.country
    vendorSites.taxRate
    vendorSites.addressLine
    vendorSites.state
    vendorSites.methodOfPayment
    vendorSites.zip
    vendorSites.rating
    vendorSites.city
    

  3. setRules = "vendorSites.**"
    Will return
    vendorSites
    vendorSites.contacts
    vendorSites.contacts.contactName
    vendorSites.contacts.country
    vendorSites.contacts.addressLine
    vendorSites.contacts.state
    vendorSites.contacts.zip
    vendorSites.contacts.sequence
    vendorSites.contacts.city
    vendorSites.siteCode
    vendorSites.country
    vendorSites.taxRate
    vendorSites.addressLine
    vendorSites.state
    vendorSites.methodOfPayment
    vendorSites.zip
    vendorSites.rating
    vendorSites.city
    

3. Rules for foreign objects

When a foreign object is referenced by a main object there are 3 scenarios to look at

  1. is there a need for the object. This is the case when the foreign keys are null. In this case the foreign object reference is null
  2. is there a need to retrieve a foreign object? if we can avoid loading foreign objects then this will improve performance.
  3. we need to load the foreign object, as the user wants to access fields from that foreign object.

In both scenarios (b) and (c) a foreign object will be return. In the case of (b) only the fields that make up the object key will be populated, as these can be derived from the foreign keys in the main object. In scenario (c) we need to load the foreign object so we can access other data from it

How do we detect when to load and not load the object?

We first need to see if either the object property, or and of its fields are referenced. In the above case we will look at the 'businessType' on the vendor. Any of the following referenced will cause the object to be returned...

businessType
businessType.businessType
businessType.description
but only a reference to description required the record to be read from the database.

The filtering engine will internally do the following

  1. apply the filter rules to any field reference, and included it if valid. if it is valid the following additional rules will be applied

  2. if the foreign object field is referenced, it will leave it in the 'fields to include' list

  3. if one of the primary keys of the object is referenced it will
    1. add in a reference to the object, like in (b), if there is not one already
    2. it will remove the primary key reference, as the primary fields will ALWAYS be returned regardless of any rules that may try and exclude them

  4. any field reference on the foreign object that is not a primary key field will be left in the list

So the following scenarios occur

  1. setRules = "*"
    Will return
    ...
    businessType
    businessType.businessType
    

  2. setRules = "businessType"
    Will return
    businessType
    businessType.businessType
    

  3. setRules = "businessType.businessType"
    Will return
    businessType
    businessType.businessType
    

  4. setRules = "businessType.description"
    Will return
    businessType
    businessType.businessType
    businessType.description
    

  5. setRules = "businessType.*"
    Will return
    businessType
    businessType.businessType
    businessType.description
    

  6. setRules = "-businessType.businessType","businessType"
    Will return
    businessType
    businessType.businessType
    

  7. setRules = "-businessType.description","businessType.*"
    Will return
    businessType
    businessType.businessType
    

  8. setRules = "-businessType.businessType","businessType.*"
    Will return
    businessType
    businessType.businessType
    businessType.description
    



    Copyright © 2002-2004 JAFFA Project.