中断执行长时间运行的数据库选择的线程

时间:2012-06-29 10:03:31

标签: java spring

我的要求与this非常相似,只是我长时间运行的IO操作是数据库选择。

该线程中建议的一个相当有创意的解决方案,涉及在单独的线程中关闭IO流。但是,我实际上没有对输入流或套接字的引用。

我甚至无法关闭正在使用的连接,因为我使用的是spring-jdbc,它不能让我访问正在使用的底层连接。我相信JdbcTemplate.getDataSource().getConnection()可能会从数据源返回另一个连接。

感谢我能得到的任何帮助/建议。

2 个答案:

答案 0 :(得分:2)

使用JdbcTemplate.execute(PreparedStatementCreator, PreparedStatementCallback)

在PreparedStatementCreator中,您可以访问Statement,您可以将其提供给另一个线程。这个其他线程创建一个计时器,并在必要时在Statement上调用.cancel。

答案 1 :(得分:1)

正如Istvan所提到的,PreparedStatementCreator是要走的路。 粘贴我的实现,以防有用..

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);
        }
    }
}