
Overriding doDML() to populate an attribute with a gapless sequence
In this recipe, we will go over a generic programming technique that you can use to assign gapless database sequence values to entity object attributes. A gapless sequence will produce values with no gaps in between them. The difference between this technique and the one presented in the Using a custom property to populate a sequence attribute recipe, is that the sequence values are assigned during the transaction commit cycle instead of during component creation.
Getting ready
We will add this generic functionality to the custom entity framework class that we created in the Setting up BC base classes recipe in Chapter 1, Pre-requisites to Success: ADF Project Setup and Foundations. The custom framework classes in this case reside in the SharedComponets
workspace. You will need access to the HR
database schema to run the recipe's test case.
How to do it...
- Start by opening the
SharedComponets
workspace in JDeveloper. If needed, follow the steps in the referenced recipe to create it. - Locate the custom entity framework class in the
SharedBC
project and open it in the editor. - Click on the Override Methods… icon on the toolbar (the green left arrow) to bring up the Override Methods dialog.
- From the list of methods that are presented, select the doDML() method and click OK. JDeveloper will go ahead and insert a
doDML()
method into the body of your custom entity class. - Add the following code to the
doDML()
before the call tosuper.doDML()
:// check for insert operation if (DML_INSERT == operation) { // iterate all entity attributes for (AttributeDef atrbDef :this.getEntityDef().getAttributeDefs()) { // check for a custom property called COMMITSEQ_PROPERTY String sequenceName=(String)atrbDef.getProperty(COMMITSEQ_PROPERTY); if (sequenceName != null) { // create the sequence based on the custom property sequence name SequenceImpl sequence = new SequenceImpl(sequenceName, this.getDBTransaction()); // populate the attribute with the next sequence number this.populateAttributeAsChanged(atrbDef.getIndex(), sequence.getSequenceNumber()); } } }
How it works...
If you examine the code presented in this recipe, you will see that it looks similar to the code presented in the Using a custom property to populate a sequence attribute recipe in this chapter. The difference is that this code executes during the transaction commit phase. During this phase, the ADF framework calls the entity's doDML()
method. In our overridden doDML()
, we first check for a DML_INSERT
operation flag. This would be the case when inserting a new record into the database. We then iterate the entity's attribute definitions looking for a custom property identified by the constant COMMITSEQ_PROPERTY
. Based on the property's value, we create a sequence object and get the next sequence value by calling getSequenceNumber()
. Finally, we assign the sequence value to the specific attribute by calling populateAttributeAsChanged()
. Assigning a sequence value during the commit phase does not allow the user to intervene. This will produce gapless sequence values. Of course to guarantee that there are no final gaps in the sequence values, deletion should not be allowed. That is, if rows are deleted, gaps in the sequence values will appear. Gaps will also appear in case of validation failures, if you do not subsequently rollback the transaction. Since all of the entity objects are derived from the custom entity framework class, all object commits will go through this doDML()
implementation.
To use this technique, first you will need to re-deploy the shared components project. Then add the CommitSequence
custom property as needed to the specific attributes of your entity objects. We explained how to do this in the Using a custom property to populate a sequence attribute recipe.
There's more...
doDML()
is called by the ADF framework during a transaction commit operation. It is called for every entity object in the transaction's pending changes list. This is true even when entity Update Batching optimization is used. For an entity-based view object, this means that it will be called for every row in the row set that is in the pending changes list. The method accepts an operation flag; DML_INSERT
, DML_UPDATE
, or DML_DELETE
to indicate an insert, update, or delete operation on the specific entity.
Data is posted to the database once super.doDML()
is called, so any exceptions thrown before calling super.doDML()
will result in no posted data. Once the data is posted to the database, queries or stored procedures that rely upon the posted data should be coded in the overridden application module's beforeCommit()
method. This method is also available at the entity object level, where it is called by the framework for each entity in the transaction's pending changes list. Note that the framework calls beforeCommit()
for each entity object in the transaction pending changes list prior to calling the application module beforeCommit()
.
For additional information on doDML()
, consult the sections Methods You Typically Override in Your Custom EntityImpl Subclass and Transaction "Post" Processing (Record Cache) in the Fusion Developer's Guide for Oracle Application Development Framework,which can be found at http://docs.oracle.com/cd/E24382_01/web.1112/e16182/toc.htm.
Note
Note that for testing purposes, we have created a Department
entity object in the HRDepartments
workspace and added the CommitSequence
custom property to its DepartmentId
attribute. The value of the CommitSequence
property was set to DEPARTMENTS_SEQ
, the database sequence that is used to assign values to the DepartmentId
attribute. To test the recipe, run the DepartmentAppModule
application module on the ADF Model Tester .
See also
- Breaking up the application in multiple workspaces, Chapter 1, Pre-requisites to Success: ADF Project Setup and Foundations
- Setting up BC base classes, Chapter 1, Pre-requisites to Success: ADF Project Setup and Foundations
- Using a custom property to populate a sequence attribute, in this chapter
- Creating and applying property sets, in this chapter