TIL - JAVA spring DAY 15

jihan kong·2022년 1월 26일
0

JAVA spring 입문

목록 보기
17/20
post-thumbnail

스프링 Jdbc Template

오늘은 Jdbc template에 관해 학습하였다. 기본적으로 Jdbc template은 순수한 Jdbc 코드에서의 반복 코드를 제거해준다. 그러나, SQL은 직접 작성해야한다. Jdbc template은 실제로 실무에서도 많이 사용한다고 하셨다. 그만큼 복잡했던 Jdbc를 편리하게 작성할 수 있는 장점 때문인 것 같다. 본격적으로 Jdbc template 을 생성해보자.
먼저, 다음과 같이 repository package에 JdbcTemplateMemberRepository class를 생성한다.

JdbcTemplateMemberRepository.class

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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class JdbcTemplateMemberRepository implements MemberRepository {

    private final JdbcTemplate jdbcTemplate; // Jdbc Template이 따로 있다.
    
    @Autowired  // 1.
   public JdbcTemplateMemberRepository(DataSource dataSource) {
        jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override // 2.
    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 // 3.
    public Optional<Member> findById(Long Id) {
        List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), Id);
        return result.stream().findAny();
    }

    @Override // 4.
    public Optional<Member> findByName(String name) {
        List<Member> result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
        return Optional.empty();
    }

    @Override // 5.
    public List<Member> findAll() {
        return jdbcTemplate.query("select * from member", memberRowMapper());
    }
	
    // 6.
    private RowMapper<Member> memberRowMapper() {
        return (rs, rowNum) -> {
            Member member = new Member();
            member.setId(rs.getLong("id"));
            member.setName(rs.getString("name"));
            return member;
        };
    }
}

주석처리로 넘버링한 코드의 설명은 다음과 같다.

  1. DataSourceInjection을 받음. 그 후, JdbcTemplate 객체를 생성하고, dataSource를 받도록 해줌. (위와 같이 생성자가 하나만 있으면 @Autowired 생략가능)
  2. 쿼리를 짤 필요 없이 템플릿 내 기능으로Insert문을 생성. (JdbcTemplate Document를 참고하여 만들면 편함)
  3. 조회하는 쿼리. 나온 결과값을 RowMapper 라는 메소드로 매핑해주는 작업이 필요. result는 List로 받아서 Optional로 반환
  4. 위 3번의 코드에서 Idname으로 바꿔서 구현
  5. select문으로 구현
  6. 위에서 언급한 RowMapper 를 람다식으로 구현한 메소드.

이제 조립(?)하는 단계만 남았다. SpringConfig class를 살펴보자.

SpringConfig.class

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

위와 같이 memberRepository 메소드에 JdbcTemplateMemberRepositorydataSource 를 입력인자로 받고 리턴하게끔 하면 된다.

그리고 실행시켜보자. 우리는 저번에 스프링 통합 테스트를 만들어놓았다. 이제 DB에 내용이 반영되었는지 웹을 통해 검증할 필요없이 심플하게 그것만 실행시켜서 테스트를 진행하면 된다.

(테스트가 통과되는 모습)

Test code

강사님께서 테스트 코드의 중요성에 대해서 설명해주셨다. 현업에서도 프로덕션 코드를 개발하는 것보다 오히려 테스트 코드를 개발하는 비중이 더 많은데 이는 테스트코드의 중요성을 말해주고 있다. 개발을 잘하는 개발자일수록 테스트코드를 정교하고 꼼꼼하게 잘 구성한다고 말씀하셨다. 테스트를 통해 원천적인 오류를 찾아내고 해결하는 능력을 갖추는 것이 좋은 개발자의 자질임을 항상 기억해야겠다.

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글