Updated: 5/24/2006; 10:57:47 AM.
Sung Im's Radio Weblog
        

Saturday, May 20, 2006

BC4J 10.1.3 supports a new feature called "query mode."  Using this, the user can decide how the VO draws its data.
 
The following constants are defined in oracle.jbo.ViewObject:

QUERY_MODE_SCAN_VIEW_ROWS: To refine further View rows currently in the QC (using the RowQualifier--for tier transparency, oracle.jbo.RowMatch is created and RowQualifier subclasses this).  For example, your RS may have Emps whose SAL is > 3000.  From this, you can further qualify (i.e., remove from the QC unqualifying rows) rows that have Commission > 10.

QUERY_MODE_SCAN_ENTITY_ROWS: To draw rows from Entity Cache.  This is good for performing in-memory filtering of rows that are already in Entity Cache.  In addition, this enables the user to produce View rows on Entity rows that were created and not yet posted.  Again, you use RowMatch to qualify rows.

QUERY_MODE_SCAN_DATABASE_TABLES: To draw rows frmo query result as before.


The default is QUERY_MODE_SCAN_DATABASE_TABLES.  You can OR these flags together.  If OR them, BC4J handles skipping of duplicate rows.

Here are relevant JavaDocs:

     /**
      * These <code>QUERY_MODE_SCAN_...</code> constants are used to specify
      * the query mode for the View Object.  Query mode controls how qualifying
      * formulated for each Row Set in the View Object.  These constants can be
      * OR'ed together.  If more than one query mode is specified in this
      * manner, rows for the collection will be produced from more than
      * one source.
      * <p>
      *
      * If you call {@link #setQueryMode(int)} or {@link #addQueryMode(int)} to
      * change the query mode, the new query mode does not go into effect
      * until you call {@link RowSet#executeQuery()} on the Row Set.
      * <p>
      *
      * Rows can come from three different sources.  If the Row Set currently
      * has a collection of rows (View rows), <code>QUERY_MODE_SCAN_VIEW_ROWS</code>
      * will indicate that the row match (see {@link #setRowMatch(RowMatch)}) should
      * be applied to further filter View rows.  Unqualifying rows are removed
      * from the collection.
      * <p>
      *
      * If the query mode includes <code>QUERY_MODE_SCAN_ENTITY_ROWS</code>,
      * the Entity cache is scanned to see if qualifying rows can be produced.
      * If so, these rows are added to the collection.
      * <p>
      *
      * If the query mode includes <code>QUERY_MODE_SCAN_DATABASE_TABLES</code>,
      * a database query is issued to produce rows from the query result.
      * The default query mode is <code>QUERY_MODE_SCAN_DATABASE_TABLES</code>.
      * <p>
      *
      * If the query mode specifies multiple sources, then care if taken
      * to prevent duplicate rows from appearing.
      */
     static final int QUERY_MODE_SCAN_VIEW_ROWS = 0x0001;

     /**
      * Specifies that rows should be produced from Entity cache.
      * See above for details.
      */
     static final int QUERY_MODE_SCAN_ENTITY_ROWS = 0x0002;

     /**
      * Specifies that rows should be produced from database query result.
      * See above for details.
      */
     static final int QUERY_MODE_SCAN_DATABASE_TABLES = 0x0004;

     /**
      * Sets an in-memory filter (<code>RowMatch</code>) for the View Object.
      * While the WHERE clause is used when a database query is issued,
      * the row match is used for qualifying rows in memory.
      * Calling this method does not cause filtering of rows by the
      * row match.  To filter, {@link RowSet#executeQuery()}
      * must be called.
      *
      * @param rowMatch the new row match.
      */
     void setRowMatch(RowMatch rowMatch);

     /**
      * Gets the in-memory filter (<code>RowMatch</code>) for the View Object.
      * While the WHERE clause is used when a database query is issued,
      * the row match is used for qualifying rows in memory.
      *
      * @return the current row match.
      */
     RowMatch getRowMatch();

     /**
      * Sets query mode for the View Object.
      * Query mode controls how qualifying rows are formulated for each
      * Row Set in the View Object.
      * <p>
      *
      * The <code>queryMode</code> parameter may be an OR'ed flag of
      * <code>QUERY_MODE_SCAN_...</code> constants.  See these constants
      * for further details.
      * <p>
      *
      * Calling this method does not cause automatically cause the new
      * query mode to go into effect.  Call
      * {@link RowSet#executeQuery()} to apply the new query
      * mode.
      * <p>
      *
      * The default query mode is <code>QUERY_MODE_SCAN_DATABASE_TABLES</code>.
      *
      * @param queryMode the new query mode.
      */
     void setQueryMode(int queryMode);

     /**
      * Adds query mode for the View Object.
      * Query mode controls how qualifying rows are formulated for each
      * Row Set in the View Object.
      * <p>
      *
      * The <code>queryMode</code> parameter may be an OR'ed flag of
      * <code>QUERY_MODE_SCAN_...</code> constants.  This method
      * OR'es in the incoming <code>queryMode</code> to the View Object's
      * current query mode.  See these constants for further details.
      * <p>
      *
      * Calling this method does not cause automatically cause the new
      * query mode to go into effect.  Call
      * {@link RowSet#executeQuery()} to apply the new query
      * mode.
      *
      * @param queryMode the new query mode to be added (OR'ed).
      */
     void addQueryMode(int queryMode);

     /**
      * Gets the current query mode of this View Object.
      * Query mode controls how qualifying rows are formulated for each
      * Row Set in the View Object.
      * <p>
      *
      * The returning value may be an OR'ed flag of
      * <code>QUERY_MODE_SCAN_...</code> constants.  See these constants
      * for further details.
      * <p>
      *
      * The default query mode is <code>QUERY_MODE_SCAN_DATABASE_TABLES</code>.
      *
      * @return query mode.
      */
     int getQueryMode();

1:24:10 PM    comment []

BC4J 10.1.3 supports 'named where-clause params' and 'variables' on various BC4J objects.  The memo below explains tech details:


This memo will describe the named where-clause parameter feature.

Underlying the named where-clause parameter is a general feature of Variable support (aka, name space).  Each app component object (specifically, AM, VO, RS and eventually binding container) is a variable manager (name space).

Each def object (AM def, VO def, EO def) is a variable manager.

A variable manager may be nested in the sense of scope nesting. (Interface name is oracle.jbo.VariableManager).  Name lookup goes from the current var mgr and searches outward.  Hence, a variable mgr has the concept of parent var mgr.

For a RowSet, the parent var mgr is the VO's var mgr.

For a VO, its parents are the AM instance's var mgr and view def's var mgr.

For an AM, its parents are the parent AM's (in terms of AM nesting) var mgr and the AM def's var mgr.

For a VO def its parents are the entity defs of the base EOs.

~~~~~

A var mgr contains variables (interface Variable).

A variable is typed, has a name, and has a default value.  I also copied AttributeHint support into it so that people can to attr-hinting with these vars (just like Shailesh's JUCtrlParameterDef).

A var mgr is further extended into VariableValueManager, which knows how to store and manage current values (above and beyond the default value).

Strictly speaking, an app component object will have a VariableValueManager.  AM def, VO def, EO def has VariableManager.

A variable can be a named where-clause parameter or a method parameter (or other things to be included as requirements arise).  A "variable kind" indicates what kind of variable it is.

A where-clause parameter will have an additional list of integer ids. These ids will be used to bind the variable values into where-clause when the query is executed (will translate into setWhereClauseParam(int, Object) calls).

~~~~~

For named where-clause parameter implementation, I added the following APIs to oracle.jbo.RowSet.

   void defineNamedWhereClauseParam(String name, Object defaultValue, int[] indices);
   void removeNamedWhereClauseParam(String name);
   void setNamedWhereClauseParam(String name, Object value);
   void skipNamedWhereClauseParam(String name);


Also, use the following link for further info

http://www.oracle.com/technology/oramag/oracle/06-mar/o26frame.html?msgid=4658272


11:54:34 AM    comment []

To allow customization of data consistency check (between the data in the EO cache and the database), the following overriddable methods are provide:

oracle.jbo.server.EntityImpl:

   protected boolean checkConsistency (SparseArray target, boolean lock)

The default implementation of this method calls EntityImpl.compare() which is also overriddable:

   protected boolean compare(SparseArray target)

The default implementation of compare() will check to see if this entity has a change indicator attr.  If so, it uses that.  If not, is compares all attr values (non-LOB attrs).

 


11:41:57 AM    comment []

Background:  RowInconsistentException is an exception thrown under the following scenario.  The user reads a row in with value aaa for an attribute.  He performs some operation that is about to lock the row.  A check is made to see if someone else has modified the row since this user read it.  If so, this exception is thrown.

Question:  When RowInconsistentException is thrown, why does BC4J compare values of attributes that are not modified by this user?  Isn't that a bit excessive?  In other words, shouldn't BC4J only compare 'modified' attribute's original value with the db value to raise RowInconsistentException?

Answer: RowInconsistentException is usually thrown when the row is about to be locked.  Under pessimistic, RIE will be thrown during lock request ==> No attr has been modified.

Even under optimistic, since data updates were performed based on the old data, if some data were changed by another transaction, we want the user notified that their updates may have been performed based on stale data.

For example, suppose in a banking app (under opt), the user sees remaining balance of $300 in his app.  The user makes a request to withdraw $250 from it.  Before this change is posted, another user comes into the same row and withdraws $200 from it.  If we compare only the modified attr, the req to w/d $250 will go through.

This is why we want to compare all attrs regardless of whether they were modified or not.


11:37:12 AM    comment []

After long silence on this Weblog, I decided to post some useful articles and Q&A's.  Of course, when it comes to BC4J resources, you must first look at Steve's (Muench) site:

http://radio.weblogs.com/0118231/

Stay tuned for more article.s

 


11:33:00 AM    comment []

© Copyright 2006 Sung Im.
 
May 2006
Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Apr   Jun


Click here to visit the Radio UserLand website.

Subscribe to "Sung Im's Radio Weblog" in Radio UserLand.

Click to see the XML version of this web page.

Click here to send an email to the editor of this weblog.