数据库查询中断

时间:2017-01-05 11:09:27

标签: java multithreading interrupt spring-jdbc futuretask

我已经在新线程中启动了一些进程:

FutureTask<?> futureTask = new FutureTask<Void>(() -> {
               startSomeProcess();
            }, null);

startSomeProcess方法中,我为每个项目生成报告:

for (Item item : items) {
            if (Thread.interrupted()) {
                logger.info("currentThread isInterrupted");
                return;
            }
             generateReport(item);
     }

generateReport()方法中,我执行一些select to DB并从ResultSet生成excel报告:

try (PreparedStatement ps = conn.prepareStatement(query.toString(),
                    ResultSet.TYPE_SCROLL_INSENSITIVE)) {
                ResultSet rs = ps.executeQuery();
                //and fill excel from rs 
                 ...

但我的ps.executeQuery();可以执行很长时间(1秒999999h。 我有取消按钮。如果它按我做这个

futureTask.cancel(true); 

并检查startSomeProcess();方法中的异常。但我无法检查和中断ps.executeQuery();。当我futureTask.cancel(true);这个executeQuery抛出异常时。但我不配置这个。这是自动的。

我的语言:当我中断线程时 - 我可以自己中断查询到数据库,还是刚刚发生,我只能处理错误?

编辑:

用户发送命令 - “取消报告生成”。我晕倒了futureTask并调用了cancel()方法。并打破构建报告。但是如果ps.executeQuery();已经开始了 - 我不知道怎么打破它

2 个答案:

答案 0 :(得分:1)

  

我的问题:当我中断线程时 - 我可以自己中断对数据库的查询,还是刚刚发生,我只能处理错误?

中断线程只在线程上设置一个标志,这只会导致抛出InterruptedException的那些方法。在这种情况下,SQL方法不会抛出InterruptedException,因此只调用future.cancel(true)将不起作用。

如果您尝试取消正在运行的SQL查询,那么您需要canceling the underlying Statement在JDBC级别进行此操作。引用Statement.cancel()的javadoc:

  

如果DBMS和驱动程序都支持中止SQL语句,则取消此Statement对象。一个线程可以使用此方法来取消正由另一个线程执行的语句。

所以在你的情况下,这意味着另一个线程将不得不取消你的ps。我创建了一个包装generateReport()方法的对象,该方法将PreparedStatement ps放入volatile字段。然后,当方法执行ps时,它会从字段执行,而另一个线程可以调用cancel()上调用ps.cancel()的对象。

请务必注意,查询取消是SQL数据库和JDBC驱动程序相关的。并非所有数据库都支持它。

答案 1 :(得分:0)

  

当我中断线程时 - 我可以自己中断查询到数据库,还是刚刚发生,我只能处理错误?

executeQuery启动后,可以使用cancel方法停止。

其他方式是处理异常或使用setQueryTimeout