2015-02-12 3 views
0

Я застрял здесь с этой проблемой. Я запускаю приложение на моем сервере приложений Tomcat. В качестве интерфейса я использую HTML-сайт с javascript в нем, в бэкэнд я использую Java.Отменить SQL-заявление с помощью JDBC

Когда пользователь нажимает кнопку, несколько запросов 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(); 
    } 
} 

Таким образом, пользователь нажимает на кнопку Run =>runQuery выполняется и STMT инициализируется/перекрываться с запросом, который нужно выполнить.

Затем пользователь нажимает кнопку отмены =>cancelQuery. К сожалению, иногда я получаю исключение NullPointerException, потому что stmt имеет значение null. Но он не должен даже вызывать cancelQuery, если stmt равно null?! Вот StackTrace:

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) 
..... 

Любая идея, почему это продолжает производить исключение? Как я могу отменить утверждение правильно?

EDIT: Я получил ссылку на комментарии в комментариях и теперь запускаю метод cancel() из другого потока. Однако NullPointer все еще происходит. Это, как я называю метод отмены() теперь:

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(). Потому что я закрыл заявление & соединение NullPointer было брошено. Теперь я удалил этот блок, но это, конечно, ведет к огромному утечке ресурсов. Любой, кто может вести меня в правильном направлении, как правильно закрыть мои ресурсы?

+0

см. Http://stackoverflow.com/q/16589497/217324 –

+0

@NathanHughes, пожалуйста, взгляните на мой отредактированный вопрос. ссылка не принесла общего решения :( – dehlen

+0

Я бы сказал, зачем беспокоиться об этом? Просто поймите NullPointerException. – mwarren

ответ

1
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(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

Попробуйте это. Я добавил общее исключение сразу после SQLException.

Не могу сказать, что это очень чистое решение, но оно будет игнорировать исключение нулевого указателя, которое может быть вызвано оператором stmt.close().

+0

Поскольку это своего рода ответ, с которым я иду, я буду отмечать вас как принято, хотя это может быть не самое чистое решение. – dehlen

0

Вы должны взглянуть на Apache DB-Utils это делает этот вид проблемы исчезают, и вы можете просто написать что-то вроде:

} finally { 
    DbUtils.closeQuietly(resutlSet); 
    DbUtils.closeQuietly(preparedStatement); 
    DbUtils.closeQuietly(connection); 
} 
0

Вы можете использовать Statement.cancel()

Как Java Docs говорит

void cancel() 
      throws SQLException 

Отменяет этот объект, если себе как СУБД и поддержка драйверов прерывания оператора SQL. Этот метод может использоваться одним потоком для отменить инструкцию, выполняемую другим потоком.

Вы также можете установить setQueryTimeout, если выполнение запроса проходит время порогу

java.sql.Statement.setQueryTimeout(seconds) 

Update

Не забудьте Rollback на транзакцию

Любой, кто может вести меня в правильном направлении, как закрыть мой ресурсов правильно?

это то, что для, наконец, блок был изобретен

finally{ 
//Release All Resources 
} 

окончательно преградить всегда выполняется, когда попытка блокировать выходы. Этот гарантирует, что блок finally будет выполнен, даже если произойдет непредвиденное исключение . Но, наконец, полезно не только для исключения обработки - это позволяет программисту избежать кода очистки случайно обходить путем возврата, продолжения или разрыва. Ввод кода очистки код в блоке finally всегда является хорошей практикой, даже если не ожидаются исключения .

+0

спасибо за ваш ответ, но в основном вы описываете то, что я уже пробовал. Я закрываю все свои ресурсы в блоке finally и запускаю метод cancel() из другого потока. – dehlen

Смежные вопросы