The JavaDoc for the findByKey method covers its use with some examples, but in recent interactions with customers using BC4J I've found there was still some confusion on what kind of support exists for finding a row by a "partial key". So I'll try to clarify.
Recall that a view object can be based on zero or more entity object usages.
When a view object is based on at least one entity usage, the findByKey() method finds rows by turning around and doing a findByPrimaryKey() on the entity cache the first non-null entity key. If the primary key of that entity is comprised of multiple attributes, all of those attribute must have a non-null value for the findByPrimaryKey() to find the row.
If a view object is based on a single entity object, the key for each view object row will be comprised of the underlying entity object's key attribute(s). The "Key Attribute" property for the view object attributes corresponding to these underlying entity object primary key attributes will be set to "true" and the checkbox will be disabled because you cannot unselect them.
The corollary of the above two paragraphs is that when you perform a findByKey() on a view object with a single entity object usage, you must provide an oracle.jbo.Key object which has non-null values for all of the attributes in the view row key.
If a view object is based on N entity usages, where N > 1, then the view row key is by default comprised of all of the primary key attributes from all of the participating entity usages. Only the ones from the first entity object are required to participate in the view row key, but by default all of them do.
If you allow the key attributes from some second or subsequent entity usage to remain "Key Attributes" at the view row level, then you should leave all of the attributes that form the primary key for that entity object as part of the view row key. Assuming you have left the one or more key attributes in the view row for M of the N entity usages, where (M <= N) then you can use findByKey() to find rows based on any subset of these M entity "bases", but for each entity base for which you provide values in the Key object, you must provide non-null values for all of the attributes in that entity's primary key.
As a concrete example, imagine that you have a view object Employees with an Emp entity as its primary entity usage, and a Dept entity as secondary (by reference) entity usage. Furthermore, assume that you leave the Empno attribute (primary key for the Emp entity) and the DeptDeptno view row attribute (mapped to the Dept entitiy's Deptno attribute which is its primary key) as "Key Attributes" in the Employees view object.
The view row key will therefore be the (Empno, DeptDeptno) combination.
When you do a findByKey(), you can provide a Key object that provides:
- A completely specified key for the underlying Emp entity -- which in this case means providing a value for the Empno attribute in the Key object passed to findByKey()
- A completely specified key for the underlying Dept entity -- in this case, this means a value for the DeptDeptno attribute in the Key object passed to findByKey()
- A completely specified key for both underlying Emp and Dept entities.
Assuming that we've imported oracle.jbo.domain.Number into our class, we would create an example of each key combination above like this:
- Key k = new Key(new Object[]{new Number(7839), null});
/* Val for Emp EO part of view row key */
This would find the row with employee id 7839, regardless of department she works in.
- Key k = new Key(new Object[]{null, new Number(10)});
/* Value for Dept EO part of view row key */
This would find the row(s) with employees in deparment number 10.
- Key k = new Key(new Object[]{new Number(7839), new Number(10)});
/* Value for both */
This would find the row with employee 7839 in department 10 only.
If a view object is based on zero entity usages, then it's view row key is determined by the ordered set of view attributes that have the "Key Attribute" property checked on/true. Alternatively, this set of one or more key attributes can be provided programmatically through the call to setKeyAttributeDefs() in your ViewObjectImpl subclass.
A findByKey() performed on a view object with no entity usage, must be done using the complete key for the view row, so no partial searching is possible. Also, in order to enable the findByKey() to work at all for such a view object, the method setManageRowsByKey(true) must be called from the create() method of your view object implementation class.
4:32:42 PM
|