ResultSetExtractor

2024. 5. 17. 09:53Back-End/Spring

데이터베이스와의 상호작용에서 결과 집합(Result Set)을 처리하는 일은 매우 중요하다. 스프링 프레임워크는 JDBC를 통해 데이터베이스와 쉽게 상호작용할 수 있도록 다양한 유틸리티 클래스를 제공하며, 그 중 ResultSetExtractor는 복잡한 쿼리 결과를 처리할 때 유용한 도구이다. 이번 글에서는 ResultSetExtractor에 대해 알아보고, 이를 사용하는 방법을 예제와 함께 설명하고자 한다.

 

ResultSetExtractor란?

ResultSetExtractor는 스프링 JDBC 모듈에서 제공하는 인터페이스로, JDBC ResultSet을 커스터마이즈드 방식으로 처리할 수 있게 한다. 이 인터페이스는 단일 메서드인 extractData를 포함하며, 이 메서드를 구현하여 결과 집합을 원하는 형태로 변환할 수 있다.

 

왜 ResultSetExtractor를 사용하는가?

ResultSetExtractor 복잡한 결과 집합을 처리하는 데 적합하다. 단순한 쿼리의 경우 RowMapper를 사용하여 각 행을 매핑할 수 있지만, 복잡한 조인 쿼리나 계층적 데이터를 처리할 때는 ResultSetExtractor가 더 적합하다. 예를 들어, 여러 테이블을 조인한 결과를 객체 그래프로 변환하거나, 중첩된 데이터를 처리해야 할 때 유용하다.

 

사용 방법

ResultSetExtractor를 사용하는 방법은 간단하다. 먼저, ResultSetExtractor 인터페이스를 구현하는 클래스를 정의한 후, JdbcTemplatequery 메서드에 이를 전달하여 사용한다.

 

예제 코드

다음은 ResultSetExtractor를 사용하여 데이터베이스에서 복잡한 쿼리 결과를 처리하는 예제이다.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@Repository
public class UserRepository {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public UserRepository(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public List<User> findAllUsersWithOrders() {
        String sql = "SELECT u.id AS user_id, u.name AS user_name, o.id AS order_id, o.amount AS order_amount " +
                     "FROM users u LEFT JOIN orders o ON u.id = o.user_id";

        return jdbcTemplate.query(sql, new UserWithOrdersExtractor());
    }

    private static class UserWithOrdersExtractor implements ResultSetExtractor<List<User>> {
        @Override
        public List<User> extractData(ResultSet rs) throws SQLException {
            Map<Long, User> userMap = new HashMap<>();
            while (rs.next()) {
                Long userId = rs.getLong("user_id");
                User user = userMap.get(userId);
                if (user == null) {
                    user = new User();
                    user.setId(userId);
                    user.setName(rs.getString("user_name"));
                    user.setOrders(new ArrayList<>());
                    userMap.put(userId, user);
                }
                Long orderId = rs.getLong("order_id");
                if (orderId != null) {
                    Order order = new Order();
                    order.setId(orderId);
                    order.setAmount(rs.getDouble("order_amount"));
                    user.getOrders().add(order);
                }
            }
            return new ArrayList<>(userMap.values());
        }
    }
}

 

코드 설명

  1. UserRepository 클래스:
    - UserRepository는 JdbcTemplate을 사용하여 데이터베이스와 상호작용하는 리포지토리 클래스이다.
    - findAllUsersWithOrders 메서드는 사용자와 그들의 주문을 조회하는 쿼리를 실행하고, 결과를 User 객체의 리스트로 변환한다.
  2. UserWithOrdersExtractor 클래스:
    - UserWithOrdersExtractor는 ResultSetExtractor 인터페이스를 구현하여, ResultSet을 사용자와 주문 객체로 변환한다.
    -  extractData 메서드는 결과 집합을 처리하여 사용자와 주문 객체를 매핑한다.
    - 사용자 ID를 키로 하는 맵을 사용하여, 중복된 사용자 객체를 생성하지 않고 각 사용자의 주문 목록을 업데이트한다.

결론

ResultSetExtractor는 스프링 JDBC에서 복잡한 결과 집합을 처리하는 데 매우 유용한 도구이다. 이를 사용하면 복잡한 쿼리 결과를 커스터마이즈된 객체 그래프로 변환할 수 있다. RowMapper가 단순한 행 매핑에 적합하다면, ResultSetExtractor는 다중 행 및 중첩된 데이터 구조를 처리하는 데 강력한 해결책을 제공한다. 스프링 애플리케이션에서 복잡한 데이터 매핑이 필요할 때, ResultSetExtractor를 적극 활용해 보기를 권장한다.

 

 

 

 

 

 

'Back-End > Spring' 카테고리의 다른 글

Spring MVC  (0) 2024.05.18
AOP (Aspect-Oriented Programming)  (0) 2024.05.18
@Transactional과 TransactionTemplate  (0) 2024.05.17
배치 업데이트(Batch Update)  (0) 2024.05.17
Spring Data JDBC  (0) 2024.05.16