15-M3. DB → Mapper: ResultSet 반환
DB가 SQL 실행 결과를 돌려주면, MyBatis는 ResultSetHandler 계층에서 이를 받아 DTO/VO 매핑 준비를 합니다.
이 단계는 JDBC 결과가 Mapper 세계로 다시 들어오는 구간입니다.
이번 단계의 역할 — JDBC 결과를 MyBatis 결과 처리기로 넘기는 단계
PreparedStatement 실행 후 얻은 JDBC 결과를 MyBatis 결과 처리기로 넘기는 단계입니다.
아직 DTO/VO가 완성된 것은 아니고, 우선 ResultSet이 처리기에 전달됩니다.
호출 흐름 요약 — ps.execute() 완료 → handleResultSets(ps) → getFirstResultSet(stmt)
PreparedStatementHandler.query(...)가ps.execute()를 마칩니다.resultSetHandler.handleResultSets(ps)를 호출합니다.DefaultResultSetHandler.handleResultSets(...)가 첫 번째 결과 집합을 가져옵니다.- 이후 결과 매핑이 시작됩니다.
호출 흐름 다이어그램 — PreparedStatementHandler가 DefaultResultSetHandler에 결과를 넘긴다
sequenceDiagram
participant DB
participant PS as PreparedStatementHandler
participant RSH as DefaultResultSetHandler
DB-->>PS: ResultSet
PS->>RSH: handleResultSets(ps)
RSH->>RSH: getFirstResultSet(stmt)
핵심 코드 — query()가 handleResultSets()를 불러 결과 처리를 위임한다
// PreparedStatementHandler.java
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
// DefaultResultSetHandler.java
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ResultSetWrapper rsw = getFirstResultSet(stmt);
...
return collapseSingleResultList(multipleResults);
}
코드 해설 — 결과 처리기를 따로 두어 단건·다건·중첩 매핑을 한 구조에서 다룬다
MyBatis는 DB에서 온 결과를 바로 반환하지 않고 ResultSetHandler에 넘겨서 통합적으로 처리합니다.
이 단계 덕분에 단건 조회, 다건 조회, 중첩 결과 매핑을 한 구조 안에서 처리할 수 있습니다.
설계 의도 — SQL 실행과 결과 매핑을 갈라 각자에 집중하게 한다
SQL 실행과 결과 매핑을 분리해, 한쪽은 JDBC 호출에 집중하고 다른 한쪽은 객체 변환에 집중하게 하려는 구조입니다. 이는 MyBatis가 SQL 중심 프레임워크이면서도 풍부한 매핑 기능을 제공할 수 있는 이유입니다.
다음 단계 연결 — 15-M4 DTO/VO를 만들어 서비스로 돌려주는 과정으로 이어진다
다음 문서 15-M4에서는 ResultSetHandler가 최종적으로 DTO/VO를 만들어 서비스로 돌려주는 과정을 봅니다.