How Does View Link/Entity Association Consistency Exactly Work?
I get asked the above question a lot. So, I'm going to try to give as much detailed info as possible. Steve's following blog page has a lot of functional description of view link consistency
http://radio.weblogs.com/0118231/2003/12/02.html
Please take a look.
I will focus my discussions on technical details.
What Are View Link/Entity Association Consistency for?
Let me first discuss view link consistency and leave entity association consistency for later.
This flag controls whether unposted rows show up in the query collections of this VO of not.
For example, suppose we have 2 VOs: VO1 and VO2 both based on the same entity. If you create a new row through VO1, a question comes up as to whether VO2 will see this new row.
If the view link consistency flag is on for VO2, it can see the new row (more discussion on this below). If the view link consistency flag is off for VO2, VO2 will not see any unposted new row.
How View Link Consistency Works
Suppose the user creates a new row through VO1. The act of creating a new view row means that a new entity row is created for the corresponding entity. This row is by default blank (if the user overrode create() to initialize some attr, it won¡¯t be blank). And, a blank row is not yet added to the entity cache.
Only when some (I say 'some' because the EO's PK may be multi-part) of the PK attributes are set (most likely through the viewRow.setAttribute(..)), will the entity row be added to the entity cache. And, in response to the set attribute call, the
oracle.jbo.server.EntityCache's following method is invoked:
protected void deliverEntityEvent(EntityEvent event)
This will then turn around looking for ViewObject's that are listening in on the EO events. Going back to our VO1 and VO2 example, as they are based on this EO, both of them will be listeners to the entity cache, regardless of its view link consistent flag value. For each entity listener, the following method is invoked (that of the oracle.jbo.server.EntityListener interface, which ViewObjectImpl implements):
public void sourceChanged(EntityEvent event);
So, VO1's sourceChanged() is invoked first, followed by VO2. Let's assume now that VO1's view link consistency is false, but VO2's consistency is true. Then, VO1's sourceChanged() will not do anything with this new row. VO2, on the other hand, will walk through all its query collections (oracle.jbo.server.QueryCollection) and process the new row for each one of these QCs.
Each QC in a VO has a data structure called the row filter. Let me back up a bit and explain this. A VO may have a where-clause with a bind parameter, e.g.,
DEPTNO = :myDeptno
for EmpView (myDeptno is the bind variable). Typically, setWhereClauseParam() or setNamedWhereClauseParam() is invoked to specify the bind variable value. Or, if the where-clause was one generated from a view link, the where-clause parameters are automatically supplied by BC4J.
Suppose the user or (in the case of master-detail) the system, creates a row set from this VO for myDeptno = 10. This creates a row set and the underlying QC, where the QC's row filter is {10} (an Object[] with 10 as its only element). If you or the system creates another row set for myDeptno = 20, or if you navigate the master VO to the row whose Deptno is 20, this creates another QC whose row filter is {20}. So, the VO now has 2 QCs with row filters {10} and {20}, respectively.
Going back to the view link consistency discussion, while processing the new row for the QC, the VO checks to see if the new row's row filter value matches that of the QC's. If so, then we proceed further.
Now, a check is made to see if the QC in its collection already has a view row, which is based on this entity row (a data structure named ViewRowCache makes this look-up fast). If the QC already has one, we just return and not bother with the new entity row. If the QC does not have any view row, which is based on the new entity row, a new view row is created on the QC and the new view rows points to this new entity row.
The VO's RowQualifier/RowMatch is now applied to the new view row to see if the row qualifies to be in this QC. If true, the row is finally inserted into the QC and the QC is now able to see the new entity row.
Why Are They Called Link/Assoc Consistency?
An observant BC4J user asked me why we call this flag view link/entity association when it seems deal with the question of unposted rows.
Part of the reason is historical. This feature was originally requested for entity associations where the user wanted to see news rows through the association accessor before they are posted to database.
Another reason is that this feature simply works more logically for master-detail situation. More specifically, it works better for the detail VO. Let's go back to the above discussion on row filter. I mentioned earlier that "The VO checks to see if the new row's row filter value matches that of the QC's". For master-detail, we're able to build the row filter value from the new row because the view link/entity association definition let's us know which attribute is involved in the QC's row filter.
For example, if the view link links Dept's Deptno to Emp's Deptno, when we deal with a new Emp row, we take the Emp's Deptno value to build the row filter value to compare to that of the QC.
But, if no view link is involved, BC4J doesn't have that information; in the above example, suppose the where-clause was specified through setWhereClause() and not by a view link. When sourceChanged() is invoked, BC4J does not know that the where-clause parameter has any relationship to any of the attributes of Emp. So, when view link consistency is being applied to a non-detail VO, we do not perform the row filter check (because the bottom line is that we don't know how to build the row filter from the row). The row qualifier (oracle.jbo.server.RowQualifier) or the row match (oracle.jbo.RowMatch) check is still performed.
What about Entity Association Consistency?
Keep in mind the following important facts re: entity assocation. When you call an entity association accessor, an oracle.jbo.server.EntityRowSetImpl is returned (assuming that the accessor is for the many side of the association). EntityRowSetImpl is a facade in front of ViewRowSetImpl and its main job is to peel off the entity row from the view row. Behind this EntityRowSetImpl is a ViewObjectImpl which is created through the following ApplicationModule API:
public ViewObject createViewObjectFromQueryClauses(String voName,
String eoName,
String selectClause,
String fromClause,
String whereClause,
String orderByClause);
Hence, all of the above discussions apply to entity association in that EntityRowSetImpl is really a ViewRowSetImpl with the added functionality of peeling the view row off.
Why Are the APIs Called set/isAssociationConsistent Even for View Links?
Someone asked me why the APIs are named AssocationConsistent even for view links. As I mentioned early, these APIs first went in for entity associations. So, we originally named them set/isAssociationConsistent. Later, users asked the same functionality to be supported for view links. These APIs were elevated to oracle.jbo.RowSet and the names stuck.
What Are the Rules for Computing This Flag?
Steve's page (link included at the beginning) has detailed description of various ways through which this flag can be specified. Take a look.
Why Do These New View Rows Sometimes Appear at Different Locations?
The above description re: how new view rows appear in a QC is only half the story. It explains how new view rows appear in an existing QC. The other half is what happens if a QC is being formed new (how the new QC picks up unposted new rows). But, before I discussed that, let me say that for an existing QC, the new view rows will appear at the end of the current collection. So, suppose the database table contains 100 rows that would go into this QC. The QC has fetched 20 rows. If the user causes a new row to be inserted through view link consistency, the new row will appear in the 21-st slot. If the user then continues to fetch, the 21-st row from the table will go into the 22-nd slot and so on.
Back to the new QC case (which is the same case as if executeQuery() is invoked on the view object or the row set)... As the QC is created and executeQuery'ed, it will check the view link consistency flag. If the flag is true, the appropriate entity cache will be examined to see if it has unposted new rows. Depending on whether the QC is for a detail VO or not, the row filter check is made to pre-filter the new entity rows. New view rows are created from these and put into a "temporary holding station."
As the user retrieves rows from this QC, new rows are moved from this temporary holding station to the real collection and returned to the caller. So, these new rows will appear at the beginning of the collection.
Do View Link Consistency Make Sense for EO-less VOs?
No. View link consistency is not really supported for VOs that are not EO based.
10:57:42 AM
|