인프런의 김영한님의 강의 스프링 DB 2편 - 데이터 접근 활용 기술을 학습하며 정리한 글입니다.
스프링 DB 2편 - 데이터 접근 활용 기술 (인프런)
JDBC Template란?
JDBC Template는 꼭 스프링에서만 사용 할 수 있는것은 아니고 의존성만 추가한다면 사용할 수 있는 JDBC를 매우 편리하게 사용 할 수 있게 도와주는 라이브러리다.
장점
- 설정의 편리함
-> 스프링 사용시 spring-jdbc 라이브러리에 포함되어 있으므로 의존성만 추가한다면 별도의 복잡한 설정 없이 바로 사용가능하다. - 반복문제 해결 ->템플릿 콜백 패턴을 사용하여, JDBC를 직접 사용할 때 발생하는 대부분의 반복 작업을 대신처리해줌
- SQL을 작성하고, 전달할 파라미터와 응답값 매핑만 하면 된다.
- 커넥션 획득, statement를 준비 & 실행, 결과 반복 루프, 커넥션 종료, statement, resultset 종료
- 트랜잭션을 다루기 위한 커넥션 동기화
- 예외 발생시 스프링 예외 변환기 실행
단점
- 동적 SQL 처리가 힘듦
주요 기능
JdbcTemplate이 제공하는 주요 기능은 다음과 같습니다.
- JdbcTemplate
- 순서 기반 파라미터 바인딩 지원
- NamedParameterJdbcTemplate
- 이름 기반 파라미터 바인딩 지원
- SimpleJdbcInsert
- INSERT SQL을 편리하게 사용 가능하도록 지원
- SimpleJdbcCall
- 스토어드 프로시저를 편리하게 호출 할수있도록 지원
이제 사용법을 알아보도록 하자
기본적으로 gradle을 사용하여 진행합니다.
DataBase는 H2 DB를 사용합니다.
의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
한줄만 추가하면 끄읕! (정말?!)
사용방법은 CRUD 기반으로 코드를 작성하며 delete부분은 따로 추가하지 않습니다.
각각의 메소드 명은 save, update, findById 정도로 진행합니다.
각각의 기능에 사용 될 기본 Item 테이블을 추가하도록 하겠습니다.
--테이블 생성
create table item
(
id bigint generated by default as identity,
item_name varchar(10),
price integer,
quantity integer,
primary key (id)
);
SAVE(저장)
데이터베이스에 데이터를 저장하는 방법은 여러가지가 존재합니다.
- JdbcTemplate를 사용하는 방법
- NamedParameterJdbcTemplate를 사용하는방법
- SimpleJdbcInsert를 사용하는 방법
JdbcTemplate를 사용하는 방법
public class JdbcTemplateItemRepositoryV1 implements ItemRepository {
private final JdbcTemplate template;
public JdbcTemplateItemRepositoryV1(DataSource dataSource){
this.template = new JdbcTemplate(dataSource);
}
public Item save(Item item) {
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;
}
}
NamedParameterJdbcTemplate를 사용하는 방법
public class JdbcTemplateItemRepositoryV2 implements ItemRepository {
private final NamedParameterJdbcTemplate template;
public JdbcTemplateItemRepositoryV2(DataSource dataSource){
this.template = new NamedParameterJdbcTemplate(dataSource);
}
@Override
public Item save(Item item) {
String sql = "insert into item(item_name, price, quantity) " +
"values (:itemName, :price, :quantity)";
SqlParameterSource param = new BeanPropertySqlParameterSource(item);
KeyHolder keyHolder = new GeneratedKeyHolder();
template.update(sql, param, keyHolder);
long key = keyHolder.getKey().longValue();
item.setId(key);
return item;
}
}
SimpleJdbcInsert를 사용하는 방법
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", "quantity"); //생략 가능
}
@Override
public Item save(Item item) {
SqlParameterSource param = new BeanPropertySqlParameterSource(item);
Number key = jdbcInsert.executeAndReturnKey(param);
item.setId(key.longValue());
return item;
}
}
UPDATE(수정)
update의 경우도 save와 마찬가지로 ?,?,? 형태로 업데이트 컬럼을 작성하여 순서대로 넣는 방식과 각각의 컬럼명(MapSqlParameterSource)을 직접 명시해서 실수를 줄일 수 있는 방법이 있습니다.
순서대로 넣는 방법
public void update(Long itemId, ItemUpdateDto updateParam) {
String sql = "update item set item_name=?, price=?, quantity=? where id=?";
template.update(sql,
updateParam.getItemName(),
updateParam.getPrice(),
updateParam.getQuantity(),
itemId);
}
MapSqlParameterSource 사용하여 수정하는 방법
public void update(Long itemId, ItemUpdateDto updateParam) {
String sql = "update item set item_name=:itemName, price=:price, quantity=:quantity " +
"where id=:itemId";
SqlParameterSource param = new MapSqlParameterSource()
.addValue("itemName", updateParam.getItemName())
.addValue("price", updateParam.getPrice())
.addValue("quantity", updateParam.getQuantity())
.addValue("itemId", itemId);
template.update(sql, param);
}
FindById (검색)
검색의 경우 데이터베이스에서 값을 찾아 row을 해당 Class로 매핑해줘야 하는 부분이 필요한데 그부분이 RowMapper인터페이스를 구현해서 처리한다.
직접 각각의 컬럼을 매핑해주는 방법과 BeanPropertyRowMapper을 이용하는 방법을 알아보도록 하겠습니다.
각각의 컬럼을 매핑해주는 방법
public Optional<Item> findById(Long id) {
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();
}
}
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;
});
}
BeanPropertyRowMapper를 이용하고 ?대신 컬럼명으로 where문을 작성하는 방법
public Optional<Item> findById(Long id) {
String sql = "select id, item_name, price, quantity from item where id =:id";
try{
Map<String, Long> param = Map.of("id", id);
Item item = template.queryForObject(sql, param, itemRowMapper());
return Optional.of(item);
}catch (EmptyResultDataAccessException e){
return Optional.empty();
}
}
private RowMapper<Item> itemRowMapper() {
return BeanPropertyRowMapper.newInstance(Item.class); //camel 변환 지원
}
기본적인 사용방법을 알아보았는데 개발을 하며 좀 더 자세한 내용이 필요한 부분들은 따로 찾아보며 작업하면 될 것 같습니다.
스프링 JdbcTemplate 사용 방법 공식 메뉴얼
'프로그래밍 > java' 카테고리의 다른 글
[Srping Batch] 스프링 배치를 이용하여 예,적금 데이터 동기화하기 4편 (2) | 2022.09.12 |
---|---|
[Srping Batch] 스프링 배치를 이용하여 예,적금 데이터 동기화하기 3편 (0) | 2022.09.10 |
[Srping Batch] 스프링 배치를 이용하여 예,적금 데이터 동기화하기 2편 (0) | 2022.09.09 |
[Srping Batch] 스프링 배치를 이용하여 예,적금 데이터 동기화하기 1편 (6) | 2022.09.07 |
[Spring Boot] JSP 사용시 다국어 적용하기 (0) | 2022.05.02 |
댓글