Hi,
I need a solution for cancelling a long-running select statement.
I'm using Spring 3.0.2, iBatis 2.3.0 and Oracle 10g.
I managed to get it to work with plain JDBC, but because the select is
generated dynamically through an advanced search screen, I really need
to use iBatis.
The iBatis internal class responsible for the creation/retrieval from cache of prepared statements is com.ibatis.sqlmap.engine.execution.SqlExecutor. The internal method called for every call of queryForList()/queryForObject() is SqlExecutor's
public void executeQuery(RequestScope request, Connection conn,
String sql, Object[] parameters, int skipResults, int maxResults,
RowHandlerCallback callback) throws SQLException
method.
Due to performance reasons, iBatis creates a new prepared statement
only if one does not already exist for the given select statement.
The prepared statements are stored/cached in a HashMap where the sql
string is the key and the prepared statement is the value.
Unfortunately, iBatis and the newer version myBatis don't seem to offer any support for cancelling a long running prepared statement.
After trying different other solutions with no success, I think it might be possible to work with AspectJ
to try to advice the SqlExecutor.executeQuery() method and somehow
store on the HTTP session the iBatis cache map and sql string, both of them available as method arguments.
When the user will try to cancel the long-running query, a check will
be made from another thread to see if a prepared statement already
exists in the iBatis cache map for the given sql string, previously
stored on the HTTP session through AOP.
If one does exist, a Statement.cancel() call will be issued.
I don't see why a solution like this might interfere with the iBatis
internal mechanisms since if the prepared statement will be canceled, an
SqlException will be thrown (ORA-01013 user requested cancel of current operation) and Ibatis will properly handle that as any other generated SqlException.
Using Spring AOP is not an option because it only
allows you to pointcut methods declared in objects managed by the Spring
container. I cannot declare SqlExecutor as a Spring bean, because it is
created and managed internally by iBatis.
Haven't yet tried the above solution with AspectJ since I'm not quite familiar with the framework, but I started reading about it.
Can anyone please tell me if this is the right approach for my problem? Can I solve it with AspectJ?
Any answer at all will be highly appreciated.
Thanks,
Andrei