JDBC는 오래된 기술이다. 그래서 최근에는 JDBC를 직접 사용하기 보다는 JDBC를 편리하게 사용하기 위한 다양한 기술(SQL Mapper & ORM)이 존재한다.
그 중 SQL Mapper
기술은 기존 Jdbc의 반복 작업(connection 획득, statement 준비 및 실행, close등)을 대신 처리해준다. 즉, SQL Mapper 기술을 통해 개발자는 JDBC기술을 훨씬 편리하게 사용할 수 있다.
JdbcTemplate
은 SQL Mapper기술 중 하나이다.
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);
}
}
public Member save(Member member) {
String sql = "insert into member(member_id, money) values(?, ?)";
jdbcTemplate.update(sql, member.getId(), member.getMoney());
}
<T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException;
?
을 이용해 파라미터 바인딩을 할 수 있다.
?
에 순서대로 파라미터가 들어가게 된다.
int countOfActorsNamedJoe = jdbcTemplate.queryForObject(
"select count(*) from t_actor where first_name = ?",
Integer.class,
"Joe");
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);
update() 메소드는 SQL 실행 결과에 영향받은 row수를 int로 반환한다
jdbcTemplate.update(
"insert into t_actor (first_name, last_name) values (?, ?)",
"Leonor", "Watling");
jdbcTemplate.update(
"update t_actor set last_name = ? where id = ?",
"Banjo", 5276L);
jdbcTemplate.update(
"delete from t_actor where id = ?",
Long.valueOf(actorId));
이외의 임의의 SQL을 실행할 때는 execute() 메서드를 사용할 수 있다.
예를 들어 테이블을 생성하는 DDL 등에 사용할 수 있다.
jdbcTemplate.execute("create table mytable (id integer, name varchar(100))");
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);
}
예를 들어 아래와 같은 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);
}
앞 예제에서 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