참고
JdbcTemplate - 이름 지정 파라미터
NOTE
JdbcTemplate을 기본적으로 사용하면 파라미터를 순서대로 바인딩한다
String sql = "update item set item_name=?, price=?, quantity=? where id=?";
template.update(sql,
itemName,
price,
quantity,
itemId);
Java
복사
•
여기서는 itemName, price, quantity, id가 sql에 순서대로 바인딩된다.
•
그런데 문제는 파라미터 순서를 바꾸면 심각한 문제가 발생하게 된다. (다른게 맵핑됨)
quantity가 price로 , price가 quantity로 잘못 맵핑됨..
•
이러한 모호성을 제거하기 위해 NamedParameterJdbcTemplate를 사용한다!
NamedParameterJdbctemplate (이름 지정 바인딩)
NOTE
NamedParameterJdbctemplate는 파라미터를 바인딩 하는 기능을 제공한다
NamedParameterJdbctemplate 생성
private final NamedParameterJdbcTemplate template;
public JdbcTemplateItemRepositoryV2(DataSource dataSource) {
this.template = new NamedParameterJdbcTemplate(dataSource);
}
Java
복사
•
NamedParameterJdbctemplate는 JdbcTemplate와 동일한 형태로 생성됨
NamedParameterJdbctemplate 사용방법
// JdbcTemplate
String sql = "insert into item(item_name, price, quantity) values (?,?,?)";
template.update(connection -> {
PreparedStatement ps = connection.prepareStatement(sql, new String[]{"id"});
ps.setString(1, item.getItemName());
ps.setInt(2, item.getPrice());
ps.setInt(3, item.getQuantity());
return ps;}, keyHolder);
Java
복사
JdbcTemplate 사용방법
// NamedParameterJdbcTemplate
String sql = "insert into item(item_name, price, quantity) values (:itemName,:price,:quantity)";
BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(item);
template.update(sql, param, keyHolder);
Java
복사
NamedParameterJdbcTemplate 사용방법
•
JdbcTemplate는 파라미터 바인딩을 위해 ?를 사용하고, PreparedStatement에서 직접 세팅해주었다
•
NamedParameterJdbcTemplate는 PreparedStatement를 사용하는 대신, :[이름]을 지정하고 Parameter Map을 넘겨주는 방식으로 처리가 된다.
Parameter Map 구현방법 3가지
NOTE
Map
Map<String, Long> param = Map.of("id", id);
Item item = template.queryForObject(sql, param,itemRowMapper());
return Optional.of(item);
Java
복사
•
단순히 Map을 사용하면 된다.
BeanPropertySqlParameterSource (권장)
@Override
public List<Item> findAll(ItemSearchCond cond) {
...
SqlParameterSource param = new BeanPropertySqlParameterSource(cond);
...
}
Java
복사
•
BeanPropertySqlParameterSource에 DB에 넣을 객체(item)을 전달해준다
•
자바 빈 프로퍼티 규약을 통해서 자동으로 파라미터 객체 생성
◦
ex) getItemName() → itemName()
•
단 Dto에 없는 값이 있을경우에는, 사용이 불가능하다
MapSqlParameterSource
String sql = "update item set item_name=:itemName, price=:price, quantity=:quantity where id=:id";
//NamedParameterJdbcTemplate을 사용하면서 다음과 같이 해결함.
MapSqlParameterSource param = new MapSqlParameterSource()
.addValue("itemName", updateParam.getItemName())
.addValue("price", updateParam.getPrice())
.addValue("quantity", updateParam.getQuantity())
.addValue("id", itemId);
Java
복사
현재 DTO는 id가 존재하지 않는다
•
DTO에 없는 값을 등록할 때 유용한다.
SimpleJdbcInsert
NOTE
JdbcTemplate은 INSERT SQL을 직접 작성하지 않아도 되도록, ‘SimpleJdbcInsert’라는 기능을 제공한다.
SimpleJdbcInsert - 사용
NOTE
public class JdbcTemplateItemRepositoryV3 implements ItemRepository {
private final NamedParameterJdbcTemplate template;
private final SimpleJdbcInsert jdbcInsert;
public JdbcTemplateItemRepositoryV3(DataSource dataSource) {
this.template = new NamedParameterJdbcTemplate(dataSource);
this.jdbcInsert = new SimpleJdbcInsert(dataSource)
.withTableName("item")
.usingGeneratedKeyColumns("id");
//.usingColumns("item_name", "price", "quantitiy") // 생략가능
}
@Override
public Item save(Item item) {
SqlParameterSource param = new BeanPropertySqlParameterSource(item);
Number key = jdbcInsert.executeAndReturnKey(param);
item.setId(key.longValue());
return item;
}
Java
복사
사용 코드
•
withTableName : 데이터를 저장할 테이블 명을 지정
•
usingGeneratedKeyColumns : Key를 생성하는 PK컬럼명을 지정한다
•
usingColumns : INSERT SQL에 사용할 컬럼을 지정한다, 특정한 값만 저장하고 싶을 때 사용하며 생략이 가능함