Skip to main content

Preparing ViewObject's query for execution

If you need to assign bind variable values or modify where clause conditionally just before the the query execution, then release has a new method added ViewObjectImpl::prepareRowSetForQuery(ViewRowSetImpl vrs). This method engages well with ViewObjectImpl::getQueryHitCount()and ViewObjectImpl::getEstimatedRowCount() as well. I mean the prepareRowSetForQuery(...) will get invoked before calling the the above methods by the runtime. This is useful if you need to set bind variable values before the query execution for List Of Values or ViewAccssors used for displaying Tree components.

You can use this method safely(zero side effect) to add your logic for tweaking default query by setting bind variable values or additional where clause at run time.

public class DepartmentsViewObjectImpl extends ViewObjectImpl{
public void prepareRowSetForQuery(ViewRowSetImpl vrs) {
vrs.ensureVariableManager().setVariableValue("bindVarDeptId", deptIdRuntimeValue);

Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post-


Why use this one and not executeQueryForCollection?
Jobinesh said…
Well..good question. A couple of points for not using executeQueryForCollection...
1. The executeQueryForCollection(...) will never get invoked before getEstimatedRowCount() which is used for identifying the total result size. This may have serious side effects if you are modifying the query from executeQueryForCollection, as two different queries are getting executed - one for VO and the other on for rowCount. Table/Tree table will check for row count first and then displays records

2. If you need to modify the bind parameters values present in the query, executeQueryForCollection(..) is not the place as its too late and the values has already been extracted for execution.
Excellent info!! Really Thanx!
VC said…
You said that this is in version if im using a previous versiĆ³n what can i do for do this procedure

Nicolas Pilot said…
Do you have a solution for version ?
You can put your logic in executeQueryForCollection. It will not have such good performance as the one described by Jobinesh, but it ll do the job.
Nicolas Pilot said…
One problem with overwriting executeQueryForCollection to set bind variables is, that it is too late in the life cycle.
I've discussed with John Stegeman & Timo Hahn about that here:

A workaround solution is to set the default value of the bind variable using a groovy expression.
varun said…
I am running master-detail relationship. For ex: there are tables schools, students, studentDetails, subject etc.

when user logs in on site I am having school id. Corresponding to school id I need to fetch all students for that school and for each student information should be displayed in tree format. Like for student1 information like name, subjects, performance etc should be displayed when I click on student id in tree. these information are coming from multiple table like studentdetails, subjects.

Here is the approach I follow.

Create Application Module

Created 2 views:
studentsVO : fetching studentId, studentName from students table. This contains binding variable for schoolId. To fetch all students only for that school.
StudentInfoVO: fetching student information from various tables along with student id to create association with StudentVO. This also contain binding variable for schoolId.

StudentAssociation: to associate studentsVo with studentInfoVO.

Now from data control pallet I drag my studentVO to jsf and added a tree with subchild as studentInfoVO.

In application module studentAM I wrote one client method to bind variable from UI i.e schoolId and expose it to client and to execute query.

method is setSchoolId(Long schoolId){
ViewImpl schoolVO = getSchoolVO();

// it is displaying me tree for all studentId but no information is displayed.

is it the way to bind variable in association.
If I need to populate master VO with detail VO programmatically. How to do that?
Jan Vervecken said…

This blog post is referred to in forum thread "Bind variable required/not required: strange behaviour"

Jan Vervecken
krishna said…
super cool Jobinesh , helped me a lot

Rob Nobel said…
This original post is already years ago, but since the last reaction was feb 2014 I take my chances:
Where does overriding the buildWhereClause (ViewObjectImpl) method fit into all of this ? I checked the diagram on page 151 of your book, but could not figure out at which moment this method is executed ?

Popular posts from this blog

How to set Bind Variable Values at runtime ?

In this post I'm sharing a couple of approaches for programmatically setting bind variables values at run time. This post is an attempt to explain 'When to use what ?'[ In case if you are familiar with 'Bind Variables' in ADF BC, please refer Section 5.10, Working with Bind Variables in Fusion Developer's Guide ]

1. Set the Bind Variable value using RowSet::setNamedWhereClauseParam(...)

You can use use the setNamedWhereClauseParam(...) method on the ViewObject interface (which extends oracle.jbo.RowSet) to set the value for bind variables. Please note this sets the value on default RowSet. In other words, this doesn't have any effect on the secondary RowSets that you/system generates.
ViewObject vo = am.findViewObject("EmployeesView1"); vo.setNamedWhereClauseParam("bindVarDeptId", new Number(10)); vo.executeQuery();
2. Set the Bind Variable value using ViewObject's VariableValueManager::setVariableValue(...)

VariableValueManager Ma…