수업 복습

JDBCTemplate + RowMapper

_김영인 2026. 1. 28. 12:49

 

1) DB가 바뀌면 update, 읽어오면 query 계열

 

먼저 잡은 기준은 다음 두 줄이다.

    • DB에 변화 (INSERT / UPDATE / DELETE)가 생기는 작업은 JdbcTemplate.update()를 사용한다.
    • DB를 읽어오는 SELECT는 반환이 필요하므로 queryForObject() 또는 query()를 사용한다. 특히 단건 (select one)은 queryForObject()를 사용한다.

 

여기서 주의할 점은 “select는 다 queryForObject”가 아니라 단건은 queryForObject, 리스트는 query로 나뉜다는 점이다.

 


 

2) 반환 (매핑)을 직접 지정해야 해서 SELECT가 더 까다f롭다

 

SELECT 파트로 넘어가면서 강조한 포인트는 ‘반환이 있다’는 점이다.

  • CUD는 결과를 int (영향받은 행 수)로 받아서 성공 / 실패 판단만 하면 되지만
  • SELECT는 DB에서 가져온 결과를 DTO로 만들어서 반환해야 한다.

그래서 “어떻게 반환할지” 정보가 필요하고 그 역할을 하는 클래스가 필요하다고 설명한다.


 

3) queryForObject() 인자 구성: “반환 정보 (매핑) + 파라미터”

 

queryForObject()는 update()와 인자 구성이 다르다고 정리한다.

  • update()는 보통 SQL + 파라미터
  • queryForObject()는 어떻게 반환할지(매핑) + 파라미터가 추가로 필요

“SELECT류는 반환이 있으니까 어떻게 반환할지를 먼저 쓰고 그 다음 파라미터를 넣는다”라고 설명한다.

그리고 마지막 정리에서 더 명확하게 문장으로 고정한다.

    • 첫 번째 인자 = SQL
    • 중간 인자 = 어떻게 반환할지
    • 마지막 인자 = 파라미터 전달

 

4) 컬럼 → DTO 필드 매핑을 직접 지정해야 한다

 

    • “어떤 컬럼이 어떤 멤버 변수인지 짚어줘야 된다.”

DB에서 가져온 결과는 자동으로 DTO가 되지 않는다.
ResultSet에서 꺼낸 컬럼 값을 DTO의 어떤 필드에 넣을지를 사람이 코드로 지정해야 한다.


 

5) 그 역할을 하는 클래스가 RowMapper이고 “강제로 (규칙대로) 만들기 위해 implements 한다”

 

“그 이야기를 해줄 클래스”를 만들고 그걸 로우매퍼 (RowMapper) 라고 부른다고 정리한다.

그리고 중요한 포인트가 이어진다.

    • “그냥 막 만들면 안 되고 JDBC 템플릿이 쓸 수 있게끔 줘야 된다.”
    • “강제해야 한다.”

그래서 수업에서는 RowMapper<BoardDTO>를 implements 해서 JdbcTemplate이 요구하는 형태로 만들게 된다.

“메서드 강제가 필요하므로 인터페이스를 추가하여 구현하면 된다”고 정리한다.


 

6) PlusBoardDAO에서 단건 / 리스트 조회 구현

  • 단건 (select one) → queryForObject()
  • 리스트 (select all) → query()
public BoardDTO getBoard(BoardDTO dto) {
    return jdbcTemplate.queryForObject(SELECT_ONE, new BoardRowMapper(), dto.getBid());
}

public List<BoardDTO> getBoardList(BoardDTO dto){
    return jdbcTemplate.query(SELECT_ALL, new BoardRowMapper());
}

 


 

7) BoardRowMapper에서 “컬럼 → DTO 필드”를 직접 지정한다

class BoardRowMapper implements RowMapper<BoardDTO> {

    @Override
    public BoardDTO mapRow(ResultSet rs, int rowNum) throws SQLException {
        BoardDTO data = new BoardDTO();
        data.setBid(rs.getInt("BID"));
        data.setTitle(rs.getString("TITLE"));
        data.setWriter(rs.getString("WRITER"));
        data.setContent(rs.getString("CONTENT"));
        data.setRegdate(rs.getDate("REGDATE"));
        data.setCnt(rs.getInt("CNT"));
        return data;
    }
}

 

PlusBoardDAO 아래에 BoardRowMapper를 같은 파일에 두었지만 내부 클래스가 아니라 그냥 별도의 클래스를 같은 파일에 둔 형태이다.


8) 리스트 반환은 query()를 쓴다 (파라미터 없으면 안 넣는다).

    • “리스트 반환할 때는 query라는 메서드를 쓴다.”
    • “select all이고 파라미터 줄 게 없으면 안 쓴다.”
    • “어떻게 반환할지만 알려주면 알아서 리스트 반환해 준다.”

 

10) RowMapper는 하나만 있는 게 아니다: ResultSet (결과 모양)이 다르면 RowMapper도 여러 개

 

조회 결과 컬럼 구성이 달라져서 DTO에 채워 넣는 방식이 달라지면 그에 맞는 RowMapper를 별도로 만든다.


 

11) 콘솔 실행에서 단건 조회 전에 조회수 증가 (update)를 먼저 호출한다

 

 “2. 1개출력”을 선택했을 때 흐름이 이렇게 되어 있다.

  1. bid 입력
  2. updateBoard(dto) 호출 (조회수 증가)
  3. getBoard(dto) 호출 (단건 조회 후 출력)
else if(command == 2) {
    System.out.print("출력할 글 번호 입력 >> ");
    BoardDTO dto = new BoardDTO();
    dto.setBid(sc.nextInt());
    boardService.updateBoard(dto);
    System.out.println(boardService.getBoard(dto));
}

 

 

    • DB 변경 (CUD): update() 사용
    • 단건 조회 (select one): queryForObject() 사용
    • 리스트 조회 (select all): query() 사용, 파라미터 없으면 생략
    • SELECT는 반환이 있으므로 “컬럼 → DTO 필드 매핑”을 직접 지정해야 한다
    • 그 매핑 규칙을 담는 클래스가 RowMapper이고 JdbcTemplate이 쓰게 하려면 인터페이스 구현 (강제)이 필요하다
    • 결과 모양이 다르면 RowMapper도 여러 개가 될 수 있다