2012-06-29 2 views
2

Мое требование очень похоже на this, за исключением того, что моя длинная операция ввода-вывода - это выбор базы данных.Прерывать поток, выполняющий длинную базу данных, выбрать

Одно довольно своеобразное решение, предлагаемое в этой теме, включающее закрытие потока ввода-вывода в отдельном потоке. Однако на самом деле у меня нет ссылки на входной поток или сокет.

Я не могу даже закрыть соединение, которое используется, поскольку я использую spring-jdbc, который не предоставляет мне доступ к используемому базовому соединению. Я считаю, что JdbcTemplate.getDataSource().getConnection() потенциально вернет другое соединение из источника данных.

Оцените любую помощь/предложения, которые я могу получить.

ответ

2

Использование JdbcTemplate.execute(PreparedStatementCreator, PreparedStatementCallback)

В PreparedStatementCreator, вы получите доступ к заявлению, которое вы можете дать другому потоку. Этот другой поток создает таймер и при необходимости вызывает .cancel в Заявлении.

1

Как упоминалось в Иштване, подготовленный государственный контроль - это путь. Вставка моей реализации в случае ее полезности.

private final long timeout = 1000; //timeout in seconds 
final SqlRowSet rowSet = jdbcTemplate.getJdbcOperations().query(new PreparedStatementCreator() { 
    @Override 
    public PreparedStatement createPreparedStatement(Connection con) throws SQLException { 
     if (timeout>0){ 
      Timer timer = new Timer(); 
      timer.schedule(new ConnectionInterrupter(con), timeout*1000); 
     } 
     return con.prepareStatement(queryString); 
    } 
}, new ResultSetExtractor<SqlRowSet>() { 
    @Override 
    public SqlRowSet extractData(ResultSet rs) throws SQLException, DataAccessException { 
     CachedRowSet rowSet = newCachedRowSet(); 
     rowSet.populate(rs); 
     return new ResultSetWrappingSqlRowSet(rowSet); 
    } 

    protected CachedRowSet newCachedRowSet() throws SQLException { 
     return new CachedRowSetImpl(); 
    } 
}); 
private class ConnectionInterrupter extends TimerTask { 
    private final Connection connection; 
    public ConnectionInterrupter(Connection connection) { 
     this.connection = connection; 
    } 

    @Override 
    public void run() { 
     try { 
      logger.warn("Connection timeout has occurred. Manually closing the connection ..."); 
      connection.close(); 
     } catch (SQLException e) { 
      throw new RuntimeException(e); 
     } 
    } 
}