PreparedStatementCreator
で渡すことができるJdbcTemplate
メソッドを介してものを実行することができます。これを使用して(Proxy
を使用して)呼び出しを傍受すると、cancel
が別のスレッドで発生し、cond
となり、true
となった可能性があります。
public Results respondToUseRequest(Request req) {
final AtomicBoolean cond = new AtomicBoolean(false);
requestRegister.put(req, cond);
return jdbcTemplate.query(new PreparedStatementCreator() {
public PreparedStatement createPreparedStatement(Connection conn) {
PreparedStatement stmt = conn.prepareStatement();
return proxyPreparedStatement(stmt, cond);
}
},
new ResultSetExtractor() { ... });
}
このcanceller
は、正常終了するとキャンセルされる可能性があります。例えば
private final static ScheduledExecutorService scheduler =
Executors.newSingleThreadedScheduledExecutor();
PreparedStatement proxyPreparedStatement(final PreparedStatement s, AtomicBoolean cond) {
//InvocationHandler delegates invocations to the underlying statement
//but intercepts a query
InvocationHandler h = new InvocationHandler() {
public Object invoke(Object proxy, Method m, Object[] args) {
if (m.getName().equals("executeQuery") {
Runnable cancel = new Runnable() {
public void run() {
try {
synchronized (cond) {
while (!cond.get()) cond.wait();
s.cancel();
}
} catch (InterruptedException e) { }
}
}
Future<?> f = scheduler.submit(cancel);
try {
return m.invoke(s, args);
} finally {
//cancel the canceller upon succesful completion
if (!f.isDone()) f.cancel(true); //will cause interrupt
}
}
else {
return m.invoke(s, args);
}
}
}
return (PreparedStatement) Proxy.newProxyInstance(
getClass().getClassLoader(),
new Class[]{PreparedStatement.class},
h);
だから今、ユーザーの取り消しに応答しているコードは次のようになります。
cond.set(true);
synchronized (cond) { cond.notifyAll(); }
面白いと奇数たとえば、その手で問題に適用する方法を全くわからない:このコールバックでは、その文をキャンセルすることができます。明らかに、10秒の自動キャンセルは、外部からトリガされたものに置き換える必要があります。 – skaffman
なぜ外部からトリガーする必要がありますか? OPはそれについて、何も言及していません、つまり、ユーザー定義の –
OPはここにあります:実際には、私はキャンセルがユーザーの操作に応じてトリガーされることを望みます。 –