JdbcTemplate (Spring Framework 6.2.1 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
- JdbcTemplate 은 스프링 프레임워크에서 제공하는 JDBC API의 고도화된 도구로, 데이터베이스 작업을 간소화하고 반복적인 코드를 제거하며, SQL 실행 및 데이터 매핑을 더 효율적으로 수행할 수 있도록 설계되었다.
1. JdbcTemplate의 주요 특징
반복 코드 제거 :
- JDBC의 Connection, PreparedStatement, ResultSet 관리 및 예외 처리를 자동화합니다.
- 간단한 API 제공 :
- SQL 실행을 위한 간단하고 직관적인 메서드(query, update, execute)를 제공
- 예외 처리 간소화 :
- 체크 예외를 런타임 예외인 DataAccessException으로 변환하여 처리
- 트랜잭션 통합 :
- 스프링의 트랜잭션 관리와 완벽히 통합되어 안전한 작업을 보장
2. JdbcTemplate의 동작 흐름
- 데이터베이스 연결 설정 (DataSource를 통해 연결 관리)
- SQL 실행 (SELECT, INSERT, UPDATE, DELETE)
- 결과 처리 (ResultSet 데이터를 매핑하여 객체로 변환)
- 자원 해제 (Connection, Statement, ResultSet은 내부적으로 관리)
3. JdbcTemplate 기본 설정 및 사용
3.1 Gradle 의존성 추가
build.gradle 파일에 spring-boot-starter-jdbc와 데이터베이스 드라이버를 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
implementation 'org.mariadb.jdbc:mariadb-java-client:3.1.2'
}
3.2 데이터베이스 설정
application.properties 파일에 데이터베이스 연결 정보를 추가
spring.datasource.url=jdbc:mariadb://localhost:3306/mydatabase
spring.datasource.username=myuser
spring.datasource.password=mypassword
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
3.3 JdbcTemplate를 사용한 DAO 작성
3.3.1 테이블 매핑 클래스 작성
users 테이블과 매핑될 클래스는 다음과 같다.
public class User {
private int id;
private String name;
private String email;
// Getters and Setters
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
3.3.2 DAO 클래스 작성
JdbcTemplate을 사용해 SQL 작업을 수행하는 DAO 클래스를 작성
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@Repository
public class UserRepository {
private final JdbcTemplate jdbcTemplate;
public UserRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// 테이블 생성
public void createTable() {
String sql = "CREATE TABLE IF NOT EXISTS users (" +
"id INT AUTO_INCREMENT PRIMARY KEY, " +
"name VARCHAR(50), " +
"email VARCHAR(100))";
jdbcTemplate.execute(sql);
}
// 데이터 삽입
public int insertUser(String name, String email) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
return jdbcTemplate.update(sql, name, email);
}
// 모든 사용자 조회
public List<User> findAllUsers() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
});
}
// ID로 사용자 조회
public User findUserById(int id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new Object[]{id}, new RowMapper<User>() {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getInt("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
});
}
// 사용자 삭제
public void deleteUser(int id) {
String sql = "DELETE FROM users WHERE id = ?";
jdbcTemplate.update(sql, id);
}
}
3.4 DAO 실행 테스트
CommandLineRunner를 사용하여 JdbcTemplate 기능을 테스트
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
@Component
public class DatabaseTestRunner implements CommandLineRunner {
private final UserRepository userRepository;
public DatabaseTestRunner(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public void run(String... args) throws Exception {
userRepository.createTable();
System.out.println("테이블 생성 완료");
userRepository.insertUser("홍길동", "hong@test.com");
userRepository.insertUser("이몽룡", "lee@test.com");
System.out.println("데이터 삽입 완료");
userRepository.findAllUsers().forEach(user ->
System.out.println("사용자: " + user.getName() + " - " + user.getEmail())
);
User user = userRepository.findUserById(1);
System.out.println("ID 1인 사용자: " + user.getName() + " - " + user.getEmail());
userRepository.deleteUser(1);
System.out.println("ID 1 사용자 삭제 완료");
}
}
4. 주요 메서드
메서드 | 설명 |
execute(String sql) | SQL 실행 (DDL이나 단순 쿼리). |
update(String sql, Object...) | INSERT, UPDATE, DELETE 같은 DML 작업. |
query(String sql, RowMapper) | SELECT 쿼리를 실행하고 결과를 객체 리스트로 반환. |
queryForObject(String sql, Class) | 단일 값을 반환하는 SELECT 쿼리. |
batchUpdate(String sql, List<Object[]>) | 여러 개의 데이터를 대량으로 처리. |
5. 장점 & 단점
장점
- 반복 제거 : JDBC의 번거로운 작업을 간소화
- 예외 처리 : 체크 예외를 런타임 예외(DataAccessException)로 변환
- 유연성 : SQL을 직접 작성 → 제어 용이
- 트랜잭션 지원 : 스프링의 트랜잭션 관리와 통합
단점
- SQL 직접 작성 필요
- ORM 대안 부족 : 복잡한 엔티티 관계를 다루기에는 JPA(ORM)보다 비효율적
'Spring' 카테고리의 다른 글
MyBatis 개요 (1) | 2024.12.15 |
---|---|
RowMapper와 BeanPropertyRowMapper (1) | 2024.12.15 |
Spring Boot - JDBC 연결과 DataSource(MariaDB) (0) | 2024.12.14 |
[Spring] Java Bean vs POJO vs Spring Bean (1) | 2024.07.22 |
Spring Container (0) | 2024.07.20 |