드라이버의 역할 : 애플리케이션과 데이터베이스간의 통신을 중개하는 역할 ( 애플리케이션의 요청을 데이터베이스가 이해 할 수 있는 언어로 변환)
드라이버의 종류
ex) Oracle, MySQL, PostgreSQL
드라이버의 동작 방식
- 연결 초기화
- 요청 수신: 애플리케이션은 데이터베이스 작업을 시작하기 위해 드라이버에 연결을 요청합니다. 이는 마치 항공편✈️ 이 이륙 허가를 받기 위해 관제탑에 요청하는 것과 유사합니다.
- 연결 설정: 드라이버는 데이터베이스 서버에 로그인하고 필요한 설정을 수행하여 연결을 완료합니다. 이 과정은 네트워크 정보, 인증 자격 증명 등을 사용하여 이루어집니다.
- SQL 전송 및 실행
- SQL 명령 변환: 애플리케이션에서 발송된 SQL 명령을 받은 드라이버는 해당 명령을 데이터베이스가 이해할 수 있는 형태로 변환합니다. 이는 외국어를 현지 언어로 번역하는 통역사의 역할과 같습니다.
- 명령 처리: 변환된 명령은 데이터베이스 서버로 전송되어 실행됩니다. 데이터베이스는 쿼리를 처리하고, 요구된 데이터를 검색하거나 데이터에 변화를 줍니다.
- 결과 처리
- 결과 수신: 데이터베이스에서 작업의 결과를 보내면, 드라이버는 이 결과를 받아 애플리케이션에서 해석할 수 있는 형태로 변환합니다.
- 결과 전달: 최종적으로, 드라이버는 이 결과를 애플리케이션에 전달합니다. 이는 관제탑이 항공기✈️에 착륙 지시를 내리는 과정과 유사하며, 애플리케이션은 이 정보를 사용자에게 표시하거나 다음 작업을 진행합니다.
- 연결 종료
- 연결 해제: 작업이 완료되면, 드라이버는 데이터베이스 서버와의 연결을 종료합니다. 이는 비행이 끝난 후 항공기✈️가 공항 게이트에 도킹하는 것과 비슷하며, 자원을 정리하고 다음 세션을 위해 시스템을 초기화합니다.
💡 JDBC Driver Manager 는 애플리케이션이 실행되고 있는 런타임 시점에
- Connection(연결) 을 생성하여 쿼리를 요청할 수 있는 상태를 만들어주고
- Statement(상태) 를 생성하여 쿼리를 요청하게 해주고
- ResultSet(결과셋) 을 생성해 쿼리 결과를 받아올 수 있게 해줍니다.
Spring Boot 의 JDBC 라이브러리
- Spring Boot와 JDBC: Spring Boot는 데이터베이스 연결을 쉽게 구성할 수 있도록 다양한 JDBC 드라이버를 지원합니다. 이를 통해 개발자는 복잡한 설정 없이 데이터베이스와의 연결을 쉽게 구성할 수 있습니다.
- spring-boot-starter-jdbc는 Spring Boot 프로젝트에서 JDBC를 통해 데이터베이스와 상호작용하기 위해 사용되는 스타터 패키지입니다.
- 이 스타터 패키지는 데이터베이스 작업을 수행하는 데 필요한 주요 의존성과 자동 구성 기능을 제공합니다. 데이터베이스와의 연결을 쉽고 빠르게 구성할 수 있도록 도와주는 브릿지 역할을 합니다.
- 주요 포함 내용
- JDBC API 지원: JDBC API를 통해 SQL 데이터베이스에 접근하고 작업을 수행할 수 있습니다.
- DataSource 구성: 데이터 소스 연결을 위한 기본적인 설정을 자동으로 구성합니다. 이는 데이터베이스 연결을 관리하는 데 필수적인 요소입니다.
- JdbcTemplate: **JdbcTemplate**은 Spring의 핵심 클래스 중 하나로, JDBC 작업의 많은 번거로움을 줄여 줍니다. SQL 쿼리 실행, 결과 세트 처리, 예외 처리 등을 단순화합니다.
- 주요 장점 내용
- 간소화된 데이터베이스 연결: DataSource 설정과 JdbcTemplate 사용을 통해 복잡한 JDBC 코드를 간소화할 수 있습니다.
- 자동 구성: Spring Boot의 자동 구성 기능은 개발자가 데이터베이스 연결에 필요한 대부분의 구성을 자동으로 처리할 수 있도록 합니다.
- 효율적인 예외 처리: Spring의 **DataAccessException**을 통해 JDBC에서 발생하는 예외를 Spring의 일관된 예외 체계로 변환합니다.
JDBC Template (QueryMapper)
- JDBC 로 직접 SQL을 작성했을때의 문제
- SQL 쿼리 요청시 중복 코드 발생
- DB별 예외에 대한 구분 없이 Checked Exception (SQL Exception) 처리
- Connection, Statement 등.. 자원 관리를 따로 해줘야함
- 자원 해제 안해주면 메모리 꽉차서 서버가 죽음
- 이 문제 해결을 위해 처음으로 Persistence Framework 등장!
- Persistence Framework 는 2가지가 있다.
- SQL Mapper : JDBC Template, MyBatis 👈 요게 먼저나옴
- ORM : JPA, Hibernate
- Persistence Framework 는 2가지가 있다.
- SQL Mapper (QueryMapper)
- SQL ↔ Object
- SQL 문과 객체(Object)의 필드를 매핑하여 데이터를 객채화
JDBC Template (RowMapper)
- SQL Mapper 첫번째 주자로 JDBCTemplate 에 RowMapper 탄생
- 쿼리 수행 결과와 객채 필드 매핑
- RowMapper 로 응답필드 매핑코드 재사용
- Connection, Statement, ResultSet 반복적 처리 대신 해줌
- 😵💫 But, 결과값을 객체 인스턴스에 매핑하는데 여전히 많은 코드가 필요함
JDBC Template 실습
- insertUser: 새로운 사용자를 users 테이블에 추가합니다. 사용자의 이름과 이메일 주소를 매개변수로 받아 데이터베이스에 저장합니다.
- findUserNameById: 주어진 ID에 해당하는 사용자의 이름을 조회합니다. queryForObject 메서드를 사용하여 단일 결과를 반환합니다.
- updateUser: 주어진 ID의 사용자 이름을 새로운 이름으로 변경합니다. UPDATE SQL 명령을 사용하여 해당 ID의 사용자 정보를 업데이트합니다.
- deleteUser: 주어진 ID를 가진 사용자를 users 테이블에서 삭제합니다. DELETE SQL 명령을 사용하여 해당 ID의 사용자 정보를 삭제합니다.
// DataRepository.java
package com.thesun4sky.jdbc;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class DataRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
// 테이블 생성
public void createTable() {
jdbcTemplate.execute("CREATE TABLE IF NOT EXISTS users (id SERIAL, name VARCHAR(255))");
}
// 사용자 추가 (Create)
public void insertUser(String name) {
jdbcTemplate.update("INSERT INTO users (name) VALUES (?)", name);
}
// 사용자 ID로 이름 조회 (Read)
public String findUserNameById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT name FROM users WHERE id = ?",
new Object[]{id},
String.class
);
}
// 사용자 이름 변경 (Update)
public void updateUser(Long id, String newName) {
jdbcTemplate.update("UPDATE users SET name = ? WHERE id = ?", newName, id);
}
// 사용자 삭제 (Delete)
public void deleteUser(Long id) {
jdbcTemplate.update("DELETE FROM users WHERE id = ?", id);
}
}
// JdbcApplication.java
package com.thesun4sky.jdbc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class JdbcApplication {
public static void main(String[] args) {
// 어플리케이션 실행 컨텍스트 생성
var context = SpringApplication.run(JdbcApplication.class, args);
// 데이터 조회 클래스 빈 조회
var repository = context.getBean(DataRepository.class);
// 테이블 생성
repository.createTable();
// 유저정보 추가
repository.insertUser("Teasun Kim");
// 유저정보 조회
System.out.println("User Name: " + repository.findUserNameById(1L));
}
}
JDBC Template RowMapper 실습
- RowMapper.mapRow : RowMapper 를 상속받아 mapRow() 메서드를 구현하면 JDBCTemplate 에서 row 응답을 mapRow() 메서드에 rs 파라미터로 넘겨주어 객체에 매핑하기 쉽도록 도와준다.
- findUserById : jdbcTemplate.queryForObject() 메서드에서는 두번쨰 인자로 RowMapper 를 넣어줄 경우 해당 RowMapper 의 mapRow() 메서드를 사용하여 응답을 하도록 동작한다.
// UserRowMapper.java
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.jdbc.core.RowMapper;
public class UserRowMapper implements RowMapper<User> {
// JDBCTemplate 에서 row 응답을 mapRow() 메서드에 rs 파라미터로 넘겨주어 객체에 매핑하기 쉽도록 도와준다.
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
var user = new User();
user.setId(rs.getInt("ID"));
user.setName(rs.getString("NAME"));
return user;
}
}
// 사용자 ID로 User 조회 (Read)
public User findUserById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new UserRowMapper(), // 이자리에 매퍼를 생성자로 넣어주면 됨
id
);
}
'Springboot' 카테고리의 다른 글
AWS # Identity and Access Management (0) | 2024.07.05 |
---|---|
QueryDSL, Auditing, Dynamic Insert/Update (0) | 2024.07.01 |
테이블 객체 만들기 (0) | 2024.06.28 |
쿼리 파일 만들기 (QueryMapper) (0) | 2024.06.28 |
Filter, Intercepter (0) | 2024.06.26 |