Spring

JDBCTemplate을 사용한 JDBC 쿼리의 스트림 결과

기록만이살길 2022. 11. 13. 19:38
반응형

JDBCTemplate을 사용한 JDBC 쿼리의 스트림 결과

1. 질문(문제점):

나는 Spring 자바를 사용하고 있습니다.

Stream데이터베이스 쿼리에서 개체 를 반환해야 합니다 ( ObjectMapper이를 JSON에 매핑하는 데 사용).

쿼리 결과는 상당히 클 수 있으므로(500k 개체 이상) 메모리에 저장하고 싶지 않습니다.

나는 그것을 했다 JpaRepository.

어떻게 할 수 있고 그렇게 할 JdbcTemplate때 이점이 있는지 알고 싶습니다.

JdbcTemplate즉 ... 또는 다른 라이브러리 를 사용하여 처리량과 메모리 사용을 최적화할 수 있습니까?

내 목표는 결국 메모리/시간/처리 측면에서 쿼리를 실행하고 모든 개체를 출력 스트림에 인쇄하는 최적의 방법을 찾는 것입니다.

2. 해결방안:

예, 스트림은 모든 데이터를 메모리에 저장하지 않고 데이터를 처리하기 위한 일반적인 추상화이므로 이점이 있습니다. 예를 들어 스트림을 HTTP 응답으로 전달합니다.

Spring 5.3

Spring 5.3을 사용하는 경우 다음과 같이 사용할 수 있는 편리한 방법 JdbcTemplate.queryForStream()이 있습니다.

String sql = "select * from table";

Stream<Person > stream = jdbcTemplate.queryForStream(sql, (resultSet, rowNum) -> {
    return new Person(resultSet.getInt(1), resultSet.getString(2));
});

이전 Spring 버전

의 이전 버전에는 JDBCTemplate직접 스트림에 대한 기능이 없습니다. 그러나 기본 데이터베이스 연결을 사용하여 스트림을 만들 수 있습니다.

String sql = "select * from table";

Connection connection = jdbcTemplate.getDataSource().getConnection();
PreparedStatement statement = connection.prepareStatement(sql);
ResultSet resultSet = statement.executeQuery();

PersonMapper personMapper = new PersonMapper();

Spliterator<Person> spliterator =
    Spliterators.spliteratorUnknownSize(
        new Iterator<Person>() {
            @Override public boolean hasNext() {
                try {
                    return !resultSet.isAfterLast();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            @Override public Person next() {
                try {
                    if (resultSet.isBeforeFirst()) {
                        resultSet.next();
                    }

                    Person result = new Person(resultSet.getInt(1), resultSet.getString(2));

                    resultSet.next();
                    return result;
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        },
        Spliterator.IMMUTABLE);

Runnable closer = () -> {
    try {
        resultSet.close();
        statement.close();
        connection.close();
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
};

Stream<Person> = StreamSupport.stream(spliterator, false).onClose(closer);
반응형