Post

Spring 스프링 DB 2편 - 데이터 접근 활용 기술 - 2. 데이터 접근 기술 - 스프링 JdbcTemplate

2. 데이터 접근 기술 - 스프링 JdbcTemplate


JdbcTemplate 소개와 설정

  • SQL을 직접 사용하는 경우에 스프링이 제공하는 JdbcTemplate은 아주 좋은 선택지다. JdbcTemplate 은 JDBC를 매우 편리하게 사용할 수 있게 도와준다.

장점

  • 설정의 편리함
    • JdbcTemplate은 spring-jdbc 라이브러리에 포함되어 있는데, 이 라이브러리는 스프링으로 JDBC를 사용할 때 기본으로 사용되는 라이브러리이다. 그리고 별도의 복잡한 설정 없이 바로 사용할 수 있다.
  • 반복 문제 해결
    • JdbcTemplate은 템플릿 콜백 패턴을 사용해서, JDBC를 직접 사용할 때 발생하는 대부분의 반복 작업을 대신 처리해준다.
    • 개발자는 SQL을 작성하고, 전달할 파리미터를 정의하고, 응답 값을 매핑하기만 하면 된다.
    • 우리가 생각할 수 있는 대부분의 반복 작업을 대신 처리해준다.
      • 커넥션 획득
      • statement 를 준비하고 실행
      • 결과를 반복하도록 루프를 실행
      • 커넥션 종료, statement , resultset 종료
      • 트랜잭션 다루기 위한 커넥션 동기화
      • 예외 발생시 스프링 예외 변환기 실행

단점

  • 동적 SQL을 해결하기 어렵다.

JdbcTemplate 기능 정리

주요 기능

  • JdbcTemplate
    • 순서 기반 파라미터 바인딩을 지원한다.
  • NamedParameterJdbcTemplate
    • 이름 기반 파라미터 바인딩을 지원한다. (권장)
  • SimpleJdbcInsert
    • INSERT SQL을 편리하게 사용할 수 있다.
  • SimpleJdbcCall
    • 스토어드 프로시저를 편리하게 호출할 수 있다.

NamedParameterJdbcTemplate

  • save()
  • SQL에서 다음과 같이 ? 대신에 :파라미터이름 을 받는 것을 확인할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public Item save(Item item) {
    String sql = "insert into item (item_name, price, quantity) " +
 "values (:itemName, :price, :quantity)";
    
    SqlParameterSource param = new BeanPropertySqlParameterSource(item);
    KeyHolder keyHolder = new GeneratedKeyHolder();
    template.update(sql, param, keyHolder);
    
    Long key = keyHolder.getKey().longValue();
    item.setId(key);
    
    return item;
}
    

BeanPropertySqlParameterSource

  • 자바빈 프로퍼티 규약을 통해서 자동으로 파라미터 객체를 생성한다.
  • 예) ( getXxx() -> xxx, getItemName() -> itemName )
  • 예를 들어서 getItemName() , getPrice() 가 있으면 다음과 같은 데이터를 자동으로 만들어낸다.
  • key=itemName, value=상품명 값
  • key=price, value=가격 값
  • SqlParameterSource 인터페이스의 구현체이다.

별칭

  • 그런데 select item_name 의 경우 setItem_name() 이라는 메서드가 없기 때문에 골치가 아프다.
  • 이런 경우 개발자가 조회 SQL을 다음과 같이 고치면 된다.
  • select item_name as itemName
  • 별칭 as 를 사용해서 SQL 조회 결과의 이름을 변경하는 것이다. 실제로 이 방법은 자주 사용된다. 특히 데이터베이스 컬럼 이름과 객체 이름이 완전히 다를 때 문제를 해결할 수 있다. 예를 들어서 데이터베이스에는 member_name 이라고 되어 있는데 객체에 username 이라고 되어 있다면 다음과 같이 해결할 수 있다.
  • select member_name as username
  • 이렇게 데이터베이스 컬럼 이름과 객체의 이름이 다를 때 별칭( as )을 사용해서 문제를 많이 해결한다.
  • JdbcTemplate 은 물론이고, MyBatis 같은 기술에서도 자주 사용된다.

관례의 불일치

  • 자바 객체는 카멜( camelCase ) 표기법을 사용한다. itemName 처럼 중간에 낙타 봉이 올라와 있는 표기법이다.
  • 반면에 관계형 데이터베이스에서는 주로 언더스코어를 사용하는 snake_case 표기법을 사용한다.
  • item_name 처럼 중간에 언더스코어를 사용하는 표기법이다.
  • 이 부분을 관례로 많이 사용하다 보니 BeanPropertyRowMapper 는 언더스코어 표기법을 카멜로 자동 변환해준다.
  • 따라서 select item_name 으로 조회해도 setItemName() 에 문제 없이 값이 들어간다.

  • 정리하면 snake_case 는 자동으로 해결되니 그냥 두면 되고, 컬럼 이름과 객체 이름이 완전히 다른 경우에는 조회 SQL에서 별칭을 사용하면 된다.

정리

  • 실무에서 가장 간단하고 실용적인 방법으로 SQL을 사용하려면 JdbcTemplate을 사용하면 된다.
  • JPA와 같은 ORM 기술을 사용하면서 동시에 SQL을 직접 작성해야 할 때가 있는데, 그때도 JdbcTemplate을 함께 사용하면 된다.
  • 그런데 JdbcTemplate의 최대 단점이 있는데, 바로 동적 쿼리 문제를 해결하지 못한다는 점이다. 그리고 SQL을 자바 코드로 작성하기 때문에 SQL 라인이 코드를 넘어갈 때 마다 문자 더하기를 해주어야 하는 단점도 있다.
  • 동적 쿼리 문제를 해결하면서 동시에 SQL도 편리하게 작성할 수 있게 도와주는 기술이 바로 MyBatis 이다.

References: 김영한 - [스프링 DB 2편 - 데이터 접근 활용 기술]
This post is licensed under CC BY 4.0 by the author.