스프링 DB 접근 기술 - 스프링 JdbcTemplate

Chooooo·2022년 8월 12일
0
post-thumbnail

스프링 JdbcTemplate

이전시간에 통합테스트에 대해 알아보았다. 이번에는 스프링 JdbcTemplate를 공부해보자.

스프링 JdbcTemplate의 장점

  • 순수 Jdbc와 동일한 환경설정을 갖는다.
  • 스프링JdbcTemplate 및 MyBatis같은 라이브러리는 JDBC API에서 본 반복 코드를 대부분 제거해준다.
  • 실무에서도 많이 사용한다

단점으로는 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접근기술"을 듣고 정리한 내용입니다.

profile
back-end, 지속 성장 가능한 개발자를 향하여

0개의 댓글