Чтобы наилучшим образом использовать поток java8 и Spring4, я использую Stream API следующим образом для набора результатов JDBC, полученного из Springs jsdbRestTemplate (код сокращен и упрощен):
public <T> T consumeResultStream(
String query,
Function<Stream<String>, T> extractorFunction
) {
return jdbcTemplate.query(
query,
resultSet -> {
Spliterator<String> spliterator =
Spliterators.spliteratorUnknownSize(
new Iterator<String>() {
@Override public boolean hasNext() {
return !resultSet.isAfterLast();
}
@Override public String next() {
String result = resultSet.getString(0);
resultSet.next();
return result;
}
},
Spliterator.IMMUTABLE);
resultStream = StreamSupport.stream(
spliterator, /*parallel*/ false);
}
return extractorFunction.apply(resultStream);
});
}
Кажется, это работает нормально. Клиенты могут использовать потоковый API таким образом, не беспокоясь о классах jdbc.
List<T> myResult = consumeResultStream("SELECT ...", stream ->
stream.filter((String s) -> ...)
.map(String s -> toT(s))
.collect(toList()));
Однако, когда я выполняю рефакторинг (пытаясь вместо этого предоставить поток клиентским методам), вот так:
final Stream<String> stream =
jdbcTemplate.query(query, resultSet -> {
// ... same as above
return resultStream;
});
return extractorFunction.apply(stream);
я получил
org.springframework.jdbc.InvalidResultSetAccessException:
The object is already closed [90007-199]
Таким образом, кажется, что данные можно прочитать только в методе jdbcTemplate.query()
. Есть ли чистый способ обойти это и вернуть ленивый поток элементов, поступающих из БД? Предположим, что материализация результата и потоковая передача невозможна из-за размера результатов (хотя разбиение на страницы может быть лучшим шаблоном).
jdbcTemplate.query(...)
инкапсулирует операцию, которая обрабатывает результирующий набор и закрывает его. Он не может вернуть ленивый поток. С другой стороны, когда вы предоставляете оператор SQL и обрабатываетеResultSet
вручную, почему бы не работать сStatement
илиPreparedStatement
напрямую? Кроме того, проще реализоватьSpliterator
, а неIterator
. См. stackoverflow.com/q/32209248/2711488. - person Holger   schedule 05.07.2019Files.lines()
иFiles.list()
. - person Holger   schedule 08.07.2019