[Spring] Spring JDBC(2): JdbcTemplate으로 Query와 Update을 해보자! (queryForObject, query, update, PreparedStatementCreator, KeyHolder)

2023. 4. 20. 18:00· Spring
반응형
 

지난 포스팅에서 Spring JDBC가 무엇인지, 그리고 어떤 도구들을 사용해 DB에 접근할 수 있는지에 대해서 알아보았다. 

이번 포스팅에서는 JdbcTemplate을 사용해서 DB에 접근하고, Querying과 Updating을 하는 방법에 대해 공부해볼 것이다!

 

💋 JdbcTemplate

 

  • Spring에서 제공하는 JDBC Core 패키지에서 가장 핵심이 되는 클래스
  • 리소스의 생성과 해제를 처리해서 연결을 닫는 것을 까먹고 못하게 되는 등의 일반적인 오류를 방지한다.
  • SQL 쿼리를 실행한다.
  • SQL문을 실행하여 DB에서 데이터를 변경한다. 예를 들어 DB에 새로운 데이터를 추가하거나, 기존 데이터를 업데이트하거나 삭제하는 작업을 한다.
  • SQL 쿼리의 실행 결과로 ResultSet을 생성한다. 
  • JDBC 예외를 잡아서 org.springframework.dao 패키지에서 정의된 일반적인 예외 계층 구조로 변환한다.

 

참고: ResultSet 인스턴스는 SQL 쿼리를 실행하여 DB에서 검색한 결과를 포함하는 객체이다.

 

 

 

💋 JdbcTemplate을 사용한 Querying (SELECT)

 

SQL 쿼리를 통해서 원하는 값을 찾아와 보자!

 

 

👍🏻 queryForObject

 

  • 단일 결과 행을 반환하는 쿼리를 실행할 때 주로 사용된다. 
  • 결과 집합이 없거나 여러 개의 결과 행이 있으면 예외가 발생한다. 

 

이 메서드는 딱 하나의 결과만을 반환하는 쿼리를 위해서 사용되는데, 파라미터가 다양하게 오버로딩 되어 있어서, 용도에 따라 사용하면 된다! 

아래에서는 오버로딩된 몇 가지의 메서드를 소개하겠다!

 

 

✔ <T> T queryForObject(String sql, Class<T> requiredType)

 

아래와 같이 사용하면, 내가 원하는 전체 개수를 얻을 수 있다. 

 

/**
 * public <T> T queryForObject(String sql, Class<T> requiredType)
 */
public int count() {
    String sql = "select count(*) from customers";
    return jdbcTemplate.queryForObject(sql, Integer.class);
}

 

 

 

✔ <T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args)

 

 

/**
 * public <T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args)
 */
public String getLastName(Long id) {
    String sql = "select last_name from customers where id = ?";
    return jdbcTemplate.queryForObject(sql, String.class, id);
}

 

이 쿼리문은 중간에 ?가 있다. 완성되지 않은 쿼리문이다.

 

@Override
public <T> T queryForObject(String sql, Class<T> requiredType, @Nullable Object... args) throws DataAccessException {
   return queryForObject(sql, args, getSingleColumnRowMapper(requiredType));
}

 

앞서 나왔던 예시에서처럼, sql문과 required type을 적어주고, 물음표에 들어갈 내용들을 순서대로 뒤에 적어주면 된다. 물음표 없으면 안 적으면 된다. 

 

 

✔ <T> T queryForObject(String sql, RowMapper<T> rowMapper, @Nullable Object... args)

 

/**
 * public <T> T queryForObject(String sql, RowMapper<T> rowMapper, @Nullable Object... args)
 */
public Customer findCustomerById(Long id) {
    String sql = "select id, first_name, last_name from customers where id = ?";
    return jdbcTemplate.queryForObject(sql, customerRowMapper, id);
}

 

 

JDBC Template의 RowMapper는 ResultSet에서 가져온 데이터를 객체에 매핑하는 역할을 한다. 

 

private final RowMapper<Customer> customerRowMapper = (resultSet, rowNum) -> {
    Customer customer = new Customer(
            resultSet.getLong("id"),
            resultSet.getString("first_name"),
            resultSet.getString("last_name")
    );
    return customer;
};

 

 

  • resultSet은 쿼리 결과를 담고 있는 객체로, ResultSet에서 가져온 데이터를 매핑하기 위해 사용한다.
  • rowNum은 ResultSet에서 가져온 데이터의 행 번호이다. RowMapper에서 rowNum을 사용하면, ResultSet에서 가져온 데이터의 행 번호를 사용하여 객체를 매핑할 수 있다. 

 

 

 

 

👍🏻 query

 

  • 결과를 List 형태로 반환하는 쿼리를 실행할 때 주로 사용된다.
  • 결과는 RowMapper 인터페이스를 구현하는 객체를 사용하여 각 행을 매핑하여 반환한다.
  • 결과 집합이 없을 때는 빈 List를 반환한다. 

 

✔ <T> List<T> query(String sql, RowMapper<T> rowMapper)

 

/**
 * public <T> List<T> query(String sql, RowMapper<T> rowMapper)
 */
public List<Customer> findAllCustomers() {
    String sql = "select id, first_name, last_name from customers";
    return jdbcTemplate.query(sql, customerRowMapper);
}

 

여기에서도 RowMapper 인터페이스를 구현하는 객체가 사용되었다.

 

 

✔ <T> List<T> query(String sql, RowMapper<T> rowMapper, @Nullable Object... args)

 

 

아까 queryForObject에서와 마찬가지로 중간에 ?로 빵꾸 뚫려있어도, 뒤에 쭉 적으면 된다. 

 

/**
 * public <T> List<T> query(String sql, RowMapper<T> rowMapper, @Nullable Object... args)
 */
public List<Customer> findCustomerByFirstName(String firstName) {
    String sql = "select id, first_name, last_name from customers where first_name = ?";
    return jdbcTemplate.query(sql, customerRowMapper, firstName);
}

 

 


 

💋 JdbcTemplate을 사용한 Updating (INSERT, UPDATE, DELETE) 

 

select랑 비슷하니, 간단하게 나열하겠음! 사실 이 포스팅은 나중에 내가 찾아보기 위한 용이므루...

 

✔ int update(String sql, @Nullable Object... args)

 

/**
 * public int update(String sql, @Nullable Object... args)
 */
public void insert(Customer customer) {
    String sql = "insert into customers (first_name, last_name) values (?, ?)";
    jdbcTemplate.update(sql, customer.getFirstName(), customer.getLastName());
}

 

update() 메서드는 데이터베이스에서 실행된 업데이트 쿼리의 결과로 변경된 행의 수를 반환한다. 

만약 변경된 행이 없으면 0을 반환한다.

 

같은 방식으로 쿼리문만 변경하면 DELETE도 가능하다.

 

public int delete(Long id) {
    String sql = "delete from customers where id = ?";
    return jdbcTemplate.update(sql, id);
}

 

 

 

 

✔ int update(final PreparedStatementCreator psc, final KeyHolder generatedKeyHolder)

 

Retrieving Auto-generated Keys에 관한 내용이다. 즉, 데이터베이스에서 자동으로 생성된 키 값을 가져오는 방법이다. 

예를 들어, MySQL에서는 AUTO_INCREMENT 키워드를 사용하여 자동으로 증가하는 키 값을 생성할 수 있다.

 

이 메서드는 첫 번째 파라미터로는 PreparedStatementCreator를 받는데, 이건 insert 쿼리문을 물음표 같은 빈 곳 없이 완벽하게 특정하기 위한 것이다. 

두 번째 파라미터는 KeyHolder이고, 이건 update가 성공적으로 되었을 때 생성된 key를 담고 있기 위한 것이다. 

 

 

final String INSERT_SQL = "insert into my_test (name) values(?)";
final String name = "Rob";

KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(connection -> {
    PreparedStatement ps = connection.prepareStatement(INSERT_SQL, new String[] { "id" });
    ps.setString(1, name);
    return ps;
}, keyHolder);

// keyHolder.getKey() now contains the generated key

 

예시 하나 더!

 

/**
 * public int update(final PreparedStatementCreator psc, final KeyHolder generatedKeyHolder)
 */
public Long insertWithKeyHolder(Customer customer) {
    final String sql = "insert into customers (first_name, last_name) values (?, ?)";
    final KeyHolder keyHolder = new GeneratedKeyHolder();
    jdbcTemplate.update(connection -> {
        final PreparedStatement preparedStatement = connection.prepareStatement(sql, 
        new String[]{"id"}); // 여기 내가 가져오려 하는 AUTO_INCREMENT 되는 Key를 넣어준다!
        preparedStatement.setString(1, customer.getFirstName());
        preparedStatement.setString(2, customer.getLastName());
        return preparedStatement;
    }, keyHolder);
    return Objects.requireNonNull(keyHolder.getKey()).longValue();
}

 

휴 이제 JdbcTemplate의 사용에 대한 부분은 거의 다 끝난 것 같다.

나중에 더 사용이 나오면 추가할 예정.. 

이제 다음 포스팅에서는 NamedParameterJdbcTemplate과 SimpleJdbcInsert을 다루는 방법에 대해 알아보려고 한다.

 

 

끗

 

 

 

 

💋 참고자료

 

  • JdbcTemplate - Querying
  • JdbcTemplate - Updating
반응형
저작자표시 비영리 변경금지 (새창열림)

'Spring' 카테고리의 다른 글

[Spring] 레이어드 아키텍처(Layered Architecture): 독립적으로 계층을 설계해보자!  (0) 2023.04.21
[Spring] Spring JDBC(3): NamedParameterJdbcTemplate를 사용해보자! SqlParameterSource, MapSqlParameterSource, BeanPropertySqlParameterSource  (0) 2023.04.21
[Spring] Spring JDBC(1): Spring JDBC가 뭘까? 좋은점? DB에 접근하는 여러 가지 방법  (2) 2023.04.20
[Spring] Spring MVC(4): @ControllerAdvice로 애플리케이션 전체에서 예외를 처리해보자!  (2) 2023.04.20
[Spring] @Repository를 final class로 만들면 안되는 이유: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dbGameDao'  (1) 2023.04.19
'Spring' 카테고리의 다른 글
  • [Spring] 레이어드 아키텍처(Layered Architecture): 독립적으로 계층을 설계해보자!
  • [Spring] Spring JDBC(3): NamedParameterJdbcTemplate를 사용해보자! SqlParameterSource, MapSqlParameterSource, BeanPropertySqlParameterSource
  • [Spring] Spring JDBC(1): Spring JDBC가 뭘까? 좋은점? DB에 접근하는 여러 가지 방법
  • [Spring] Spring MVC(4): @ControllerAdvice로 애플리케이션 전체에서 예외를 처리해보자!
깃짱
깃짱
연새데학교 컴퓨터과학과 & 우아한테크코스 5기 백엔드 스타라이토 깃짱
반응형
깃짱
깃짱코딩
깃짱
전체
오늘
어제
  • 분류 전체보기
    • About. 깃짱
    • Weekly Momentum
      • 2024
    • PROJECT
      • AIGOYA LABS
      • Stamp Crush
      • Sunny Braille
    • 우아한테크코스5기
    • 회고+후기
    • Computer Science
      • Operating System
      • Computer Architecture
      • Network
      • Data Structure
      • Database
      • Algorithm
      • Automata
      • Data Privacy
      • Graphics
      • ETC
    • WEB
      • HTTP
      • Application
    • C, C++
    • JAVA
    • Spring
      • JPA
      • MVC
    • AI
    • MySQL
    • PostgreSQL
    • DevOps
      • AWS
      • 대규모 시스템 설계
    • frontend
      • HTML+CSS
    • NextJS
    • TEST
    • Industrial Engineering
    • Soft Skill
    • TIL
      • 2023
      • 2024
    • Linux
    • Git
    • IntelliJ
    • ETC
      • 日本語

블로그 메뉴

  • 홈
  • 깃허브

인기 글

최근 글

태그

  • OOP
  • 스트림
  • TDD
  • 상속과조합
  • 레벨로그
  • lamda
  • 컴포지션
  • 람다와스트림
  • 우테코
  • 우아한테크코스5기
  • Stream
  • 함수형프로그래밍
  • 우아한테크코스
  • 예외
  • 람다
  • 우테코5기
  • 상속
  • Java
  • 조합
  • Composition
hELLO · Designed By 정상우.v4.2.0
깃짱
[Spring] Spring JDBC(2): JdbcTemplate으로 Query와 Update을 해보자! (queryForObject, query, update, PreparedStatementCreator, KeyHolder)
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.