이전시간에 통합테스트에 대해 알아보았다. 이번에는 스프링 JdbcTemplate를 공부해보자.
단점으로는 SQL문 직접 작성해야한다.
스프링 JdbcTemplate의 이름은 디자인 패턴의 템플릿 메소드 패턴을 많이 사용한데서 유래됨.
Jdbc를 사용해서 구현한 JdbcMemberRepository를 JdbcTemplate 라이브러리를 사용해서 더 간단하게 구현해보자!!
repository폴더에 JdbcTemplateMemberRepository 파일 생성 후 코드 작성
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class JdbcTemplateMemberRepository implements MemberRepository{
private final JdbcTemplate jdbcTemplate;
@Autowired
public JdbcTemplateMemberRepository(DataSource dataSource){
jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Member save(Member member) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", member.getName());
Number key = jdbcInsert.executeAndReturnKey(new
MapSqlParameterSource(parameters));
member.setId(key.longValue());
return member;
}
@Override
public Optional<Member> findById(Long id) {
List<Member> result = jdbcTemplate.query("select * from where id = ?",memberRowMapper(),id);
return result.stream().findAny();
}
@Override
public Optional<Member> findByName(String name) {
List<Member> result = jdbcTemplate.query("select * from where name = ?",memberRowMapper(),name);
return result.stream().findAny();
}
@Override
public List<Member> findAll() {
return jdbcTemplate.query("select * from member",memberRowMapper());
}
private RowMapper<Member> memberRowMapper() {
return (rs, rowNum) -> {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
};
}
}
JdbcTemplate를 사용하기 위해서 생성자에서 dataSource를 받아 JdbaTemplate를 생성할 때 인자로 넘겨주고 jdbcTemplate 객체를 생성한다.(jdbcTemplate는 주입받을 수 있는 그런게 아니라서)
(참고 : 생성자가 하나만 있을 때는 @Autowired를 생략할 수 있다. --> 스프링이 자동으로 넣어준다. but 두 개 이상일 때는 안돼)
List<Member> result = jdbcTemplate.query(sql, 결과, parameter);
query()는 DB에 sql문을 보내는 메서드야. 리턴 타입은 List
파라미터는 sql문의 "?"에 대응하는 값을 넣는다.
SimpleJdbcInsert
JdbcTemplate를 넣어서 만드는 객체. --> 쿼리문을 직접 작성하지 않아도 되게 도와준다.
private RowMapper<Member> memberRowMapper()
객체 생성을 도와줘. -> query()의 결과를 Member객체로 변환한 다음 돌려주는 용도로 사용했음
이외에도 JdbcTemplate자체에 기능이 많기에 따로 찾아서 참고하자.
JdbcTemplate를 사용한 Repository를 구현했으니 이제 이 구현체를 사용하도록 설정해야지. (SpringConfig에서 설정하는거 안 잊었지?)
SpringConfig에서 memberRepository() 생성자 부분을 수정하자
@Bean
public MemberRepository memberRepository(){
//return new MemoryMemberRepository();
//return new JdbcMemberRepository(dataSource);
return new JdbcTemplateMemberRepository(dataSource);
}
이제 프로젝트를 실행하자
DB까지 연동하여 test하는 통합테스트 코드를 작성하였기 때문에 이제 웹 애플리케이션에서 직접 실행하여 회원가입, 회원조회를 할 필요없이 MemberServiceIntegrationTest 코드를 실행하여 테스트 진행하자.
실무에서도 근무시간의 60~70%는 테스트 코드 개발을, 30~40%는 실제 사용할 코드를 개발한다....
실무에서 작은 버그 하나도 시스템에 문제를 유발하기 때문.
테스트 코드 꼼꼼하게 잘 짜는 것이 중요!!!
JdbcTemplate 으로 DB까지 연동하여 작동하는 테스트가 잘 실행되는 것 확인 가능!
이 글은 강의 : 김영한 - "스프링 입문-코드로 배우는 스프링 부트, 웹 MVC, DB접근기술"을 듣고 정리한 내용입니다.