如何使用 Spring 和 JDBCTemplate 取消长时间运行的查询?
JDBC java.sql.Statement
类有一个 cancel()
方法。 可以在另一个线程中调用它来取消当前正在运行的语句。
我如何使用 Spring 来实现这一目标? 我找不到在运行查询时获取对语句的引用的方法。 我也找不到类似取消的方法。
这是一些示例代码。 想象一下这需要长达 10 秒的时间来执行,有时根据用户的请求,我想取消它:
final int i = simpleJdbcTemplate.queryForInt("select max(gameid) from game");
我如何修改它以便我拥有对 java.sql.Statement
对象的引用?
The JDBC java.sql.Statement
class has a cancel()
method. This can be called in another thread to cancel a currently running statement.
How can I achieve this using Spring? I can't find a way to get a reference to a statement when running a query. Nor can I find a cancel-like method.
Here's some sample code. Imagine this takes up to 10 seconds to execute, and sometimes on the user's request, I want to cancel it:
final int i = simpleJdbcTemplate.queryForInt("select max(gameid) from game");
How would I modify this so I have a reference to a java.sql.Statement
object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
让我简化一下 oxbow_lakes 的答案:您可以使用查询方法的
PreparedStatementCreator
变体来访问该语句。因此,您的代码:
应该变成:
现在要取消,您只需调用
您可能希望在实际运行查询之前向其他线程提供对 stmt 的引用,或者只是将其存储为成员变量。 否则,你真的无法取消任何事情......
Let me simplify oxbow_lakes's answer: you can use the
PreparedStatementCreator
variant of the query method to gain access to the statement.So your code:
Should turn into:
Now to cancel you can just call
You probably want to give a reference to
stmt
to some other thread before actually running the query, or simply store it as a member variable. Otherwise, you can't really cancel anything...您可以通过
JdbcTemplate
方法执行内容,这些方法允许您传入PreparedStatementCreator
。 您始终可以使用它来拦截调用(也许使用代理
),这会导致取消
在单独的线程上发生,由某些cond
变为<代码> true。这个
canceller
本身可以在成功完成后被取消; 例如,现在响应用户取消的代码将如下所示:
You can execute stuff via
JdbcTemplate
methods which allow you to pass in aPreparedStatementCreator
. You could always use this to intercept invocations (perhaps using aProxy
) which caused acancel
to happen on a separate thread by somecond
becametrue
.This
canceller
could itself be cancelled upon successful completion; for exampleSo now the code that is responding to a user's cancellation would look like:
您可以在
JdbcTemplate
上注册一个StatementCallback
类型的回调对象,该对象将以当前活动语句作为参数执行。 在此回调中,您可以取消该语句:You can register a callback object of type
StatementCallback
onJdbcTemplate
that will get executed with the currently active statement as a parameter. In this callback you can then cancel the statement:我假设Spring你指的是使用JdbcDaoTemplate和/或JdbcTemplate? 如果是这样,这并不能真正帮助或阻碍您解决问题。
我假设您的用例是您正在一个线程中执行 DAO 操作,而另一个线程进入并想要取消第一个线程的操作。
你要解决的第一个问题是,第二个线程如何知道要取消哪个线程? 这是一个具有固定数量线程的 GUI,还是具有多个线程的服务器?
一旦解决了该部分,您需要弄清楚如何取消第一个线程中的语句。 一种简单的方法是将第一个线程的PreparedStatement存储在某个字段中(可能在一个简单的字段中,可能在线程ID到语句的映射中),允许第二个线程进入,检索statwment并调用cancel()在上面。
请记住,cancel() 可能会阻塞,具体取决于您的 JDBC 驱动程序和数据库。 另外,请确保您认真考虑这里的同步,您的线程是否会陷入战斗。
I assume by Spring you mean the use of JdbcDaoTemplate and/or JdbcTemplate? If so, this doesn't really help or hinder you in solving your problem.
I'll assume your use case is that you're executing a DAO operation in one thread, and another thread comes in and wants to cancel the first thread's operation.
The first problem you have to solve is, how does the second thread know which one to cancel? Is this a GUI with a fixed number of threads, or a server with several?
Once you've solved that part, you need to figure out how to cancel the statement in the first thread. One simple approach to this would be to store the first thread's PreparedStatement in a field somewhere (perhaps in a simple field, perhaps in a map of thread ID to statements), allowing the second thread to come in, retrieve the statwmentand call cancel() on it.
Bear in mind that it's possible that cancel() may just block, depending on your JDBC driver and database. Also, make sure you think hard about synchronization here, are your threads are going to get into a fight.