설정
# db 설정
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.username=sa
spring.datasource.password=
# sql 로그
logging.level.org.springframework.jdbc=debug
의존관계 주입
- JdbcTemplate는 DataSource가 필요하다
- 스프링 빈으로 등록하여 사용해도 됨
private final JdbcTemplate template;
public JdbcTemplateItemRepositoryV1(DataSource dataSource) {
this.template = new JdbcTemplate(dataSource);
}
데이터 변경
template.update()
INSERT , UPDATE , DELETE SQL에 사용한다.
- 반환 값은
int 인데, 영향 받은 로우 수를 반환한다.
String sql = "update item set item_name=?, price=?, quantity=? where id=?";
template.update(sql,
updateParam.getItemName(),
updateParam.getPrice(),
updateParam.getQuantity(),
itemId);
데이터 변경 - PK 자동생성
identity (auto increment) 방식같이 DB가 자동으로 PK을 생성하는 경우 사용
KeyHolder 사용
String sql = "insert into item(item_name, price, quantity) values (?,?,?)";
KeyHolder keyHolder = new GeneratedKeyHolder();
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);
long key = keyHolder.getKey().longValue();
item.setId(key);
return item;
데이터 조회 - 객체 변환
RowMapper 는 데이터베이스의 반환 결과인 ResultSet 을 객체로 변환한다
private RowMapper<Item> itemRowMapper() {
return ((rs, rowNum) -> {
Item item = new Item();
item.setId(rs.getLong("id"));
item.setItemName(rs.getString("item_name"));
item.setPrice(rs.getInt("price"));
item.setQuantity(rs.getInt("quantity"));
return item;
});
}
데이터 조회 - 단 건
template.queryForObject()
- 결과 로우가 하나일 때 사용한다
- 결과가 없으면
EmptyResultDataAccessException 예외가 발생한다.
- 결과가 둘 이상이면
IncorrectResultSizeDataAccessException 예외가 발생한다.
String sql = "select id, item_name, price, quantity from item where id=?";
try {
Item item = template.queryForObject(sql, itemRowMapper(), id);
return Optional.of(item);
} catch (EmptyResultDataAccessException e) {
return Optional.empty();
}
데이터 조회 - 여러 건
template.query()
- 결과가 하나 이상일 때 사용한다
- 결과가 없으면 빈 컬렉션을 반환한다.
String sql = "select id, item_name, price, quantity from item";
return template.query(sql, itemRowMapper());
데이터 조회 - 동적 쿼리
String itemName = cond.getItemName();
Integer maxPrice = cond.getMaxPrice();
String sql = "select id, item_name, price, quantity from item";
if (StringUtils.hasText(itemName) || maxPrice != null) {
sql += " where";
}
boolean andFlag = false;
List<Object> param = new ArrayList<>();
if (StringUtils.hasText(itemName)) {
sql += " item_name like concat('%',?,'%')";
param.add(itemName);
andFlag = true;
}
if (maxPrice != null) {
if (andFlag) {
sql += " and";
}
sql += " price <= ?";
param.add(maxPrice);
}
log.info("sql={}", sql);
return template.query(sql, itemRowMapper(), param.toArray());