18. 스프링 JdbcTemplate

Bummy·2023년 4월 29일
0
post-thumbnail

이번에는 스프링과 DB 연결을 JdbcTemplate을 통해 구현한다.

JdbcTemplate 연결을 위한 새로운 리포지토리를 만들어준다.

JdbcTemplateMemberRepository.java

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.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

public class JdbcTemplateMemberRepository implements MemberRepository{

    private final JdbcTemplate jdbcTemplate;

    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 member where id = ?", memberRowMapper(), id);
       return result.stream().findAny();
    }

    @Override
    public Optional<Member> findByName(String name) {
        List<Member> result = jdbcTemplate.query("select * from member 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를 부여받도록한다.
  • @Autowired는 생성자에 클래스가 하나라면 생략이 가능하다.

간단하게 코드를 한줄씩 확인해보면

memberRowMapper()

private RowMapper<Member> memberRowMapper(){
        return (rs, rowNum) -> {
            Member member = new Member();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            return member;
        };
    }
  • RowMapper는 리턴값을 객체로 리턴될 수 있도록 하는 기능을 한다.

Save()

    @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;
    }
  • save는 JdbcTemplate에서 제공하는 JdbcInsert를 활용한다.
  • 쿼리를 직접 작성해줄 필요 없이 insert 대상 테이블과, 컬럼, 그리고 값을 받아 insert를 해주는 기능을 하고 있다.

findById()

 @Override
    public Optional<Member> findById(Long id) {
       List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
       return result.stream().findAny();
    }
  • jdbcTemplate에 직접 쿼리를 작성해서 해당 파라미터 값으로 테이블에서 데이터를 select 할 수 있도록 한다.
  • query(”작성쿼리”, “리턴 형식”, “컬럼”); 을 의미하는 듯 하다.

JdbcTemplateMemberRepository가 모두 작성되었다면 SpringConfig.java에서 @Bean을 변경해준다.

SpringConfig.java

package hello.hellospring;

import hello.hellospring.repository.JdbcMemberRepository;
import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.sevice.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;

@Configuration
public class SpringConfig {
    private DataSource dataSource;

    @Autowired
    public SpringConfig(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
//        return new MemoryMemberRepository();
//        return new JdbcMemberRepository(dataSource);
        return new JdbcTemplateMemberRepository(dataSource);
    }
}

테스트 결과

DB 연결 방식에 상관 없이 통합 테스트 환경을 구축해 두었기에 실제 웹에서 테스트를 진행하지 않아도 편하게 테스트가 가능하다. 이렇게 테스트 코드가 구축이 잘 되었다면 훨씬 간편하게 코드를 작성할 수 있다.

0개의 댓글