【发布时间】:2015-02-12 15:49:44
【问题描述】:
我在这里遇到了这个问题。我正在我的 Tomcat 应用程序服务器上运行一个应用程序。作为前端,我使用的是一个带有 javascript 的 HTML 网站,在后端我使用的是 Java。
当用户单击一个按钮时,会进行多个 sql 查询,一个接一个。现在,如果用户愿意,我想提供取消此查询的功能。
我已经检查了我的 jdbc 驱动程序和数据库是否与cancel() 方法兼容,这很好。
这是我的代码:
PreparedStatement stmt = null;
public void runQuery(String query) {
Connection con = getConnection();
try {
stmt = con.prepareStatement(query);
stmt.execute();
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
if(con != null) {
con.close();
}
}
}
public void cancelQuery() {
try {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
所以用户点击运行按钮 => runQuery 被执行,stmt 被初始化/覆盖为需要执行的查询。
然后用户点击取消按钮 => cancelQuery 被执行。
不幸的是,我有时会收到 NullPointerException,因为 stmt 为空。但如果 stmt 为 null ,它甚至不应该调用 cancelQuery ?!
这是堆栈跟踪:
Stacktrace:] with root cause
java.lang.NullPointerException
at com.sybase.jdbc3.jdbc.SybStatement.doCancel(SybStatement.java:646)
at com.sybase.jdbc3.jdbc.SybStatement.cancel(SybStatement.java:614)
at org.apache.tomcat.dbcp.dbcp2.DelegatingStatement.cancel(DelegatingStatement.java:269)
at org.apache.tomcat.dbcp.dbcp2.DelegatingStatement.cancel(DelegatingStatement.java:269)
at de.package.util.DBHelper.cancelQuery(DBHelper.java:82)
.....
知道为什么这会不断产生异常吗?我怎样才能以正确的方式取消声明?
编辑: 我已经查看了 cmets 中的链接,现在从不同的线程运行 cancel() 方法。然而 NullPointer 仍然发生。这就是我现在调用 cancel() 方法的方式:
public void cancelQuery() {
Thread thread = new Thread(new SQLCancelRunnable(stmt));
thread.start();
}
public class SQLCancelRunnable implements Runnable {
PreparedStatement stmt;
public SQLCancelRunnable(PreparedStatement stmt) {
this.stmt = stmt;
}
@Override
public void run() {
if(stmt != null) {
try {
System.out.println(stmt);
System.out.println(stmt.toString());
stmt.cancel();
System.out.println("canceled");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
EDIT2 找到我的答案,问题是 runQuery() 方法的 finally 块。因为我关闭了语句和连接,所以抛出了 NullPointer。 我现在删除了这个块,但这当然会导致大量资源泄漏。谁能指导我正确地关闭我的资源?
【问题讨论】:
-
@NathanHughes 请看看我编辑的问题。该链接没有带来整体解决方案:(
-
我会说,为什么要担心呢?只需捕获 NullPointerException。
-
既然 NullPointerException 是一个运行时异常,我不应该抓住它而是避免它对吗?
-
@dehlen ,查看更新答案了解如何释放资源