Saturday, June 02, 2007

To find what data has changed in the database?

The problem statement is to find out what data has changed in the database if a transaction is committed. I am helping one of my Customers to build a similar application. Before I jump to the solution let me babble a bit.
We do work on a core application and then new requirements pop up time and again which do not disturb the core process but threatens to affect it. Such requirements are called crosscutting concerns. In one of my old blogs I have cursed such requirements. Things like Logging, Auditing, Profiling etc which does not restrict itself to a single component but affects the entire application. The solution to these problems is the concept of Interceptors. The code need not be changed but new Interceptors are written which can be added/hooked to the "project" which can provide the wanted solution. The concept of Interceptors is not new. Like HTTP plugins (like NSAPI and Apache plugins) Or ServletFilters which are added to intercept the HTTP requests and add/change the default behavior of the web server. Or even more powerful like EJB3 Interceptors or AOP.

So coming back to the original problem: In terms of databases there are two broad categories:
1. To implement it as a database trigger
2. To let the O-R mapper do it for you

Even though they both work, Option(2) is more elegant. It also provides the portability to the application with all the other goodies which O-R mapper gives. In Oracle's Toplink, it can be implemented as a SessionEventListener. The oracle.toplink.sessions.SessionEventListener is an interface which provides all the predefined events which take place in the lifecycle of a Session. If you do not want to implement or have empty methods, your class can extend SessionEventAdapter which does the same thing. The SessionEventListener is then hooked to the Toplink project with its' Toplink session. Here is how you do it:


# Client.java

public class Client {
...

public Session getSession () {
TestProject tP = new TestProject ();
DatabaseSession session = tP.createDatabaseSession ();
MySessionEventListener mL = new MySessionEventListener ();
session.getEventManager ().addListener (mL);
return session;
}
}

# MySessionEventListener.java

public class MySessionEventListener implements SessionEventListener {
...
public void postCommitUnitOfWork (SessionEvent event) {
Session session = event.getSession ();
UnitOfWork uow = (UnitOfWork) session;
UnitOfWorkChangeSet uCS = uow.getCurrentChanges ();
if (uCS != null) {
Enumeration enums = uCS.getAllChangeSets ().elements ();
// -- Traverse through the elements of what has changed.
}
}
}

Thats all you need... Run the application and Toplink will make sure that all the attached listeners keep an eye on all the events and in this case all what has changed.

Happy Toplinking...

No comments: