1. JDBC Template (QueryMapper)
- JDBC로 직접 SQL을 작성했을 때의 문제
> SQL 쿼리 요청 시 중복 코드 발생
> DB별 예외에 대한 구분 없이 Checked Exception (SQL Exception) 처리
> Connection, Statement 등 자원 관리를 따로 해줘야 함 (자원 해제를 해주지 않으면 메모리가 넘치게 되어 서버가 다운됨)
- 위 문제 해결을 위해 두 가지 Persistance Framework가 등장
> SQL Mapper : JDBC Template, MyBatis
- SQL Mapper (QueryMapper) : SQL문과 객체(Object)의 필드를 매핑하여 데이터를 객체화
> ORM : JPA, Hibernate : SQL Mapper를 포함하는 상위 단계
- JDBC Template (RowMapper) : SQL Mapper에서 JDBC Template의 RowMapper가 첫 번째로 탄생
> 쿼리 수행 결과와 객체 필드 매핑
> RowMapper로 응답 필드 매핑 코드 재사용
> Connection, Statement, ResultSet 반복적 처리를 대신 해줌
> But, 결과값을 객체 인스턴스에 매핑하는데 여전히 많은 코드 필요
2. JDBC Template 실습
1) inserUser : 새로운 사용자를 users 테이이블에 추가, 사용자의 이름과 이메일 주소를 배개변수로 받아 데이터베이스에 저장
2) findUserNameById : 주어진 ID에 해당하는 사용자의 이름을 조회, queryForObject 메서드를 사용해 단일 결과를 반환
3) updateUser : 주어진 ID의 사용자 이름을 새로운 이름으로 변경, UPDATE SQL 명렁을 사용해 해당 ID의 사용자 정보를 업데이트
4) deleteUser : 주어진 ID를 가진 사용자를 users 테이블에서 삭제, DELETE SQL 명렁을 사용해 해당 ID의 사용자 정보를 삭제
3. ORM vs SQLMapper vs RowMapper
1) ORM (Object-Relational Mapping)
: 가장 상위 개념으로, 객체지향 프로그래밍 언어(Java)와 관계형 데이터베이스(SQL)간의 데이터를 자동으로 매핑해주는 기술
- 쿼리문 작성 없이도 데이터를 객체로 매핑 가능
- 데이터베이스와 객체 간의 매핑 규칙(테이블-클래스, 컬럼-필드)을 정의하면, CRUD 작업이 자동화됨
- 대표적인 ORM 프레임워크 : JPA, Hibernate(Spring Data JPA 포함)
@Entity
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String email;
}
// 쿼리 없이 바로 사용
List<User> users = userRepository.findAll();
2) SQL Mapper
: ORM보다 조금 더 구체적인 개념으로 , MyBatis같은 SQL Mapper가 이에 해당
- 쿼리문을 여전히 작성해야 하지만, 결과를 자동으로 객체로 매핑하는 기능을 제공
- 개발자가 작성한 SQL과 매핑 규칙(XML/애너테이션)을 기반으로 결과를 객체로 변환
- 복잡한 쿼리(JOIN, SubQuery 등)에 적합
- 사용 예 : MyBatis,에서 @Mapper나 XML로 작성한 ResultMap을 통해 결과를 객체에 매핑
@Mapper
public interface UserMapper {
@Select("SELECT id, name, email FROM users")
List<User> getAllUsers();
}
// 쿼리 작성은 필요하지만, 결과는 자동으로 매핑
List<User> users = userMapper.getAllUsers();
3) RowMapper
: Spring JDBC에서 사용되는 가장 수동적인 방식
- SQL 쿼리문을 작성한 뒤, 결과 집합 ResultSet과 각 행 Row를 Java 객체로 직접 매핑해야 함
- 매핑 로직을 개발자가 직접 작성해야 함
- 단순한 매핑 작업에서 사용 가능
String sql = "SELECT id, name, email FROM users";
List<User> users = jdbcTemplate.query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
});
4) QueryMapper
: SQL 쿼리 실행 결과를 Java 객체로 매핑하는 데 사용되는 도구/유틸리티
- SQL Mapper 또는 Spring JDBC 환경에서 데이터를 변환하는 추가적인 추상화 도구로 사용
- SQL 결과(ResultSet)를 자동 또는 반자동으로 객체로 변환
- 매핑 규칙을 미리 정의하거나, 실행 시점에 동적으로 설정 가능
- RowMapper처럼 직접 매핑 로직을 구현하는 것보다 간단하고 편리
String sql = "SELECT id, name, email FROM users";
List<User> users = QueryMapper.mapQuery(sql, User.class);
// 쿼리 실행 결과를 User 클래스와 매핑하도록 설정하면 매핑 로직을 직접 작성할 필요가 없음
< 정리 >
> ORM : 완전 자동화가 필요하고 객체 지향적인 코드 작성이 목표일 때 사용
> SQL Mapper : 쿼리 제어가 필요하지만 매핑 작업은 자동화하고 싶을 때 사용
> QueryMapper : SQL Mapper와 함께 사용할 매핑 도구가 필요하거나 결과 매핑 규칙을 동적으로 설정해야 할 때 사용
> RowMapper : 간단한 매핑 작업이나 Spring JDBC를 사용할 때 사용
상위 개념으로 갈수록 자동화 수준이 높아지고 개발자의 수작업이 감소함