Difference Between View Object Select and Entity doSelect() Method
A user wrote in today to ask:
I've just discovered EntityImpl's doSelect() method! This is completely new to me. I thought the view object performs the fetching of data and stores it into the EO cache. It opens up new possibilities, but the cooperation between the VO and EO suddenly got confusing. Can you help clarify?
View objects do select the data in general, providing just the "slices" of data that are appropriate to the task at hand. Nothing in your understanding is wrong here.
However, one method that every entity object supports is: findByPrimaryKey()
This method lives on the factory for your entity, the related EntityDefImpl object.
It's job is to find an entity in the entity cache, or in the database if the entity is not in the cache already. When it goes to the database it selects all columns corresponding to all persistent attributes and does the lookup based on the column(s) that correspond to the entity's primary key attribute(s).
Anyone who invokes EntityDefImpl.findByPrimaryKey() will end up in the entity's doSelect() method.
There are several reasons why doSelect() might get called:
Your code calls findByPrimaryKey() on some EntityDefImpl class for some entity object.
ADF BC framework calls it when you do ViewObject.findByKey() on a VO that is based on entity objects. It turns around and finds the entity in the cache (or database if not in the cache) as part of doing the VO-level findByKey().
ADF BC framework needs to lock the entity object for the first time. It will lock the entity by using doSelect() passing "true" for the lock parameter. Here again, you're basically doing a lookup by the primary key. In this case, the select statement will contain the appropriate LOCK syntax for the current database (as formulated by the SQLBuilder implementation that's been picked for you by the framework at runtime based on the configuration settings of your application module). In the case of Oracle, it will use a FOR UPDATE NOWAIT clause. This brings back the current values of the persistent attributes at lock time so they can be used in lost-update detection that the ADF Entity Object performs for you. If you aren't able to lock the row, you'll get an oracle.jbo.AlreadyLockedException. If you are able to acquire the lock but the row has been changed and committed by another user since you first read it in, you'll get the RowInconsistentException instead. If you override doSelect() and completely replace what it does by default, you are responsible for continuing to provide this RowInconsistentException detection if you care to still have this behavior.
ADF BC framework needs to "fault-in" an entity object which is getting modified for the first time since having some of its attributes queried-up for browsing in a view object. The view object only retrieves the columns that are needed for the UI, so in the entity cache the entity instance is in a "partially populated" state as far as its attributes are concerned. As soon as that entity begins to have any of its persistent attributes changed for the first time, if the entity instance is in this "partially populated" state, the entity will invoke doSelect() on itself to "fault-in" all of the persistent attributes using the primary key.
Hopefully this helps clarify the differences.
This topic is discussed in the JDeveloper documentation under Help | Search... from inside the tool. Look for the "About Oracle ADF Business Components Cache Management" topic. Also, my whitepapers on Ten Key Benefits of Oracle ADF Business Components for Application Developers and Simplify J2EE and EJB Development with BC4J talk some more about the entity object and view object collaboration.