Spring JDBC(4) JdbcTemplate을 더 잘 사용해보자

오잉·2023년 4월 14일
0

SPRING

목록 보기
7/15

1. NamedParameterJdbcTemplate

JdbcTemplate은 기본적으로 SQL쿼리 안에서 ?로 표현된 파라미터를 순서대로 바인딩 한다.

String sql = "update item set item_name=?, price=?, quantity=? where id=?";
template.update(sql,
          itemName,
          price,
          quantity,
          itemId);

파라미터를 순서대로 바인딩 하는 것은 편리하기는 하지만, 순서가 맞지 않아서 버그가 발생할 수도 있으므로 주의해서 사용해야 한다.

JdbcTemplate에서는 이런 문제를 보완하기 위해 NamedParameterJdbcTemplate 라는것이 등장했다.
이를 사용하면 Sql 쿼리 안에서 파라미터를 :productName과 같이 이름을 붙여서 지정할 수 있다.
따라서 여러 개의 파리미터가 있는 쿼리를 실행할 때에는 기본 JdbcTemplate보다 NamedParameterJdbcTemplate을 사용하는 것이 좋다.

기본 구조

:productName과 같이 파라미터에 이름을 붙여서 지정한다.

String sql = "update item " +
             "set item_name=:itemName, price=:price, quantity=:quantity " +
             "where id=:id";
SqlParameterSource param = new MapSqlParameterSource()
             .addValue("itemName", updateParam.getItemName()) 
             .addValue("price", updateParam.getPrice()) 
             .addValue("quantity", updateParam.getQuantity()) 
             .addValue("id", itemId);
template.update(sql, param);

파라미터 전달 방식

파라미터를 전달하려면 Map처럼 key, value 데이터 구조를 만들어서 전달해야 한다.
key는 :파리이터이름 으로 지정한 파라미터의 이름
value는 해당 파라미터의 값

1) Map

String sql = "select id, item_name, price, quantity from item where id = :id";
Map<String, Object> param = Map.of("id", id);
Item item = template.queryForObject(sql, param, itemRowMapper());
  • 단순히 Map을 사용한다

2) MapSqlParameterSource

String sql = "update item " +
             "set item_name=:itemName, price=:price, quantity=:quantity " +
             "where id=:id";
SqlParameterSource param = new MapSqlParameterSource() 
       .addValue("itemName", updateParam.getItemName()) 
       .addValue("price", updateParam.getPrice()) 
       .addValue("quantity", updateParam.getQuantity()) 
       .addValue("id", itemId);
template.update(sql, param);
  • Map과 유사한데, SQL 타입을 지정할 수 있는 등 SQL에 좀 더 특화된 기능을 제공한다.
  • SqlParameterSource 인터페이스의 구현체이다.
  • 메서드 체인 형식으로 파라미터를 정의할 수 있다.

3) BeanPropertySqlParameterSource

String sql = "insert into item (item_name, price, quantity) " +
             "values (:itemName, :price, :quantity)";
SqlParameterSource param = new BeanPropertySqlParameterSource(item);
template.update(sql, param, keyHolder);
  • 자바빈 프로퍼티 규약을 통해서 자동으로 파라미터 객체를 생성한다.
    ex) ( getXxx() -> xxx, getItemName() -> itemName )
  • 즉, getter/setter가 있는 bean 객체로부터 파라미터를 추출한다.
  • 예를 들어서 getItemName() , getPrice() 가 있으면 다음과 같은 데이터를 자동으로 만들어낸다.
    • key=itemName, value=상품명 값
    • key=price, value=가격 값
  • SqlParameterSource 인터페이스의 구현체이다.
  • 많은 것을 자동화 해주기 때문에 가장 좋아보이지만, 항상 사용할 수 있는 것은 아니다 (필요한 파라미터가 해당 bean에 없을 경우)

2. SimpleJdbcInsert

SimpleJdbcInsert 클래스를 활용하면 직접 Insert SQL을 쓰지 않고도 DB에 데이터를 저장할 수 있다.

사용법

DB 컬럼명과 객체의 속성명이 일치한다면 간편하게 DB에 데이터 1건을 입력할 수 있다.

SimpleJdbcInsertOperations insertion = new SimpleJdbcInsert(dataSource)
			.withTableName("item")
SqlParameterSource params = new BeanPropertySqlParameterSource(item);
insertion.execute(params);

auto_increment 경우

예를 들어 DB 스키마가 다음과 같은 경우, 데이터를 입력하는 시점에 DB에서 자동으로 값을 증가시켜 PK를 결정한다.

CREATE TABLE item (
	id INT IDENTITY NOT NULL PRIMARY KEY AUTO_INCREMENT,
	item_name VARCHAR(20) ,
	price INT(50),
	quantity INT(255)
);

이럴 때에는 usingGeneratedKeyColumns() 또는 executeAndReturnKey()를 사용하면 된다.

SimpleJdbcInsertOperations insertion = new SimpleJdbcInsert(dataSource)
          .withTableName("item")
          .usingGeneratedKeyColumns("id");
SqlParameterSource params = new BeanPropertySqlParameterSource(item);
Integer id = insertion.executeAndReturnKey(params).intValue();

JdbcTemplate을 편리하게 사용하기 위한 도구

  • RowMapper (반환값 타입 변환)
    • select의 반환값인 ResultSet에서 값을 추출하여 원하는 객체로 타입을 변환
    • BeanPropertyRowMapper (ResultSet -> Bean)
    • ColumnMapRowMapper (ResultSet -> Map)
  • NamedParameterJdbcTemplate (이름이 붙여진 파라미터가 들어간 SQL을 호출)
    • :productName과 같이 파라미터에 이름을 붙일 수 있다.
  • SqlParameterSource (SQL에 파라미터 전달)
    • BeanPropertyParameterSource (Bean 객체로 파라미터 전달)
    • MapSqlParameterSource (Map으로 파라미터 전달)
  • SimpleJdbcInsert : Insert 쿼리 자동 생성

참고
인프런 김영한님 스프링 DB 2편의 [섹션2. 스프링 JdbcTemplate]
https://github.com/benelog/spring-jdbc-tips/blob/master/spring-jdbc-core.md

profile
오잉이라네 오잉이라네 오잉이라네 ~

0개의 댓글