JDBC(Java DataBase Connectivity)는 자바 프로그램이 데이터베이스와 연결하고 작업을 진행하기 위한 자바 표준 API로
응용프로그램과 데이터베이스 사이의 연결을 관리하고 쿼리를 실행하며 결과를 처리할 수 있도록 표준 인터페이스를 제공한다
장점
- 데이터베이스 독립성
- JDBC API를 사용하면 데이터베이스의 종류에 상관없이 동일한 방식으로 데이터베이스 작업을 수행할 수 있다
- 이식성
- JDBC를 사용하는 자바 애플리케이션은 다양한 플랫폼에서 실행될 수 있다
- 표준화
- JDBC는 자바 표준 API로 일관된 인터페이스를 제공한다
자바 진영에서 추상화된 Driver 인터페이스를 제공함으로 다양한 DB 환경에서 접근을 용이하게 만든다
Driver를 관리하는 DriverManager는 각 DB사가 구현한 JDBC Driver 구현체를 로드하여
연결이 성공하면 Connection 객체를 반환한다
JDBC의 주요 인터페이스
- Driver: 데이터베이스와의 통신을 담당하는 인터페이스
- Connection: 데이터베이스와의 연결을 나타내는 인터페이스
- Statement: SQL 문을 실행하기 위한 인터페이스
- PreparedStatement: 미리 컴파일된 SQL문을 실행하기 위한 인터페이스
- ResultSet: SQL 쿼리의 결과를 나타내는 인터페이스
JDBC의 사용 흐름
- JDBC 드라이버 로드
- 사용하고자 하는 데이터베이스에 맞는 JDBC 드라이버를 로드한다
-
Class.forName("com.mysql.cj.jdbc.Driver");
- 데이터베이스 연결 생성
- DriverManager.getConnection() 메서드를 사용하여 데이터베이스와의 연결을 설정한다.
-
// 데이터베이스 연결 정보 String url = "jdbc:mysql://localhost:3306/your_database_name"; String user = "your_username"; String password = "your_password"; // 연결 생성 Connection connection = DriverManager.getConnection(url, user, password);
- SQL문 실행
- Connection 객체를 통해 Statement 또는 PreparedStatement 객체를 생성하고 이를 사용하여 SQL 쿼리를 실행한다
- Statement, PreparedStatement: SQL 쿼리를 실행하기 위한 인터페이스이다
- PreparedStatement는 파라미터화된 쿼리를 사용하며 이를 통해 SQL Injection을 방어하고
쿼리를 매번 컴파일하는 Statement와 달리 미리 컴파일하여 캐시에 저장한다
- Connection 객체를 통해 Statement 또는 PreparedStatement 객체를 생성하고 이를 사용하여 SQL 쿼리를 실행한다
- 결과 처리
- Select 문의 경우 ResultSet 객체를 통해 결과를 받아 처리한다
- ReultSet 객체는 데이터베이스로부터 읽어온 데이터를 행 단위로 접근한다
- ResultSet은 초기 생성 시 커서가 첫 번째 행의 앞 쪽에 위치하기 때문에 데이터를 읽기 위해서는 next()메서드를 호출하여 첫 번째 행으로 이동해야 한다
- 데이터베이스 연결 종료
- 모든 작업이 완료되면 연결을 종료하고 리소스를 해제한다
-
rs.close(); pstmt.close(); con.close();
예제 코드
import java.sql.*;
public class SQLExample {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/your_database";
String user = "your_username";
String password = "your_password";
try (Connection conn = DriverManager.getConnection(url, user, password)) {
// JDBC를 통한 트랜잭션 관리도 가능
conn.setAutoCommit(false);
// 기본 Statement를 사용한 INSERT 예시
try (Statement stmt = conn.createStatement()) {
String insertSQL = "INSERT INTO employees (name, age) VALUES ('John Doe', 30)";
int rowsAffected = stmt.executeUpdate(insertSQL);
}
// PreparedStatement를 사용한 INSERT 예시
String preparedInsertSQL = "INSERT INTO employees (name, age) VALUES (?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(preparedInsertSQL)) {
// 첫 번째 삽입
pstmt.setString(1, "Jane Smith");
pstmt.setInt(2, 25);
int rowsAffected = pstmt.executeUpdate();
System.out.println("PreparedStatement로 " + rowsAffected + " row(s) inserted.");
// 동일한 PreparedStatement로 다른 데이터 삽입
pstmt.setString(1, "Bob Johnson");
pstmt.setInt(2, 35);
rowsAffected = pstmt.executeUpdate();
}
// 기본 Statement를 사용한 SELECT 예시
try (Statement stmt = conn.createStatement()) {
String selectSQL = "SELECT * FROM employees";
ResultSet rs = stmt.executeQuery(selectSQL);
System.out.println("\n[Statement로 조회한 결과]");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
}
}
// PreparedStatement를 사용한 SELECT 예시
String preparedSelectSQL = "SELECT * FROM employees WHERE age > ?";
try (PreparedStatement pstmt = conn.prepareStatement(preparedSelectSQL)) {
pstmt.setInt(1, 30); // 30세 이상인 직원만 조회
ResultSet rs = pstmt.executeQuery();
System.out.println("\n[PreparedStatement로 조회한 결과 (30세 이상)]");
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
System.out.println("ID: " + id + ", Name: " + name + ", Age: " + age);
}
}
conn.commit();
} catch (SQLException e) {
if(conn != null){
// 예외 발생 시 롤백
conn.rollback();
}
e.printStackTrace();
}
}
}
커넥션 풀 Connection Pool
커넥션 풀은 웹 애플리케이션 서버가 실행될 때
미리 일정 수의 데이터베이스 연결 객체를 생성하여 풀에 저장해 두는 기법이다
네트워크 오버헤드, 인증 과정, 메모리 할당, 리소스 초기화 등의 이유로
Connection 객체를 생성하는 것은 많은 비용이 발생하기 때문에 이러한 기술을 사용한다.
동작 방식
- 초기화: WAS 시작 시 미리 설정된 수만큼의 Connection 객체를 생성하여 풀에 저장한다 (기본값으로 10개)
- 연결 요청: 클라이언트가 데이터베이스 연결을 요청한다
- 연결 제공: 풀에서 사용 가능한 Connection 객체를 제공한다
- 연결 사용: 클라이언트는 제공받은 Connection 객체를 사용하여 데이터베이스 작업을 수행한다
- 연결 반환: 작업이 완료되면 Connection 객체를 풀로 반환한다
장점
- 성능 향상: 연결 객체를 재사용함으로써 객체 생성 및 제거에 따른 오버헤드를 줄임
- 리소스 관리: 동시 연결 수를 제한하여 데이터베이스 서버의 부하를 관리
- 확장성: 갑작스러운 사용자 증가에도 안정적으로 대응할 수 있음
Connection Poll은 Java에서 주로 DataSource 인터페이스를 통해 구현되며,
이전에는 Apache 재단의 Apache Commons DBCP를 주로 사용했지만
Spring Boot 2.0 이후로는 HikariCP가 기본 커넥션 풀 라이브러리로 사용된다
마무리
다양한 DB 관련 기술이 나타나며 JDBC를 직접 사용할 일은 줄어들게 되었지만
우리가 사용하는 다양한 데이터베이스 접근 기술(JPA, MyBatis, ...)들은
최하위 레벨에서 JDBC를 사용하기에 흐름에 대해 정확히 이해할 필요가 있다.
출처
https://bjwan-career.tistory.com/266
https://ittrue.tistory.com/250
https://realjavaonline.com/jdbc/jdbc.php
https://dev.to/kevwan/understanding-and-tuning-parameters-of-connection-pools-1fdb
'Java' 카테고리의 다른 글
record (2) | 2024.12.01 |
---|---|
직렬화(Serialization) (2) | 2024.12.01 |
고유 락 (Intrinsic Lock) (1) | 2024.11.29 |
Java에서의 Thread (0) | 2024.11.28 |
JVM stack & heap (1) | 2024.09.26 |