반응형
환경설정은 순수 JDBC 설정과 동일하게 하면 된다.
순수 JDBC에서 작성한 반복 코드를 제거해준다.
실무에서 많이 사용된다고 한다.
공식 문서
Data Access
The Data Access Object (DAO) support in Spring is aimed at making it easy to work with data access technologies (such as JDBC, Hibernate, or JPA) in a consistent way. This lets you switch between the aforementioned persistence technologies fairly easily, a
docs.spring.io
참고 블로그
https://velog.io/@seculoper235/JDBC-5%ED%8E%B8-jdbcTemplate
JdbcTemplate이란? 1편
jdbc+Template 즉, 직역하면 "jdbc를 위한 틀"이라는 뜻이다.그만큼 jdbc 프로그래밍에 특화되어 있다는 것 일텐데, 어떤 점이 더 좋다는 걸까? 한번 알아보자기존의 방식과 비교해서 알아보자.// SELECT
velog.io
JdbcTemplateMemberRepository 클래스 작성(JDBC템플릿 사용을 위해서)
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;
// 생성자가 하나일 경우에는 DI를 위해서 @Autowired 선언을 안해줘도 된다
// @Autowired
public JdbcTemplateMemberRepository(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Member save(Member member) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(jdbcTemplate);
// 테이블명(member), PK(id) 알려주면 sql 작성을 안해도 된다.
jdbcInsert.withTableName("member").usingGeneratedKeyColumns("id");
Map<String, Object> parameters = new HashMap<>();
parameters.put("name", member.getName());
// executeAndReturnKey: 작업 수행과 동시에 자동 생성된 PK(auto_increment)를 반환한다.
Number key = jdbcInsert.executeAndReturnKey(new MapSqlParameterSource(parameters));
member.setId(key.longValue());
return member;
}
@Override
public Optional<Member> findById(Long id) {
// 사용법: jdbcTemplate.query("쿼리문", RowMapper(), 쿼리의 ? 파라미터 값)
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());
}
@Override
public void clearStore() {
}
// 결과를 받아오기 위한 함수
private RowMapper<Member> memberRowMapper() {
return new RowMapper<Member>() {
@Override
public Member mapRow(ResultSet rs, int rowNum) throws SQLException {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
}
};
}
}
SpringConfig 클래스 수정 -> JDBC템플릿을 사용하는 것으로 설정 변경
package hello.hellospring.service;
import hello.hellospring.repository.JdbcMemberRepository;
import hello.hellospring.repository.JdbcTemplateMemberRepository;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import javax.xml.crypto.Data;
// 자바코드로 직접 스프링 빈 등록하는 방법
// 스프링 실행할때 자동 실행
@Configuration
public class SpringConfig {
private DataSource dataSource;
@Autowired
public SpringConfig(DataSource dataSource){
this.dataSource = dataSource;
}
// 스프링 빈 등록
@Bean
public MemberService memberService() {
// @Autowired와 같이 동작
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
// 구현체를 리턴해줌
// return new MemoryMemberRepository();
// JDBC 연결로 변경경
// return new JdbcMemberRepository(dataSource);
// JDBCTemplate 연결로 변경
return new JdbcTemplateMemberRepository(dataSource);
}
}
MemberServiceIntegrationTest -> 기존에 작성한 테스트 코드를 이용하여 테스트 진행
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
// 테스트는 한글로 바꾸어도 된다.
// 빌드될때 테스트코드는 포함되지 않는다.
@SpringBootTest
@Transactional
class MemberServiceIntegrationTest {
// 컨테이너로 부터 주입받는다.
// 테스트를 진행할 때는 편하게 @Autowired 사용하면 된다. -> 필드 주입 방법(DI)
@Autowired MemberService memberService;
@Autowired MemberRepository memberRepository;
@Test
void 회원가입() {
// given
Member member = new Member();
member.setName("spring");
// when
Long saveId = memberService.join(member);
// then
Member findMember = memberService.findOne(saveId).get();
assertThat(member.getName()).isEqualTo(findMember.getName());
}
@Test
public void 중복_회원_예외(){
// given
Member member1 = new Member();
member1.setName("spring");
Member member2 = new Member();
member2.setName("spring");
// when
memberService.join(member1);
// member2를 join 할 때 IllegalStateException이 발생하것을 예상하는 코드
IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));
assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
// assertThrows(NullPointerException.class,() -> memberService.join(member2));
/* try {
memberService.join(member2);
fail();
} catch (IllegalStateException e) {
Assertions.assertThat(e.getMessage()).isEqualTo("이미 존해하는 회원입니다.12333");
}*/
// then
}
}
반응형
'코드로 배우는 스프링 부트 - 인프런' 카테고리의 다른 글
스프링 데이터 JPA (0) | 2022.08.23 |
---|---|
JPA (0) | 2022.08.22 |
스프링 통합 테스트 (0) | 2022.08.18 |
순수 JDBC (0) | 2022.08.17 |
H2 데이터베이스 설치 (0) | 2022.08.16 |