views:

40

answers:

1

I want to create a subclass that extends the CallableStatement object. I want to do this so I can override the execute and executeQuery methods to track some metrics on each SP call.

Currently I have code that looks like this:

Connection db = poolingDataSource.getConnection();
CallableStatement cstmt = db.prepareCall("{call pSampleStoredProc()}");
ResultSet rs = cstmt.executeQuery();

where poolingDataSource is from the apache commons dbcp package. My implementation is hooked into a MySQL database using JDBC.

Currently, the prepareCall method returns a com.mysql.jdbc.JDBC4CallableStatement. I'd like to be able to change this so that it returns a class of my own that extends JDBC4CallableStatement but overrides the execute() and executeQuery() methods.

Any ideas about the best way to do this?

+3  A: 

If you have a manageable number of places where you need to do this, I suggest an easy way to do it (easier than trying to get that database driver to return your custom CallableStatement object) would be to make a wrapper or decorator to wrap over the CallableStatement object you get from db. Basically make a class that implements all the methods of CallableStatement, takes a CallableStatement object as a parameter to its constructor, and delegates all the method calls right through to the other object, with the exception that for execute() and executeQuery() you also call your logging methods before and after delegating to the other objects execute() method.

Certainly there are other ways to do this, this just struck me as easier.

Connection db = poolingDataSource.getConnection();
CallableStatement cstmt = db.prepareCall("{call pSampleStoredProc()}");
MyCallableStatement mystmt = new MyCallableStatement( cstmt );
ResultSet rs = mystmt.executeQuery();
Jake
`CallableStatement mystmt = new MyCallableStatement( cstmt );`. Actually, you could wrap the `Connection` too.
Tom Hawtin - tackline
This is a good idea, although not as elegant as I was hoping. :-) Tom, your comment gave me an idea about how I could do this in a way that is more reusable so that other programmers on the team won't have to remember to use MyCallableStatement. Unless someone else can come up with a more elegant solution, this is it.
Stephen
@tackline If the goal is encapsulating then I would wrap the whole thing (`DataSource`, `Connection`, `CallableStatement`). So, to client code it would be absolutely transparent.
gpeche
I've found it pretty helpful to wrap the code where I get a connection in some generic utility method of my own, so that if/when I need to go back and change something, or add something (like logging) then I can just do whatever I needed to do in that utility method instead of changing every piece of code in the app that gets a db connection. This would be a good example. :)
Jake
I ended up creating a decorate Connection object which returned a decorated CallableStatement. Since my connection creation process was in common code (which isn't represented in the example I gave above), this presented an ideal way to create these decorated objects with a minimum of code changes (and new code should pick up these changes without even thinking about it.)
Stephen