2

私の要件は、長時間実行される IO 操作がデータベースの選択であることを除いて、これと非常に似ています。

そのスレッドで提案されたかなり創造的な解決策の 1 つは、別のスレッドで IO ストリームを閉じることでした。ただし、入力ストリームまたはソケットへの参照は実際にはありません。

spring-jdbc を使用しているため、使用中の接続を閉じることさえできません。これにより、使用中の基になる接続へのアクセスが提供されません。JdbcTemplate.getDataSource().getConnection()データ ソースから別の接続が返される可能性があると思います。

私が得ることができる助け/提案に感謝します。

4

2 に答える 2

2

JdbcTemplate.execute(PreparedStatementCreator、PreparedStatementCallback)を使用します

PreparedStatementCreatorで、ステートメントにアクセスできます。このステートメントは、別のスレッドに渡すことができます。この他のスレッドはタイマーを作成し、必要に応じてステートメントで.cancelを呼び出します。

于 2012-06-29T16:08:37.513 に答える
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);
        }
    }
}
于 2012-07-05T13:34:03.817 に答える