[Java] JDBCTemplate이란? JDBCTemplate 사용법, RowMapper란?
1. JDBCTemplate 이란?
JDBCTemplate은 JDBC 코어 패키지의 중앙 클래스로
JDBC 사용을 단순화하고 일반적인 오류를 방지하는데 도움을 준다
일반적으로 JDBC를 직접 사용하면 아래와 같은 작업을 반복한다
- 커넥션 획득
- statement를 준비하고 실행
- 결과를 반복하도록 루프를 실행
- 커넥션 종료, statement 및 resultset 종료
- 트랜잭션을 다루기 위한 커넥션 동기화
- 예외 발생 시 스프링 예외 변환기 실행
요약하면 JDBCTemplate은 개발자가 JDBC를
쉽게 사용할 수 있게 도와주는 클래스이다
2. JDBCTemplate 사용법
1) 설정
먼저 라이브러리를 프로젝트에 추가해 줘야한다
Gradle, Maven 에 따라 표기 방식이 다르다
Gradle 은 build.gradle 파일에 코드를 작성해주고
Maven 은 pom.xml 파일에 코드를 작성해 준다
Gradle
//JdbcTemplate 추가
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
Maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
JDBCTemplate은 Spring-boot-starter-jdbc 에 포함되어 있다
2) DataSource 주입
JDBCTemplate은 DataSource를 필요로 한다
DataSource는 스프링 빈으로 등록해 사용한다
스프링 빈으로 직접 등록하고 주입 받는 방법
@Configuration
public class DataSourceConfiguration {
@Bean
public DataSource getDataSource() {
DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
dataSourceBuilder.url("");
dataSourceBuilder.username("");
dataSourceBuilder.password("");
dataSourceBuilder.driverClassName("");
return dataSourceBuilder.build();
}
}
사용하고자 하는 곳에서 의존 관계 주입 받는 방법
private final JdbcTemplate jdbcTemplate;
public JdbcTemplateItemRepository(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
보통 빈을 직접 만들기 보단 의존 관계를 주입받는 방법을 많이 쓴다
3. 쿼리 작성 및 실행
JDBCTemplate을 사용하는 방법은 공식문서에 나와있고
대표적인 몇가지만 알아보자
JdbcTemplate (Spring Framework 6.0.9 API)
Execute a query for a result object, given static SQL. Uses a JDBC Statement, not a PreparedStatement. If you want to execute a static query with a PreparedStatement, use the overloaded JdbcOperations.queryForObject(String, Class, Object...) method with nu
docs.spring.io
1) queryForObject()
<T> T queryForObject(String sql, RowMapper<T> rowMapper, Object... args) throws DataAccessException;
- sql : 실행할 sql문
- rowMapper : 조회대상
- args : 파라미터들
queryForObject() 를 사용하면 단건 조회를 할 수 있다
이때 조회 대상이 객체가 아닌 단순 데이터면
타입을 지정해서 사용하면 된다
int로 반환하기 위해
int rowCount = jdbcTemplate.queryForObject("select count(*) from t_actor",Integer.class);
preparedStatement ? 를 이용해서 파라미터 바인딩도 할 수 있다
int countOfActorsNamedJoe = jdbcTemplate.queryForObject(
"select count(*) from t_actor where first_name = ?", Integer.class, "cho");
String을 조회할 수 도 있다
String lastName = jdbcTemplate.queryForObject(
"select last_name from t_actor where id = ?", String.class, 3000L);
그렇다면 객체를 조회하려면 어떻게 해야할까
RowMapper를 활용해서 조회할 수 있다
RowMapper는 반환 결과인 ResultSet을 객체로 변환해주는 클래스이다
순수 JDBC를 사용해서 객체를 조회하면 아래와 같이 작성해 줘야한다
// 쿼리 날리기
ResultSet rs = stat.excuteQuery("SELECT * FROM Item");
// 결과값 가져오기
while(rs.next()) {
// item 객체에 값 저장
item = new Item();
item.setId(rs.getInt(1));
item.setItemName(rs.getString(2));
item.setPrice(rs.getInt(3));
// 리스트에 추가
itemList.add(item);
}
ResultSet의 결과를 개발자가 직접 꺼내 객체에 담아 저장한다
하지만 RowMapper를 이용하면 이러한 단순 반복 작업을 자동화 해준다
RowMapper의 mapRow() 메서드
T mapRow(ResultSet rs, int rowNum) throws SQLException;
ResultSet rs에 결과를 담아와 사용자가 원하는 객체에 담는다
rowNum은 반복되는 루프 중 현재 행의 번호를 나타낸다
public Item mapRow(ResultSet rs, int rowNum) throws SQLException {
// ResultSet 값을 Item 객체에 저장
Item item = new Item();
item.setId(rs.getLong("id"));
item.setItemName(rs.getString("item_name"));
item.setPrice(rs.getInt("price"));
// item 반환
return item;
};
2) query()
query() 메서드를 사용하면 여러 건을 조회할 수 있다
public List<Actor> findAllActors() {
return this.jdbcTemplate.query("select first_name, last_name from t_actor", actorRowMapper);
}
3) update()
INSERT, UPDATE, DELETE 등 데이터를 변경하고 싶을 때는
update() 메서드를 사용할 수 있다
SQL 실행 결과에 영향받은 로우 수를 int로 반환한다
등록 (INSERT)
jdbcTemplate.update("insert into t_actor (first_name, last_name) values (?, ?)","cho", "penguin");
수정 (UPDATE)
jdbcTemplate.update("update t_actor set last_name = ? where id = ?", "cho", 3000L);
삭제 (DELETE )
jdbcTemplate.update("delete from t_actor where id = ?", Long.valueOf(actorId));
4) execute()
임의의 SQL을 실행할 때는 execute() 메서드를 사용할 수 있다
테이블을 생성하는 DDL 등 사용할 수 있다
jdbcTemplate.execute("create table penguintable (id integer, name varchar(100))");