1. JDBC
JDBC 란?
JDBC(Java Database Connectivity)는 자바에서 데이터베이스에 접속할 수 있도록 하는 자바 API이다. 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다.
- DB 연결, SQL과 과련된 작업을 수행할 수 있는 표준 인터페이스이다.
- 이를 이용하면 DB 종류에 상관없이 SQL문을 실행하고 처리할 수 있다.
- 자바 애플리케이션에서 영속성 계층을 처리하기 위해 JDK 1.1에 포함되어 출시한 컴포넌트이다.
아키텍처
JDBC 인터페이스는 JDBC API와 JDBC 드라이버 두 개의 계층으로 나뉜다. 백엔드 엔지니어들은 JDBC API를 이용해서 드라이버와 커넥션을 맺고 쿼리를 날린다.
JDBC API는 다음과 같은 기능을 제공한다.
- Connection - 연결
- Statement - SQL 전달
- ResultSet - 결과 응답
그리고 각각의 DB 벤더사들은 자사의 DB에 맞도록 JDBC 드라이버를 개발해서 배포한다. 대표적으로 MySQL의 경우 MySQL Connector/J 라는 JDBC 드라이버를 배포한다.
2. JDBC 사용
데이터베이스에 연결하려면 JDBC가 제공하는 DriverManager.getConnection()
을 사용하면 된다.
DriverManager는 라이브러이에 등록된 드라이버 목록을 자동으로 인식하여 커넥션을 획득할 수 있는지 확인한다.
public static void main(String[] args) {
String sql = "select * from voucher";
Connection con = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try {
con = DriverManager.getConnection("jdbc:h2:tcp//localhost/~/test", "sa", "");
pstmt = con.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()) {
String name = rs.getString("name");
UUID customerId = UUID.fromString(rs.getString("customer_id"));
}
} catch (SQLException e) {
log.error("DB error", e);
} finally {
try {
if(rs != null) {
rs.close();
}
if (pstmt != null) {
pstmt.close();
}
if (con != null) {
con.close();
}
} catch (SQLException e) {
log.error("Got error while closing connection", e);
}
}
}
Connection
을 이용해 PreparedStatement
를 만들고 executeQuery()
를 통해 쿼리를 실행한다. select 쿼리의 결과는 ResultSet
에 순서대로 들어간다.ResultSet
은 내부에 커서를 가지고 있으며 최초의 커서는 데이터를 가리키고 있지 않기 때문에 rs.next()
를 호출해야 데이터를 조회할 수 있다.
데이터에 대한 조회는 rs.getxxx("필드 이름")
을 통해 현재 커서가 가리키고 있는 row의 데이터를 해당하는 타입(xxx)으로 반환한다.
작업이 모두 수행되었으면 finally
를 통해서 사용한 리소스를 정리해주어야 한다.
- 리소스를 정리하는 부분은 try-with-resource를 사용하여 간결하게 작성할 수 있다.
PreparedStatement
는?
를 통한 파라미터 바인딩을 가능하게 해준다.Statement
를 통해 rawQuery를 그래도 전달하게 되는 경우 SQL Injection을 통해 공격자에게 데이터가 노출될 수 있다.Statement
를 사용하면 매번 쿼리의 문장을 분석 -> 컴파일 -> 실행 3단계를 거친다.PreparedStatement
는 처음 한 번만 3단계를 거치고 캐시에 담아서 재사용한다. 보안성은 물론 성능상에도 이점을 가진다.
3. CRUD
앞서 조회를 수행했으니 이번엔 삽입, 수정, 삭제를 수행해본다.
Insert
public Customer save(Customer customer) {
try(
Connection con = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
PreparedStatement pstmt = con.prepareStatement("insert into customers(customer_id, name) values (?, ?)")
) {
pstmt.setString(1, customer.getCustomerId().toString());
pstmt.setString(2, customer.getName());
pstmt.executeUpdate();
return customer;
} catch (SQLException e) {
log.error("DB error", e);
throw new RuntimeException(e);
}
}
Update
public void update(Customer customer) {
String sql = "update customers set name = ? where customer_id = ?";
try (
Connection con = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
PreparedStatement pstmt = con.prepareStatement(sql)
) {
pstmt.setString(1, customer.getName());
pstmt.setString(2, customer.getCustomerId().toString());
int executeUpdate = pstmt.executeUpdate();
log.info("updatedSize={}", executeUpdate);
} catch (SQLException e) {
log.error("DB error", e);
throw new RuntimeException(e)
}
}
Delete
public void delete(UUID customerId) {
String sql = "delete from customers where customer_id = ?";
try (
Connection con = DriverManager.getConnection("jdbc:h2:tcp://localhost/~/test", "sa", "");
PreparedStatement pstmt = con.prepareStatement(sql)
) {
pstmt.setString(1, customerId.toString());
pstmt.executeUpdate();
} catch (SQLException e) {
log.error("DB error", e);
throw new RuntimeException(e)
}
}
'공부방' 카테고리의 다른 글
[TIL 06/29] NamedParameterJdbcTemplate, Transaction (0) | 2023.06.30 |
---|---|
[TIL 06/28] Connection Pool, DataSource, JdbcTemplate (0) | 2023.06.30 |
[TIL 06/26] 테스트 (0) | 2023.06.29 |
[TIL 06/23] Logging, Logback (0) | 2023.06.23 |
[TIL 06/22] Environment, Properties, Profile (0) | 2023.06.22 |