Skip to main content

Soft deletion of rows

In this post I'm sharing a simple example illustrating the 'soft deletion' of rows and undoing the delete later if the user opts for. The business use case requirement is that, whenever end user delete rows, system should not delete these rows from the underlying data base table, rather should mark(update) them as deleted. Later user can undo the deletion to restore the deleted rows(this operation should not rollback the transaction)


Download

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS4 + HR Schema]

A glance at the implementation

The 'Soft Delete' action has two steps,
1.The action first refreshes the row with database by calling row.refresh(Row.REFRESH_WITH_DB_FORGET_CHANGES) to discard the modifications that user might have done on the row before opting for delete(if any)
2. Next step is to remove the row from the iterator(effectively from entity object). Deleted row keys are stored in an ArrayList for performing 'undo' operation if needed.

Later when user commits transaction, entity instance will check for operation flag and will change it to UPDATE if the value is DELETE, and would flag an attribute as well to enable soft delete at database table level. In the above sample commits action updates DepartmentName attribute by prefixing '[DELETE]' token . The view object query has necessary where clause added to remove the soft deleted rows from the result list.

The roll back action of deleted rows refreshes the deleted entity rows with data base to restore them back to the original state.


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- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

Comments

Ankur Pradhan said…
Hi Jobinesh,

Excellent Post. I have a similar requirement, so I followed the same steps. But my doDML method is not getting invoked and even delete is not happening.

I am having logic for physical delele, so I replaced my logic with your logic given in managed bean, seem neither the delete is happening nor doDML method is getting invoked.

Attached my code snipped:

ViewObjectImpl vo =
(ViewObjectImpl)((DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry()).findIteratorBinding("SprPatchDetailsVO1Iterator").getViewObject();
Row row = vo.getCurrentRow();
String patchLocation = (String)vo.getCurrentRow().getAttribute("PatchLocation");
// String patchRowId = (String)vo.getCurrentRow().getAttribute("PatchRowId");
logger.info("Current Row Patch Location:" + patchLocation);
vo.removeCurrentRow();
// Commit changes to db
if (commitDBChanges()) {
if (patchLocation != null && patchLocation.length() > 0) {
try {

File patchFileLoc = new File(downloadPatchBaseLocation);
patchFileLoc.delete();
} catch (Exception e) {
logger.warning("patch file not found.", patchLocation);
logger.warning(e);
}
} else {
logger.warning("patch file not found.", patchLocation);
}

} else {
logger.severe("delete patch failed...");
}

.......

private boolean commitDBChanges() {
final String METHOD_NAME = "commitDBChanges()";
logger.entering(CLASS_NAME, METHOD_NAME);
boolean commitSuccess = false;
try {
BindingContainer bindings = getBindings();
OperationBinding operationBinding = bindings.getOperationBinding("Commit");
operationBinding.execute();
commitSuccess = true;

} catch (Exception e) {
e.printStackTrace();
logger.severe(e);
}

logger.exiting(CLASS_NAME, METHOD_NAME);
return commitSuccess;
}
Ankur Pradhan said…
This comment has been removed by the author.

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…