15-M2. Mapper → DB: SQL 실행
MyBatis는 Mapper 메서드 호출을 SqlSession으로 넘기고, 다시 Executor, StatementHandler, PreparedStatement 계층을 통해 실제 SQL을 실행합니다.
이 단계는 MyBatis가 DB에 닿는 실제 호출 체인을 보여줍니다.
이번 단계의 역할 — 인터페이스 메서드가 실제 SQL 실행으로 바뀌는 구간
Mapper 호출을 JDBC 실행까지 연결하는 구간입니다. 즉 인터페이스 메서드가 실제 SQL 실행으로 바뀌는 단계입니다.
호출 흐름 요약 — selectOne() → selectList() → SimpleExecutor.doQuery() → StatementHandler
MapperMethod.execute(...)가sqlSession.selectOne(...)을 호출합니다.DefaultSqlSession.selectOne(...)은 내부적으로selectList(...)를 사용합니다.SimpleExecutor.doQuery(...)가StatementHandler를 준비합니다.PreparedStatementHandler.query(...)가ps.execute()를 호출합니다.
호출 흐름 다이어그램 — DefaultSqlSession부터 PreparedStatementHandler의 ps.execute()까지
sequenceDiagram
participant Method as MapperMethod
participant Session as DefaultSqlSession
participant Exec as SimpleExecutor
participant PS as PreparedStatementHandler
participant DB
Method->>Session: selectOne(statement, param)
Session->>Exec: executor.query(...)
Exec->>PS: handler.query(stmt, resultHandler)
PS->>DB: ps.execute()
핵심 코드 — selectOne()이 내부적으로 목록 조회를 먼저 한다
// MapperMethod.java
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
// DefaultSqlSession.java
public <T> T selectOne(String statement, Object parameter) {
List<T> list = this.selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
}
return null;
}
// SimpleExecutor.java
Statement stmt = prepareStatement(handler, ms.getStatementLog());
return handler.query(stmt, resultHandler);
// PreparedStatementHandler.java
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
코드 해설 — selectOne()은 리스트 개수를 검사하고 JDBC 실행은 ps.execute()에서 일어난다
MyBatis는 selectOne()이라고 부르지만, 내부적으로는 먼저 리스트 조회를 수행하고 결과 개수를 검사합니다.
그리고 실제 JDBC 실행은 PreparedStatementHandler.query()의 ps.execute()에서 일어납니다.
설계 의도 — 세션·실행기·StatementHandler를 나눠 SQL 실행 파이프라인을 확장 가능하게 한다
Mapper, 세션, 실행기, StatementHandler를 분리해 SQL 실행 파이프라인을 확장 가능하게 만들기 위한 구조입니다. 덕분에 캐시, 플러그인, 로깅, 결과 처리 전략을 중간에 쉽게 끼워 넣을 수 있습니다.
다음 단계 연결 — 15-M3 결과를 ResultSetHandler가 처리하는 과정으로 이어진다
다음 문서 15-M3에서는 DB가 돌려준 결과를 MyBatis가 어떻게 ResultSetHandler로 처리하는지 봅니다.