10 KiB
Spring JDBC Client 소개 및 활용
Spring 6부터 도입된 **JdbcClient**는 기존 JdbcTemplate보다 더 간결하고 현대적인 API를 제공합니다.
특히, 메서드 체이닝과 함수형 스타일의 코드 작성이 가능하여, 기존 JDBC 코드보다 훨씬 직관적인 사용이 가능합니다.
이 글에서는 JdbcClient의 주요 기능과 사용법을 예제와 함께 설명하겠습니다.
1. JdbcClient란?
JdbcClient는 Spring 6 및 Spring Boot 3에서 새롭게 추가된 기능으로,
기존 JdbcTemplate이 가진 장점은 유지하면서도, 코드의 가독성과 유지보수성을 개선한 API입니다.
✔ 기존 JdbcTemplate은 보일러플레이트 코드가 많음
✔ JdbcClient는 메서드 체이닝을 지원하여 코드가 간결해짐
✔ SQL 실행 및 데이터 조회를 직관적으로 처리 가능
2. JdbcClient 사용법
📌 2.1 의존성 추가
Spring Boot 3 이상에서는 자동으로 포함되므로 별도 의존성 추가는 필요 없습니다.
하지만, Spring Framework 6에서 단독으로 사용할 경우 다음과 같은 의존성이 필요합니다.
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.x.x</version>
</dependency>
📌 2.2 JdbcClient 빈 설정
JdbcClient는 DataSource를 기반으로 생성됩니다.
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
@Configuration
public class DatabaseConfig {
@Bean
public JdbcClient jdbcClient(DataSource dataSource) {
return JdbcClient.create(dataSource);
}
}
✔ JdbcClient.create(dataSource) 를 사용하여 인스턴스 생성
✔ Spring Boot 환경에서는 자동 설정되므로 따로 등록할 필요 없음
3. CRUD 예제
📌 3.1 데이터 삽입 (INSERT)
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
private final JdbcClient jdbcClient;
public UserRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public int insertUser(String name, String email) {
return jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", name)
.param("email", email)
.update();
}
}
✔ sql("INSERT INTO users ...") → SQL 작성
✔ param("name", name) → 이름 기반 파라미터 바인딩
✔ update() → INSERT/UPDATE/DELETE 실행
📌 3.2 단일 데이터 조회 (SELECT - 단건 검색)
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public class UserRepository {
private final JdbcClient jdbcClient;
public UserRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public Optional<User> findById(Long id) {
return jdbcClient.sql("SELECT * FROM users WHERE id = :id")
.param("id", id)
.query(User.class)
.optional();
}
}
✔ query(User.class) → 자동으로 User 객체로 매핑
✔ optional() → 결과가 없을 경우 Optional.empty() 반환
📌 3.3 여러 데이터 조회 (SELECT - 리스트 검색)
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class UserRepository {
private final JdbcClient jdbcClient;
public UserRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public List<User> findAll() {
return jdbcClient.sql("SELECT * FROM users")
.query(User.class)
.list();
}
}
✔ query(User.class).list() → 리스트 형태로 결과 반환
📌 3.4 데이터 업데이트 (UPDATE)
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
private final JdbcClient jdbcClient;
public UserRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public int updateEmail(Long id, String email) {
return jdbcClient.sql("UPDATE users SET email = :email WHERE id = :id")
.param("email", email)
.param("id", id)
.update();
}
}
✔ update()를 사용하여 데이터를 수정
📌 3.5 데이터 삭제 (DELETE)
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
@Repository
public class UserRepository {
private final JdbcClient jdbcClient;
public UserRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public int deleteById(Long id) {
return jdbcClient.sql("DELETE FROM users WHERE id = :id")
.param("id", id)
.update();
}
}
✔ update()를 사용하여 DELETE 실행
4. RowMapper 없이 자동 매핑하기
기존 JdbcTemplate에서는 RowMapper를 사용하여 수동으로 매핑해야 했지만,
JdbcClient는 자동으로 Java 객체와 매핑할 수 있습니다.
import org.springframework.jdbc.core.simple.JdbcClient;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public class UserRepository {
private final JdbcClient jdbcClient;
public UserRepository(JdbcClient jdbcClient) {
this.jdbcClient = jdbcClient;
}
public List<User> findAll() {
return jdbcClient.sql("SELECT * FROM users")
.query(User.class)
.list();
}
}
✔ User 객체의 필드명과 DB 컬럼명이 일치하면 자동 매핑
5. 정리
| 기능 | JdbcTemplate | JdbcClient |
|---|---|---|
| SQL 실행 방식 | jdbcTemplate.query(sql, rowMapper) |
jdbcClient.sql(sql).query(clazz) |
| 파라미터 바인딩 | new MapSqlParameterSource() 사용 |
.param("name", value) 사용 |
| 결과 변환 | RowMapper 필요 |
자동 매핑 가능 |
| 코드 스타일 | 절차 지향 | 함수형 스타일 |
| 가독성 | 비교적 복잡 | 간결하고 직관적 |
✔ JdbcClient는 Spring Boot 3 이상에서 사용 가능
✔ 기존 JdbcTemplate 대비 더 간결하고 직관적인 코드 작성 가능
✔ 자동 매핑 기능 제공하여 RowMapper 작성 불필요
Spring Boot 3 이상을 사용한다면, JdbcTemplate 대신 더 강력하고 간결한 JdbcClient를 활용하는 것이 추천됩니다! 🚀
Spring JdbcClient 주요 메서드 정리
Spring 6 및 Spring Boot 3에서 도입된 JdbcClient는 기존 JdbcTemplate보다 간결한 API를 제공합니다.
아래는 JdbcClient의 주요 메서드를 설명과 함께 표로 정리한 것입니다.
1. JdbcClient 주요 메서드 정리
| 메서드 | 설명 | 예제 |
|---|---|---|
sql(String sql) |
실행할 SQL을 설정 | jdbcClient.sql("SELECT * FROM users") |
param(String name, Object value) |
이름 기반 파라미터 바인딩 | .param("id", 1L) |
paramSource(SqlParameterSource params) |
Map 또는 Bean을 파라미터로 전달 | .paramSource(new MapSqlParameterSource(Map.of("id", 1L))) |
query(Class<T> clazz) |
결과를 자동 매핑하여 반환 | .query(User.class).list() |
query(RowMapper<T> rowMapper) |
커스텀 RowMapper를 사용한 쿼리 실행 | .query((rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"))).list() |
queryForObject(Class<T> clazz) |
단일 결과 반환 (Optional<T> 지원) |
.queryForObject(User.class).optional() |
list() |
여러 개의 결과를 리스트로 반환 | .query(User.class).list() |
optional() |
단일 결과를 Optional로 반환 | .queryForObject(User.class).optional() |
update() |
INSERT, UPDATE, DELETE 실행 | .sql("UPDATE users SET name = :name WHERE id = :id").update() |
execute(Function<Connection, T> callback) |
JDBC 커넥션을 직접 다룰 때 사용 | .execute(conn -> conn.prepareStatement("DELETE FROM users").executeUpdate()) |
2. JdbcClient 주요 메서드 예제
📌 단일 데이터 조회 (queryForObject)
Optional<User> user = jdbcClient.sql("SELECT * FROM users WHERE id = :id")
.param("id", 1L)
.queryForObject(User.class)
.optional();
✔ SQL 실행 후 User.class로 자동 매핑
✔ 결과가 없을 경우 Optional.empty() 반환
📌 여러 데이터 조회 (query + list)
List<User> users = jdbcClient.sql("SELECT * FROM users")
.query(User.class)
.list();
✔ User.class 타입으로 리스트 변환
📌 데이터 삽입 (update)
int rows = jdbcClient.sql("INSERT INTO users (name, email) VALUES (:name, :email)")
.param("name", "Alice")
.param("email", "alice@example.com")
.update();
✔ update()를 실행하여 INSERT 수행
✔ 반영된 행 수(int) 반환
📌 데이터 삭제 (update)
int rowsDeleted = jdbcClient.sql("DELETE FROM users WHERE id = :id")
.param("id", 1L)
.update();
✔ 삭제된 행 수 반환
📌 수동 매핑 (RowMapper 사용)
List<User> users = jdbcClient.sql("SELECT * FROM users")
.query((rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name")))
.list();
✔ RowMapper를 직접 정의하여 결과 매핑 가능
3. 정리
JdbcClient는 기존JdbcTemplate보다 간결하고 현대적인 API 제공- 메서드 체이닝 지원으로 코드 가독성이 향상됨
queryForObject(),query()를 활용하면 자동 매핑 가능update()를 사용하여 INSERT, UPDATE, DELETE 실행
Spring Boot 3 이상을 사용한다면 JdbcTemplate보다 JdbcClient를 적극 활용하는 것이 추천됩니다! 🚀