6.4.1 스프링 Jdbc Template 코드 작성
앞선 섹션 6.2의 예제에서, 대부분의 코드들이 중복으로 작성되었다.
스프링 JdbcTemplate, MyBatis 같은 라이브러리는 JDBC API 에서의 중복 코드를 제거해준다.
따라서 순수 Jdbc 보다 훨씬 간결하게 코드를 작성할 수 있다는 장점이 있다.
(단, sql 은 직접 작성해야 한다.)
JdbcTemplate 코드를 작성해보자.
먼저, Jdbc Template 환경 설정의 경우, 섹션 6.3의 순수 Jdbc 설정과 동일하다.
buile.gradle 파일의 dependencies 에 아래의 코드를 추가로 작성한다.
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
다음으로, src > main > java > hello.hellospring > repository 폴더에
JdbcTemplateMemberRepository 파일을 생성하고, MemberRepository 를 구현한다.
public class JdbcTemplateMemberRepository implements MemberRepository
여기서는 JdbcTemplate 을 사용해야 하므로 아래처럼 코드를 추가한다.
private final JdbcTemplate jdbcTemplate;
이때, JdbcTemplate 을 인젝션 받을 수 없기 때문에, DataSource 를 인젝션 받도록 한다.
public JdbcTemplateMemberRepository(DataSource dataSource){
jdbcTemplate = new JdbcTemplate(dataSource);
}
+ 추가 )
위의 코드 처럼 생성자가 하나만 있을 때는, @Autowired 를 생략할 수 있다.
1) save
먼저, 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;
}
- SimpleJdbcInsert : jdbcTemplete 을 전달받고, 테이블 명과 id 로 insert 문을 작성한다.
- executeAndReturnKey 에서 key 를 전달 받는다.
- 전달 받은 key 를 setId 로 넣어준다.
2) findById
@Override
public Optional<Member> findById(Long id){
List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
return result.stream().findAny();
}
- memberRowMapper() 를 두번째 파라미터에 넣어준다. (아래에 memberRowMapper 코드 작성)
- List 로 반환되는 result 를 stream() 으로 바꾸고, findAny() 작성 (Optional 로 반환)
3) memberRowMapper
private RowMapper<Member> memberRowMapper(){
return (rs, rowNum) -> {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
};
}
- member 객체를 하나 생성한다.
- setId / setName 에서 resultSet 이 넘어오게 된다.
- member 를 반환해준다.
4) findAll
@Override
public List<Member> findAll(){
return jdbcTemplate.query("select * from member where name = ?", memberRowMapper());
}
- memberRowMapper() 로 매핑한다.
5) findByName
@Override
public Optional<Member> findByName(String name) {
List<Member> result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
return result.stream().findAny();
}
- findById 와 동일하게 작성하되, 파라미터로 id 대신 name 을 받는다.
전체 코드는 다음과 같다.
package hello.hellospring.repository;
import hello.hellospring.domain.Member;
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;
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 List<Member> findAll(){
return jdbcTemplate.query("select * from member where name = ?", memberRowMapper());
}
@Override
public Optional<Member> findByName(String name) {
List<Member> result = jdbcTemplate.query("select * from member where name = ?", memberRowMapper(), name);
return result.stream().findAny();
}
private RowMapper<Member> memberRowMapper(){
return (rs, rowNum) -> {
Member member = new Member();
member.setId(rs.getLong("id"));
member.setName(rs.getString("name"));
return member;
};
}
}
6.4.2 SpringConfig 변경 / Test
SpringConfig 에서 memberRepository 의 return 값을,
JdbcTemplateMemberRepository 로 변경하고, dataSource 를 넣어주도록 작성한다.
@Bean
public MemberRepository memberRepository() {
return new JdbcTemplateMemberRepository(dataSource);
}
지금까지 작성한 코드는 웹 어플리케이션을 통해 검증할 필요 없이,
앞서 섹션 6.3 에서 작성한 스프링 통합 test 코드를 통해 간단하게 확인할 수 있다.
test 코드를 실행해보면, 다음과 같이 정상적으로 작동하는 것을 확인할 수 있다.
김영한 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 강의를 기반으로 작성하였습니다.
'SPRING 입문 [ 코드로 배우는 스프링 부트 ]' 카테고리의 다른 글
[스프링 입문] 섹션 6.6 스프링 DB 접근 기술 (스프링 데이터 JPA) (0) | 2023.01.18 |
---|---|
[스프링 입문] 섹션 6.5 스프링 DB 접근 기술 (JPA) (1) | 2023.01.18 |
[스프링 입문] 섹션 6.3 스프링 DB 접근 기술 (스프링 통합 테스트) (0) | 2023.01.17 |
[스프링 입문] 섹션 6.2 스프링 DB 접근 기술 (순수 JDBC) (0) | 2023.01.17 |
[스프링 입문] 섹션 6.1 스프링 DB 접근 기술 (H2 데이터베이스 설치) (0) | 2023.01.17 |