✔ JdbcTemplate
: SQL을 직접 사용하는 경우에 스프링이 제공하는 JdbcTemplate 은 아주 좋은 선택지다. JdbcTemplate 은 JDBC 를 매우 편리하게 사용할 수 있게 도와준다.
• 장점
- 설정의 편리함
: 별도의 복잡한 설정 없이 바로 사용할 수 있다.
- 반복 문제 해결
: JdbcTemplate 은 템플릿 콜백 패턴을 사용해서, JDBC 를 직접 사용할 때 발생하는 대부분의 반복 작업을 대신 처리해준다. 개발자는 SQL을 작성하고, 전달할 파라미터를 정의하고, 응답 값을 매핑하기만 하면 된다.
• 단점
- 동적 SQL을 해결하기 어렵다.
✔ JdbcTemplate 설정하기
• build.gradle 의 dependencies 에 추가해야 할 것
//H2 데이터베이스 추가
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//테스트에서 lombok 사용
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
• application.properties 에 추가해야 할 것
✔ ITEM table 만들기
위와 같은 열을 가진 ITEM table 을 만든다.
✔ JdbcTemplate 적용1
: JdbcTemplate 은 데이터소스(dateSource)가 필요하다.
① save() : 데이터를 저장한다.
◽ template.update() : 데이터를 변경할 때는 update() 를 사용하면 된다.
- INSERT , UPDATE , DELETE SQL에 사용한다.
- template.update() 의 반환 값은 int 인데, 영향 받은 로우 수를 반환한다.
◽ 데이터를 저장할 때 PK 생성에 identity (auto increment) 방식을 사용하기 때문에, PK인 ID 값을 개발자가 직접 지정하는 것이 아니라 비워두고 저장해야 한다. 그러면 데이터베이스가 PK인 ID를 대신 생성해준다.
② update() : 데이터를 업데이트 한다.
◽ template.update() : 데이터를 변경할 때는 update() 를 사용하면 된다.
- ? 에 바인딩할 파라미터를 순서대로 전달하면 된다.
- 반환 값은 해당 쿼리의 영향을 받은 로우 수 이다. 여기서는 where id=? 를 지정했기 때문에 영향 받은 로우수는 최대 1개이다.
③ findById() : 데이터를 하나 조회한다.
◽ template.queryForObject()
- 결과 로우가 하나일 때 사용한다.
- RowMapper 는 데이터베이스의 반환 결과인 ResultSet 을 객체로 변환한다.
- 결과가 없으면 EmptyResultDataAccessException 예외가 발생한다.
- 결과가 둘 이상이면 IncorrectResultSizeDataAccessException 예외가 발생한다.
◽ ItemRepository.findById() 인터페이스는 결과가 없을 때 Optional 을 반환해야 한다. 따라서 결과가 없으면 예외를 잡아서 Optional.empty 를 대신 반환하면 된다.
④ findAll(): 데이터를 리스트로 조회한다. 그리고 검색 조건으로 적절한 데이터를 찾는다.
◽ template.query()
- 결과가 하나 이상일 때 사용한다.
- RowMapper 는 데이터베이스의 반환 결과인 ResultSet 을 객체로 변환한다.
- 결과가 없으면 빈 컬렉션을 반환한다.
✔ JdbcTemplate 적용2 - 동적 쿼리 문제
: 결과를 검색하는 `findAll()` 에서 어려운 부분은 사용자가 검색하는 값에 따라서 실행하는 SQL이 동적으로 달라져야 한다는 점이다.
◽ 검색 조건이 없음
select id, item_name, price, quantity from item
◽ 상품명( itemName )으로 검색
select id, item_name, price, quantity from item
where item_name like concat('%',?,'%')
◽ 최대 가격( maxPrice )으로 검색
select id, item_name, price, quantity from item
where price <= ?
◽ 상품명( itemName ), 최대 가격( maxPrice ) 둘다 검색
select id, item_name, price, quantity from item
where item_name like concat('%',?,'%')
and price <= ?
✔ JdbcTemplate - 이름 지정 파라미터
① Map
: 단순히 Map을 사용한다.
Map<String, Object> param = Map.of("id", id);
Item item = template.queryForObject(sql, param, itemRowMapper());
② MapSqlParameterSource
: Map과 유사한데 SQL 타입을 지정할 수 있는 등 SQL 에 좀 더 특화된 기능을 제공한다.
SqlParameterSource 인터페이스의 구현체이다.
MapSqlParameterSource 는 메서드 체인을 통해 편리한 사용법도 제공한다.
SqlParameterSource param = new MapSqlParameterSource()
.addValue("itemName", updateParam.getItemName())
.addValue("price", updateParam.getItemName())
.addValue("quantity", updateParam.getQuantity())
.addValue("id", itemId);
template.update(sql, param);
③ BeanPropertySqlParameterSource
: 자바빈 프로퍼티 규약을 통해서 자동으로 파라미터 객체를 생성한다.
예) getXxx() -> xxx() , getItemName -> itemName
예를 들어서 getItemName(), getPrice() 가 있으면 다음과 같은 데이터를 자동으로 만들어낸다.
key=itemName, value=상품명 값
key=price, value=가격 값
SqlParameterSource 인터페이스의 구현체이다.
SqlParameterSource param = new BeanPropertySqlParameterSource(item);
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(sql, param, keyHolder);
여기서 보면 BeanPropertyParameterSource 가 많은 것을 자동화 해주기 때문에 가장 좋아보이지만,
BeanPropertyParameterSource 를 항상 사용할 수 있는 것은 아니다.
예를 들어서 update() 에서는 SQL 에 :id 를 바인딩 해야 하는데, update() 에서 사용하는 ItemUpdateDto 에는 itemId 가 없다. 따라서 BeanPropertyParameterSource 를 사용할 수 없고, 대신에 MapSqlParameterSource 를 사용했다.
④ BeanPropertyRowMapper
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;
};
}
이걸
private RowMapper<Item> itemRowMapper() {
return BeanPropertyRowMapper.newInstance(Item.class); // camel 변환 지원
}
이렇게 바꿀 수 있다.
인프런 ) 스프링DB 2편 - 데이터 접근 활용 기술 (김영한)
'Back > DB' 카테고리의 다른 글
[DB] JPA (0) | 2023.05.12 |
---|---|
[DB] MyBatis (0) | 2023.05.09 |
[DB] H2 데이터베이스 설치 (0) | 2023.05.04 |
[DB] Sharding (샤딩) (0) | 2023.04.27 |
[DB] Replication (복제) (0) | 2023.04.27 |