Deep Dive /Java Web /15-J5

15-J5. EntityManager → JpaRepository: Entity 매핑

Hibernate는 JDBC 결과를 그대로 내보내지 않고, RowReader와 결과 소비기(resultsConsumer)를 통해 엔티티 그래프로 매핑합니다. 이 단계가 있어야 JPA 사용자는 ResultSet이 아니라 Entity를 받게 됩니다.


이번 단계의 역할 — 행 데이터가 애플리케이션이 쓸 객체 구조로 바뀌는 단계

JDBC 결과를 JPA 엔티티 객체로 바꾸는 단계입니다. 즉 DB의 행(row) 데이터가 애플리케이션이 사용할 수 있는 객체 구조로 변환됩니다.


호출 흐름 요약 — JdbcValues 준비 → RowReader 생성 → resultsConsumer.consume()

  1. Hibernate가 JdbcValues를 준비합니다.
  2. RowReader를 생성합니다.
  3. resultsConsumer.consume(...)가 결과를 순회합니다.
  4. 처리 결과가 엔티티 객체 또는 엔티티 컬렉션으로 만들어집니다.

호출 흐름 다이어그램 — ResultSet이 RowReader와 resultsConsumer를 거쳐 Entity가 된다

sequenceDiagram participant RS as ResultSet participant Exec as JdbcSelectExecutorStandardImpl participant Reader as RowReader participant Consumer as resultsConsumer participant Repo as JpaRepository RS-->>Exec: jdbcValues Exec->>Reader: createRowReader(...) Exec->>Consumer: consume(jdbcValues, rowReader) Consumer-->>Repo: Entity / entity list

핵심 코드 — ResultsHelper.createRowReader()가 만든 RowReader를 consume()에 넘긴다

// JdbcSelectExecutorStandardImpl.java
final var rowReader = ResultsHelper.createRowReader(
        factory, rowTransformer, domainResultType, jdbcValues);

final T result = resultsConsumer.consume(
        jdbcValues,
        session,
        processingOptions,
        valuesProcessingState,
        rowProcessingState,
        rowReader
);

코드 해설 — 중간 처리 계층 덕분에 단건·컬렉션·조인·캐시를 공통 방식으로 다룬다

Hibernate는 ResultSet을 직접 엔티티로 바꾸지 않고, 중간에 JdbcValues, RowReader, resultsConsumer 같은 처리 계층을 둡니다. 이 구조 덕분에 단건 조회, 컬렉션 조회, 조인 결과, 캐시 연동 같은 다양한 케이스를 공통 방식으로 다룰 수 있습니다.


설계 의도 — 행 데이터를 객체 그래프로 바꾸는 일을 독립 계층에 둔다

SQL 실행과 결과 매핑을 분리해 ORM의 핵심 책임인 “행 데이터 → 객체 그래프 변환”을 독립적으로 처리하기 위한 구조입니다. 이 단계가 JPA와 단순 JDBC 템플릿의 큰 차이 중 하나입니다.


다음 단계 연결 — 15-J6 매핑된 엔티티가 서비스로 돌아가는 과정으로 이어진다

다음 문서 15-J6에서는 매핑된 엔티티가 SimpleJpaRepository를 거쳐 서비스로 어떻게 돌아가는지 정리합니다.

← 이전: 15-J4. DB → EntityManager | 다음: 15-J6. JpaRepository → Service