[SPRING] JdbcTemplate

ShinOyh·2024년 10월 18일

Java

목록 보기
2/2

JdbcTemplate 이란?

JdbcTemplateSpring Framework에서 제공하는 클래스로, JDBC API를 보다 간편하고 효율적으로 사용할 수 있도록 도와주는 유틸리티입니다.

정의

JDBC를 사용하여 데이터베이스에 접근하고 쿼리를 실행하기 위한 핵심 클래스입니다. 복잡한 JDBC 코드의 반복을 줄여주고, 데이터베이스 작업을 단순화하여 개발자가 비즈니스 로직에 집중할 수 있도록 도와줍니다.

주요 특징

1. 간편한 데이터베이스 작업:
JdbcTemplate는 데이터베이스 연결, 쿼리 실행, 결과 처리, 예외 처리 등을 내부적으로 처리하여 개발자가 직접 JDBC 코드를 작성하지 않아도 되게 해줍니다.

2. SQL 쿼리 실행:
다양한 SQL 쿼리를 쉽게 실행할 수 있는 메서드를 제공합니다. 예를 들어, 쿼리, 업데이트, 배치 작업 등을 지원합니다.

3. RowMapper 지원:
쿼리 결과를 객체로 매핑하기 위해 RowMapper 인터페이스를 쉽게 사용할 수 있어, 결과를 DTO나 POJO 형태로 변환할 수 있습니다.

4. Named Parameters 지원:
JdbcTemplate의 하위 클래스인 NamedParameterJdbcTemplate를 통해 이름 기반의 파라미터를 사용하여 SQL 쿼리를 더 가독성 있게 작성할 수 있습니다.


JdbcTemplate 사용방법

1. 환경 설정

*h2를 사용할 것이기 때문에 h2database관련 gradle도 추가*

*username은 자신이 설정한 데이터베이스 이름*

2. DataSource 주입

업로드중..

위에서 설정한 DataBase정보를 생성자 주입 방법 사용
* 다양한 방법이 있지만 생성자 주입 방법을 많이 사용한다 *

3. 쿼리 작성

3-1 queryForObject

int countOfActorsNamedJoe = jdbcTemplate.queryForObject(
"select count(*) from t_actor where first_name = ?", Integer.class, "Joe");

단일 데이터를 반환할 때 사용되는 메서드입니다.
사용되는 매개변수는 순서대로

  • sql
  • 조회대상
  • 파라미터

로 구성되어 있고, 조회대상이 단순 자료형인 경우, 위 예시 코드처럼 Integer.class를 사용하거나 문자열인 경우에는 String.class를 사용할 수 있습니다.
파라미터는 sql문의 "?" 의 순서에 따라서 차례대로 작성하면 됩니다.

3-2 query

List<String> result = 
jdbcTemplate.query("select first_name from t_actor where last_name = ?", String.class, "Kim");

여러 데이터를 반환할 때 사용되는 메서드이다.
이외에는 위 queryForObject와 같습니다.

3-3 update

INSERT, UPDATE, DELETE 등 데이터를 변경하고 싶을 때는 update() 메서드를 사용할 수 있습니다.
SQL 실행 결과에 영향받은 로우 수를 int로 반환합니다.

INSERT 예시

jdbcTemplate.update("insert t_actor set last_name = ? where id = ?", "Banjo", 5276L);

사용법은 나머지 둘도 동일합니다.
sql문의 insert만 update, delete 로 바꿔주면 됩니다.


기본적인 쿼리문 작성 방법을 알아봤습니다!
하지만 여기서 무조건 의문이 생겨야 하는데,
객체를 반환받으려면 어떻게 해야하는 지??? 입니다.
RowMapper에 대해서 알아봅시다~

4. RowMapper

RowMapper는 데이터베이스의 반환 결과인 ResultSet을 객체로 변환해주는 클래스입니다.

Q. 굳이 ResultSet을 객체로 변환해서 받아와야하나요??
A. 무조건 꼭(?) 할 필요는 없는데 아래 비교를 보시죵..

Jdbc로 구현한 코드

@Override
 public Optional<Member> findById(Long id) {
 	String sql = "select * from member where id = ?";
 	Connection conn = null;
 	PreparedStatement pstmt = null;
 	ResultSet rs = null;
 	try {
 		conn = getConnection();
 		pstmt = conn.prepareStatement(sql);
 		pstmt.setLong(1, id);
 		rs = pstmt.executeQuery();
 		if(rs.next()) {
 			Member member = new Member();
 			member.setId(rs.getLong("id"));
 			member.setName(rs.getString("name"));
 			return Optional.of(member);
 		} else {
 			return Optional.empty();
 		}
 	} catch (Exception e) {
 		throw new IllegalStateException(e);
 	} finally {
 		close(conn, pstmt, rs);
 	}
 }

JdbcTemplate으로 구현한 코드

@Override
public Optional<Member> findById(Long id) {
	List<Member> result = jdbcTemplate.query("select * from member where id = ?", memberRowMapper(), id);
	return result.stream().findAny();
}

예.. 같은 동작을 합니다..
Jdbc 코드에서는 ResultSet의 정보를 하나하나 객체에 다시 입력해줘야합니다. 하지만
JdbcTemplate 코드에서는 memberRowMapper()만 툭 던져주고 끝났죠?

이렇게 개발자의 반복노동을 줄여주는 고마운 클래스입니다.

mapRow()

T mapRow(ResultSet rs, int rowNum) throws SQLException;

먼저 알아야 하는 것은 mapRow() 메서드의 동작입니다.

  • ResultSet rs에 결과값을 담아와 사용자가 원하는 객체에 담는다.
  • int rowNum은 반복되는 루프 중 현재 행의 번호를 나타낸다.

RowMapper 람다 구현

private RowMapper<Member> memberRowMapper() {
 	return (rs, rowNum) -> {
 		Member member = new Member();
 		member.setId(rs.getLong("id"));
 		member.setName(rs.getString("name"));
 		return member;
 	};
 }

RowMapper의 mapRow 메서드를 활용해서 람다식으로 작성할 수 있습니다.
예상되는 반환 결과를 위 코드처럼 미리 설정해 주면 됩니다!

5. NamedParameterJdbcTemplate

기존 JdbcTemplate보다 더 편리하게 사용할 수 있는 클래스입니다.
기존 JdbcTemplate"?"에 맞춰서 차례대로 파라미터들을 설정해줘야했습니다.(바로 위에 있는 내용인데 기억하셔야됩니다!!)
하지만, NamedParameterJdbcTemplate은 자동으로 설정합니다.

5-1 SqlParameterSource

위에서 ResultSet의 결과를 자동으로 객체에 담아주기 위해서 RowMapper를 사용했듯이 파라미터를 자동으로 설정해주기 위해서 우리는 파라미터들을 객체에 미리 넣어줄 건데 이 때 쓰이는 인터페이스입니다. 인터페이스니까 구현을 해야겠죠?
이 인터페이스를 구현하는 방법 2가지를 알려드리겠습니다.

5-1-1 BeanPropertySqlParameterSource

BeanPropertySqlParameterSource param = new BeanPropertySqlParameterSource(member);

member객체의 변수들을 자동으로 바인딩하여 파라미터로 사용할 수 있습니다.

5-1-2 MapSqlParameterSource

MapSqlParameterSource param = new MapSqlParameterSource()
                .addValue("name", member.getName())
                .addValue("id", member.getId());

변수들을 하나씩 설정해주지만, 이 방법의 장점은 객체에 없는 변수도 sql문의 파라미터로 사용할 수 있다는 것!입니다.

5-1-3 사용 방법

@Override
public Optional<Member> findById(Long id) {
	List<Member> result = namedJdbcTemplate.query("select * from member where id = :id", memberRowMapper(), param);
	return result.stream().findAny();
}

위에서 설정한 param을 넣어주고 "?" 대신에 :id 로 표현하는 것을 볼 수 있습니다! 그러면 어떤 "?"에 무슨 값을 넣어줘야할 지 고민할 필요없이
필요한 파라미터이름을 ":" 뒤에 쓰기만 하면 끝입니다.


출처 : https://velog.io/@aal2525/%EC%8A%A4%ED%94%84%EB%A7%81-DB-1%ED%8E%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%91%EA%B7%BC-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-Spring-Jdbc-Template#jdbctemplate
https://code-lab1.tistory.com/277

profile
비 온 뒤 맑음

0개의 댓글