You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Stringsql = "update item set item_name=?, price=?, quantity=? where id=?";
template.update(sql,
itemName,
price,
quantity,
itemId);
여기서는 itemName, price, quantity 가 SQL 에 있는 ? 에 순서대로 바인딩 된다.
순서만 잘 지키면 문제가 될 것이 없다. 그러나 문제는 변경 시점에 발생한다.
누군가 price ,quantity 의 순서를 변경했을 때
Stringsql = "update item set item_name=?, quantity=?, price=? where id=?";
template.update(sql,
itemName,
price,
quantity,
itemId);
이렇게 되면 item_name=itemName, quantity=price, price=quantity
결과적으로 price 와 quantity 가 바뀌는 심각한 문제가 발생한다. 실무에서는 파라미터가 10~20개가 넘어가는 일도 아주 많기에 미래에 필드를 추가하거나 수정하면서 이런 문제가 충분히 발생할 수 있다.
버그 중에서 가장 고치기 힘든 버그는 데이터베이스에 데이터가 잘못 들어가는 버그이다. 코드만 고치는 수준이 아니라 데이터베이스의 데이터를 복구해야 하기 때문에 버그를 해결하는데 들어가는 리소스가 어마어마하다.
**개발을 할 때는 코드를 몇 줄 줄이는 편리함도 중요하지만, 모호함을 제거해서 코드를 명확하게 만드는 것이 유지보수 관점에서 매우 중요하다. **
이름 지정 바인딩
JdbcTemplate은 이러한 문제를 보완하기 위해 NamedParameterJdbcTemplate 라는 이름을 지정해서 파라미터를 바인딩 하는 기능을 제공한다.
JdbcTemplateItemRepositoryV2 는 ItemRepository 인터페이스를 구현했다.
this.template = new NamedParameterJdbcTemplate(dataSource);
NamedParameterJdbcTemplate 도 내부에 dataSource 가 필요하다.
JdbcTemplateItemRepositoryV2 생성자를 보면 의존관계 주입은 dataSource 를 받고 내부에서 NamedParameterJdbcTemplate 을 생성해서 가지고 있다. 스프링에서는 JdbcTemplate 관련 기능을 사용할 때 관례상 이 방법을 많이 사용한다.
물론 NamedParameterJdbcTemplate 을 스프링 빈으로 직접 등록하고 주입받아도 된다.
BeanPropertySqlParameterSource 를 항상 사용할 수 있는 것은 아니다.
예를 들어 update() 에서는 SQL에 :id 를 바인딩 해야 하는데, update() 에서 사용하는 ItemUpdateDto 에는 itemId 가 없다. 따라서 BeanPropertySqlParameterSource 를 사용할 수 없고, 대신에 MapSqlParameterSource 를 사용했다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
1️⃣ JdbcTemplate - 이름 지정 파라미터1
순서대로 바인딩
JdbcTemplate 을 기본으로 파라미터를 순서대로 바인딩한다.
여기서는
itemName,price,quantity가SQL에 있는 ? 에 순서대로 바인딩 된다.순서만 잘 지키면 문제가 될 것이 없다. 그러나 문제는 변경 시점에 발생한다.
누군가
price,quantity의 순서를 변경했을 때이렇게 되면
item_name=itemName, quantity=price, price=quantity결과적으로
price와quantity가 바뀌는 심각한 문제가 발생한다. 실무에서는 파라미터가 10~20개가 넘어가는 일도 아주 많기에 미래에 필드를 추가하거나 수정하면서 이런 문제가 충분히 발생할 수 있다.버그 중에서 가장 고치기 힘든 버그는 데이터베이스에 데이터가 잘못 들어가는 버그이다. 코드만 고치는 수준이 아니라 데이터베이스의 데이터를 복구해야 하기 때문에 버그를 해결하는데 들어가는 리소스가 어마어마하다.
**개발을 할 때는 코드를 몇 줄 줄이는 편리함도 중요하지만, 모호함을 제거해서 코드를 명확하게 만드는 것이 유지보수 관점에서 매우 중요하다. **
이름 지정 바인딩
JdbcTemplate은 이러한 문제를 보완하기 위해
NamedParameterJdbcTemplate라는 이름을 지정해서 파라미터를 바인딩 하는 기능을 제공한다.JdbcTemplateItemRepositoryV2는ItemRepository인터페이스를 구현했다.this.template = new NamedParameterJdbcTemplate(dataSource);NamedParameterJdbcTemplate도 내부에dataSource가 필요하다.JdbcTemplateItemRepositoryV2생성자를 보면 의존관계 주입은dataSource를 받고 내부에서NamedParameterJdbcTemplate을 생성해서 가지고 있다. 스프링에서는JdbcTemplate관련 기능을 사용할 때 관례상 이 방법을 많이 사용한다.NamedParameterJdbcTemplate을 스프링 빈으로 직접 등록하고 주입받아도 된다.save()
SQL 에서 다음과 같이 ? 대신에
:파라미터이름을 받는 것을 확인할 수 있다.추가로
NamedParameterJdbcTemplate은 데이터베이스가 생성해주는 키를 매우 쉽게 조회하는 기능도 제공해준다.2️⃣ JdbcTemplate - 이름 지정 파라미터2
이름 지정 파라미터
파라미터를 전달하려면 Map 처럼 key, value 데이터 구조를 만들어서 전달해야 한다.
key 는
:파라미터이름으로 지정한, 파라미터의 이름이고,value는 해당 파라미터의 값이 된다.아래 코드를 보면 이렇게 만든 파라미터(
param) 을 전달하는 것을 확인할 수 있다.template.update(sql, param, keyHolder);이름 지정 바인딩에서 자주 사용하는 파라미터의 종류는 크게 3가지가 있다.
MapSqlParameterSourceMapSqlParameterSourceBeanPropertySqlParameterSource1. Map
Map을 사용한다.findById()코드에서 확인할 수 있다.2. MapSqlParameterSource
Map 과 유사한데 , SQL 타입을 지정할 수 있는 등 SQL 에 좀 더 특화된 기능을 제공한다.
SqlParameterSource인터페이스의 구현체이다.MapSqlParameterSource는 메서드체인을 통해 편리한 사용법도 제공한다.update()코드에서 확인할 수 있다.3. BeanPropertySqlParameterSource
자바빈 프로퍼티 규약을 통해서 자동으로 파라미터 객체를 생성한다.
예 )
getXxx() -> xxx, getItemName() -> itemName예를 들어
getItemName(),getPrice()가 있으면 다음과 같은 데이터를 자동으로 만들어낸다.key=itemName, value=상품명 값key=price, value=가격 값SqlParameterSource인터페이스의 구현체이다.save(),findAll()코드에서 확인할 수 있다.BeanPropertySqlParameterSource를 항상 사용할 수 있는 것은 아니다.update()에서는 SQL에:id를 바인딩 해야 하는데,update()에서 사용하는ItemUpdateDto에는itemId가 없다. 따라서BeanPropertySqlParameterSource를 사용할 수 없고, 대신에MapSqlParameterSource를 사용했다.BeanPropertyRowMapper
한가지 더 변화된 부분은
BeanPropertyRowMapper를 사용한 것이다.BeanPropertyRowMapper는ResultSet의 결과를 받아서 자바빈 규약에 맞추어 데이터를 변환한다.예를 들어 데이터베이스에서 조회한 결과가
select id, price라고 하면 다음과 같은 코드를 작성해준다.데이터베이스에서 조회한 결과 이름을 기반으로
setId(),setPrice()처럼 자바빈 프로퍼티 규약에 맞춘 메서드를 호출하는 것이다.별칭
select item_name의 경우setItem_name()이라는 메서드가 없기에 개발자가 조회 SQL을select item_name as itemName으로 고치면 된다.별칭 as 를 사용해서 SQL 조회 결과의 이름을 변경하는 것이다.
이렇게 데이터베이스 컬럼 이름과 객체의 이름이 다를 때 별칭(as) 을 사용해서 문제를 많이 해결한다.
JdbcTemplate은 물론이고,MyBatis같은 기술에서도 자주 사용된다.관례의 불일치
3️⃣ JdbcTemplate - 이름 지정 파라미터3
4️⃣ JdbcTemplate - SimpleJdbcInsert
5️⃣ JdbcTemplate 기능 정리
All reactions