ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스프링 DB 데이터접근 기술 - 스프링 JdbcTemplate
    Spring-Boot/스프링 DB 2편 - 데이터 접근 기술 2022. 9. 5. 18:43

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

     

    * 장점 *

    - 설정의 편리함

        ㆍJdbcTemplate은 `spring-jdbc` 라이브러리에 포함되어 있는데, 이 라이브러리는 스프링으로 JDBC를 사용할 때 

           기본으로 사용되는 라이브러리이다.

        ㆍ그리고 별도의 복잡한 설정 없이 바로 사용할 수 있다

    - 반복 문제 해결

        ㆍJdbcTemplate은 템플릿 콜백 패턴을 사용해서, JDBC를 직접 사용할 때 발생하는 대부분의 반복 작업을 대신 처리

        ㆍ개발자는 SQL을 작성하고, 전달할 파라미터를 정의하고, 응답 값을 매핑하기만 하면 된다

        ㆍ우리가 생각할 수 있는 대부분의 반복 작업을 대신 처리해준다

             ㆍ커넥션 획득

             ㆍ`statement`를 준비하고 실행

             ㆍ결과를 반복하도록 루프를 실행

             ㆍ커넥션 종료, `statement`, `resultset` 종료

             ㆍ트랜잭션 다루기 위한 커넥션 동기화

             ㆍ예외 발생시 스프링 예외 변환기 실행

     

    * 단점 *

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

     

    * 로그 추가

    ``` properties
    
    #jdbcTemplate sql log
    logging.level.org.springframework.jdbc=debug

     

     

    * 개발을 할 때는 코드를 몇줄 줄이는 편리함도 중요하지만, 모호함을 제거해서 코드를 명확하게 만드는 것이 유지보수 관점에서 매우 중요하다 *

     

    이름 지정 바인딩

    - JdbcTemplate은 이런 문제를 보완하기 위해 `NamedParameterJdbcTemplate` 라는 이름을 지정해서 파라미터를 바인딩하는 기능을 제공한다.

    - 파라미터를 전달하려면 `Map`처럼 `key`, `value` 데이터 구조를 만들어서 전달해야 한다

        ㆍ여기서 `key`는 `:파라미터이름` 으로 지정한 파라미터 이름이고, `value`는 파라미터의 값이 된다.

     

    template.update(sql, param, keyHolder);

    - 다음 코드를 보면 param으로 전달하는 것을 확인

     

    - 이름 지정 바인딩에서 자주 사용하는 파라미터 종류 3가지

        ㆍMap

        ㆍSqlParameterSource

             ㆍMapSqlParameterSource

             ㆍBeanPropertySqlParameterSource

     

    * 1. Map *

    - 단순히 `Map`을 사용

    Map<String, Object> param = Map.of("id", id);
    Item item = template.queryForObject(sql,param, itemRowMapper());

     

    * 2. MapSqlParameterSource *

    - Map 과 유사한데, SQL 타입을 지정할 수 있는 등 SQL에 좀 더 특화된 기능을 제공

    - SqlParameterSource 인터페이스의 구현체

    - MapSqlParameterSource 는 메서드 체인을 통해 편리한 사용법도 제공

    SqlParameterSource param = new MapSqlParameterSource()
                    .addValue("itemName", updateParam.getItemName())
                    .addValue("price", updateParam.getPrice())
                    .addValue("quantity", updateParam.getQuantity())
                    .addValue("id", itemId);
    
    template.update(sql, param);

     

    * 3. BeanPropertySqlParameterSource *

    - 자바빈 프로퍼티 규약을 통해서 자동으로 파라미터 객체를 생성한다

        ㆍ예 ) getXxx() → xxx()

    - SqlParameterSource 인터페이스의 구현체이다

    SqlParameterSource param = new BeanPropertySqlParameterSource(item);
    
    KeyHolder keyHolder = new GeneratedKeyHolder();
    template.update(sql, param, keyHolder);

    - BeanPropertySqlParameterSource 가 많은 것을 자동화 해주기 때문에 좋아보이지만 dto에 값이 없으면 사용할 수 없다.

     

    private RowMapper<Item> itemRowMapper() {
            return BeanPropertyRowMapper.newInstance(Item.class);   // camel 변환 지원
    }

    - `BeanPropertyRowMapper`는 `ResultSet`의 결과를 받아서 자바빈 규약에 맞추어 데이터를 변환

    - 데이터베이스에서 조회한 결과 이름을 기반으로 `setId()`, `setPrice()`처럼 자바빈 프로퍼티 규약에 맞춘 메서드를 호출

     

    * 별칭 *

    - 그런데 `select item_name`의 경우 `setItem_name()` 이라는 메서드가 없기에 골치아프다

    - 이런 경우 개발자가 조회 SQL을 다음과 같이 고치면 된다.

        ㆍ`select item_name as itemName`

    - 별칭 `as`를 사용해서 SQL 조회 결과의 이름을 변경하는 것이다.

    - 이렇게 데이터베이스 컬럼 이름과 객체의 이름이 다를 때 별칭(`as`)을 사용해서 문제를 많이 해결한다.

        ㆍ`JdbcTemplate`은 물론이고 `MyBatis`같은 기술에서도 자주 사용

     

    * 관례의 불일치 *

    - 자바 객체는 카멜표기법을 사용한다.

    - 반면에 관계형 데이터베이스에서는 주로 언더스코어를 사용하는 스네이크표기법을 사용한다.

    - `BeanPropertyRowMapper`는 언더스코어 표기법을 카멜로 자동 변환해준다.

     

    * SimpleJdbcInsert *

    this.jdbcInsert = new SimpleJdbcInsert(dataSource)
            .withTableName("item")
            .usingGeneratedKeyColumns("id");
    //                .usingColumns("item_name","price","quantity");    // 생략가능

    - `withTableName` : 데이터를 저장할 테이블 명을 지정한다.

    - `usingGeneratedKeyColumns` : key를 생성하는 PK 컬럼명을 지정

    - `usingColumns` : INSERT SQL에 사용할 컬럼을 지정한다. 특정 값만 저장하고 싶을 때 사용, 생략 가능

     

    - `SimpleJdbcInsert`는 생성 시점에 데이터베이스 테이블의 메타 데이터를 조회한다

        ㆍ따라서 어떤 컬럼이 있는지 확인 가능하기에 `usingColumns` 생략 가능


    JdbcTemplate 기능 정리

    - JdbcTemplate

        ㆍ순서 기반 파라미터 바인딩을 지원

    - NamedParameterJdbcTemplate

        ㆍ이름 기반 파라미터 바인디을 지원( 권장 )

    - SimpleJdbcInsert

        ㆍINSERT SQL을 편리하게 사용할 수 있다

    - SimpleJdbcCall

        ㆍ스토어드 프로시저를 편리하게 호출할 수 있다.

     

    * 정리 *

    - JdbcTemplate의 최대 단점이 바로 동적 쿼리 문제를 해결하지 못한다는 점이다.

    - SQL을 자바 코드로 작성하기 때문에 SQL라인이 코드를 넘어갈 때마다 문자 더하기를 해주어야 하는 단점도 있다.

     

    → 동적 쿼리 문제를 해결하면서 동시에 SQL도 편리하게 작성할 수 있게 도와주는 기술이 바로 MyBatis 이다.

    댓글

Designed by Tistory.