https://docs.spring.io/spring-framework/docs/current/javadoc-
BeanPropertyRowMapper (Spring Framework 6.2.1 API)
Determine the mapped names for the given property. Subclasses may override this method to customize the mapped names, adding to or removing from the set determined by this base method (which returns the property name in lower-case and underscore-based form
docs.spring.io
api/org/springframework/jdbc/core/BeanPropertyRowMapper.html
BeanPropertyRowMapper (Spring Framework 6.2.1 API)
Determine the mapped names for the given property. Subclasses may override this method to customize the mapped names, adding to or removing from the set determined by this base method (which returns the property name in lower-case and underscore-based form
docs.spring.io
- RowMapper는 스프링 JDBC에서 제공하는 인터페이스로, SQL 결과(ResultSet)를 Java 객체로 매핑하는 데 사용됩니다. 데이터베이스의 결과를 특정 자바 객체로 변환하기 위해 사용되며, SELECT 쿼리의 결과를 처리하는 데 주로 활용됩니다.
RowMapper
1. RowMapper의 역할
- SQL 결과를 Java 객체로 변환 :
- 데이터베이스의 컬럼 이름과 자바 객체의 필드를 매핑하여 객체로 변환
- 코드 재사용성 증가 :
- 객체 변환 로직을 분리하여 재사용 가능한 매핑 로직을 제공
- 직접 매핑 구현 가능 :
- 단순 매핑은 BeanPropertyRowMapper를 활용하고, 복잡한 매핑은 RowMapper를 직접 구현]
2. RowMapper 인터페이스 구조
메서드
RowMapper는 단일 메서드로 구성되어 있음
public interface RowMapper<T> {
T mapRow(ResultSet rs, int rowNum) throws SQLException;
}
- mapRow(ResultSet rs, int rowNum) :
- ResultSet 객체의 현재 행을 읽고, 이를 변환하여 Java 객체를 반환함
- 매개 변수 :
- rs : 쿼리 결과를 나타내는 ResultSet
- rowNum : 결과 집합 내에서 현재 행의 번호(0부터 시작)
- 반환값 :
- 매핑된 객체( T )
3. 사용 예제
3.1 테이블과 매핑할 클래스 정의
데이터베이스의 emp테이블과 매핑할 클래스
package com.example.rowmapperex.dto;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Emp {
private String ename;
private String job;
private int empno;
}
3.2 RowMapper 구현
Emp 객체로 결과를 매핑하기 위한 RowMapper를 직접 구현
package com.example.rowmapperex.rowmapper;
import com.example.rowmapperex.dto.Emp;
import org.springframework.jdbc.core.RowMapper;
import java.sql.ResultSet;
import java.sql.SQLException;
public class EmpRowMapper implements RowMapper<Emp> {
@Override
public Emp mapRow(ResultSet rs, int rowNum) throws SQLException {
Emp emp = new Emp();
emp.setEname(rs.getString("ename"));
emp.setJob(rs.getString("job"));
emp.setEmpno(rs.getInt("empno"));
return emp;
}
}
- 매핑 로직 :
- ResultSet에서 데이터베이스 컬럼 값을 읽고, Emp객체에 설정
3.3 JdbcTemplate과 함께 사용
JdbcTemplate의 query 메서드에서 RowMapper를 사용하여 데이터를 객체로 변환함.
package com.example.rowmapperex.repository;
import com.example.rowmapperex.dto.Emp;
import com.example.rowmapperex.rowmapper.EmpRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class EmpRepository {
private final JdbcTemplate jdbcTemplate;
public EmpRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public List<Emp> findAllusers() {
String sql = "select ename, job, empno from emp";
return jdbcTemplate.query(sql, new EmpRowMapper());
}
public Emp findUserByDeptno(int deptno) {
String sql = "select ename, job, empno from emp where empno = ?";
return jdbcTemplate.queryForObject(sql, new EmpRowMapper());
}
}
- query() :
- 여러 행의 결과를 처리하여 리스트로 반환.
- queryForObject :
- 단일 행의 결과를 처리하여 객체로 반환.
결과
BeanPropertyRowMapper
- BeanPropertyRowMapper는 스프링 JDBC에서 제공하는 RowMapper의 구현체로, SQL 결과(ResultSet)를 지정한 클래스의 객체로 자동 매핑해주는 유용한 도구이다. 클래스의 속성 이름과 데이터베이스 컬럼 이름이 일치할 경우, 이를 자동으로 매핑하여 객체를 생성함.
1. 특징 및 사용 목적
- 자동 매핑 : SQL 쿼리의 결과(Resultset)를 클래스의 필드 이름과 매칭하여 객체로 변환한다.
- Reflection 기반 : Java Reflection을 사용하여 매핑 작업 자동화함
- 단순화 : 별도의 커스텀 Mapper Class 작성하지 않아도 객체로 변환할 수 있음
2. 사용 예제
2.1 예제 데이터베이스 테이블
users테이블 생성
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
2.2 매핑할 클래스
users 테이블과 매핑할 클래스 작성
package com.example.beanpropertyrowmapper.dto;
import lombok.Getter;
import lombok.Setter;
@Setter
@Getter
public class User {
private int id;
private String name;
private String email;
}
- 클래스의 필드 이름이 데이터베이스 컬럼 이름과 일치해야 함. (다를 경우 별도로 매핑 필요…)
2.3 JdbcTemplate과 BeanPropertyRowMapper 사용
package com.example.beanpropertyrowmapper.repository;
import com.example.beanpropertyrowmapper.dto.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class UserRepository {
private final JdbcTemplate jdbcTemplate;
public UserRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
public List<User> findAllUsers() {
String sql = "select id, name , email from users";
return jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
}
public User findUserById(int id) {
String sql = "select id, name, email from users where id = ?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
}
}
- new BeanPropertyRowMapper<>(User.class) : SQL 결과를 User 객체로 자동 매핑함
- query : 여러 개의 결과를 리스트로 반환
- queryForObject : 단일 결과를 객체로 반환
2.4 결과
3. BeanPropertyRowMapper 작동 방식
- 클래스의 필드와 데이터베이스 컬럼 매칭
- SQL 결과의 컬럼 이름과 클래스의 필드 이름을 대소문자를 구분하지 않고 매핑함
- 컬럼 이름이 snake_case 일 경우, camelCase 필드로 자동 변환하여 매핑함
- ex) 데이터베이스 컬럼 user_email → 클래스 필드 userEmail
- Setter 메서드 호출
- Reflection을 통해 클래스의 Setter 메서드를 호출하여 값을 설정함
- 클래스에는 반드식 기본 생성자와 setter 메서드가 있어야 함
- 예외 처리
- 필드와 컬럼이 매칭되지 않으면 예외가 발생할 수 있음(DataAccessException)
4. 장점 & 단점
장점
- 자동화 : 데이터베이스의 결과를 간단히 객체로 변환할 수 있음
- 간결성 : RowMapper를 직접 구현할 필요가 없음
- CamelCase 변환 : 컬럼 이름이 snake_case 형식이어도 클래스 필드가 camelCase 형식이라면 자동으로 매핑됨
단점
- 필드 이름 의존 : 데이터베이스 컬럼 이름과 클래스 필드 이름이 반드시 일치해야 함
- 퍼포먼스 : Reflection을 사용하기 때문에 성능이 미세하기 저하될 수 있음
- 커스텀 매핑 어려움 : 복잡한 매핑 로직이 필요한 경우에는 적합하지 않음
5. 컬럼 이름이 필드 이름과 다른 경우 처리 방법
5.1 SQL에서 별칭 사용
SQL 쿼리에서 컬럼 이름에 별칭을 지정하여 필드 이름과 일치시키는 방법
public User findUserById(int id) {
String sql = "SELECT id AS id, name AS name, email AS email_address FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), id);
}
6. RowMapper 와 BeanPropertyRowMapper 비교
특징 | RowMapper | BeanPropertyRowMapper |
매핑 방식 | 개발자가 매핑 로직을 직접 작성 | Reflection을 통해 필드와 컬럼 이름 자동 매핑 |
유연성 | 복잡한 매핑 로직에 적합 | 단순 매핑 로직에 적합 |
컬럼-필드 이름 일치 여부 | 불필요 (직접 매핑) | 컬럼 이름과 필드 이름이 일치해야 함 |
성능 | Reflection이 없으므로 더 빠름 | Reflection 사용으로 약간 느림 |
코드 간결성 | 다소 코드가 길어질 수 있음 | 코드가 더 간결 |
'Spring' 카테고리의 다른 글
MyBatis - Mapper XML (1) | 2024.12.15 |
---|---|
MyBatis 개요 (0) | 2024.12.15 |
JDBC API - JDBC Template (1) | 2024.12.14 |
Spring Boot - JDBC 연결과 DataSource(MariaDB) (0) | 2024.12.14 |
[Spring] Java Bean vs POJO vs Spring Bean (0) | 2024.07.22 |