Spring JDBC(3) JdbcTemplate을 사용해보자

오잉·2023년 4월 13일
0

SPRING

목록 보기
6/15

1. Jdbc vs JdbcTemplate

JDBC는 오래된 기술이다. 그래서 최근에는 JDBC를 직접 사용하기 보다는 JDBC를 편리하게 사용하기 위한 다양한 기술(SQL Mapper & ORM)이 존재한다.

그 중 SQL Mapper 기술은 기존 Jdbc의 반복 작업(connection 획득, statement 준비 및 실행, close등)을 대신 처리해준다. 즉, SQL Mapper 기술을 통해 개발자는 JDBC기술을 훨씬 편리하게 사용할 수 있다.

JdbcTemplate은 SQL Mapper기술 중 하나이다.

기존 Jdbc

 public Member save(Member member) throws SQLException {
          String sql = "insert into member(member_id, money) values(?, ?)";
          Connection con = null;
          PreparedStatement pstmt = null;
          
          try {
              con = getConnection(); // connection 획득
              pstmt = con.prepareStatement(sql); // statement 세팅
              pstmt.setString(1, member.getMemberId());
              pstmt.setInt(2, member.getMoney());
              pstmt.executeUpdate(); // sql을 connection을 통해 실제 db로 전달
              return member;
          } catch (SQLException e) {
            throw e;
          } finally {
            close(con, pstmt, null);
          }
}

JdbcTemplate

public Member save(Member member) {
	String sql = "insert into member(member_id, money) values(?, ?)";
    jdbcTemplate.update(sql, member.getId(), member.getMoney());
}

2. JdbcTemplate 사용

1) query() - SELECT

기본 형태

<T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException;
  • sql : 실행할 SQL 문
  • rowMapper : 반환 타입
  • args : 파라미터들

파라미터 바인딩

?을 이용해 파라미터 바인딩을 할 수 있다.
?에 순서대로 파라미터가 들어가게 된다.

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

queryForObject vs query

queryForObject : 단건조회 (반환값 하나)

Actor actor = jdbcTemplate.queryForObject(
        "select first_name, last_name from t_actor where id = ?",
         actorRowMapper,
         1212L);

query : 다건조회 (반환값 리스트)

List<Actor> actors = jdbcTemplate.query(
	"select first_name, last_name from t_actor",
	 actorRowMapper);

2) update() - INSERT, UPDATE, DELETE

update() 메소드는 SQL 실행 결과에 영향받은 row수를 int로 반환한다

  • insert
jdbcTemplate.update(
        "insert into t_actor (first_name, last_name) values (?, ?)",
        "Leonor", "Watling");

  • update
jdbcTemplate.update(
        "update t_actor set last_name = ? where id = ?",
        "Banjo", 5276L);
  • delete
jdbcTemplate.update(
        "delete from t_actor where id = ?",
        Long.valueOf(actorId));

3) execute()

이외의 임의의 SQL을 실행할 때는 execute() 메서드를 사용할 수 있다.
예를 들어 테이블을 생성하는 DDL 등에 사용할 수 있다.

jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");

3. RowMapper

RowMapper는 Jdbc의 인터페이스인 ResultSet에서 값을 추출하여 원하는 객체로 타입을 변환하는 역할을 한다.

RowMapper 작성법

private final RowMapper<Actor> actorRowMapper = 
	(resultSet, rowNum) -> {
    Actor actor = new Actor();
    actor.setFirstName(resultSet.getString("first_name"));
    actor.setLastName(resultSet.getString("last_name"));
    return actor;
};

RowMapper 사용법

public List<Actor> findAllActors() {
	String sql = "select first_name, last_name from t_actor";
    return jdbcTemplate.query(sql, actorRowMapper);
}

1) BeanPropertyRowMapper

  • ResultSet -> Bean으로 변환
  • DB의 컬럼명과 bean 객체의 속성명이 일치하다면 BeanPropertyRowMapper를 이용하여 자동으로 객체변환을 할 수 있다.
  • DB 컬럼명이 'snake_case'로 되어 있어도 'camelCase'로 선언된 클래스의 필드로 매핑된다.

예를 들어 아래와 같은 Actor 객체가 있을 때,

public class Actor {
	private Integer id;
	private String firstName;
    private String lastName;
}

다음과 같은 코드로 ResultSet에서 Actor로 타입을 변환하여 쿼리 결과를 받아온다.

public Actor findById(Integer id) {
    String sql = "SELECT id, first_name, last_name FROM actor WHERE id = ?";
    RowMapper<Actor> actorMapper = BeanPropertyRowMapper.newInstance(Actor.class);
    jdbcTemplate.queryForObject(sql, actorMapper, 1L);
}

2) ColumnMapRowMapper

  • ResultSet -> Map으로 변환

앞 예제에서 Actor대신 Map으로 변환을 하려면

public Map<String, Object> findById(Integer id) {
	String sql = "SELECT it, first_name, last_name FROM actor WHERE id = ?";
    RowMapper<Map<String, Object>> actorMapper = new ColumnMapRowMapper();
    jdbcTemplate.queryForObject(sql, actorMapper, 1L);
}

참고
인프런 김영한님 스프링 DB 2편의 [섹션2. 스프링 JdbcTemplate]
https://code-lab1.tistory.com/277
https://github.com/benelog/spring-jdbc-tips/blob/master/spring-jdbc-core.md

profile
오잉이라네 오잉이라네 오잉이라네 ~

0개의 댓글