자바에서 데이터베이스에 접근하고 SQL을 실행할 수 있도록 지원하는 표준 API(인터페이스).
JDBC는 데이터베이스별로 제공되는 드라이버를 통해 실제 연결을 처리한다.
주요 구성 요소
- Connection : 데이터베이스와의 연결 관리
- Statement 또는 PreparedStatement : SQL 실행
- ResultSet : 결과 처리.
Maven/Gradle을 사용할 경우, 자동으로 라이브러리를 추가 가능<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.33</version>
</dependency>
</dependencies>
JDBC API에서 제공하는 인터페이스.
SQL 문장을 데이터베이스에 전달하고 실행 결과를 받아오는 데 사용된다.
Statement 단점
1. 보안에 취약(사용자 입력값이 직접 SQL 문자열에 들어가기 때문)
2. 가독성이 떨어지고 반복되는 코드는 유지보수가 어렵다.
executeQuery(String sql) SELECT 문 실행 – 결과는 ResultSet 객체로 반환
executeUpdate(String sql) INSERT, UPDATE, DELETE – 영향을 받은 행 수(int) 반환
execute(String sql) 모든 SQL 문 실행 가능 – 실행 결과에 따라 ResultSet 또는 boolean 반환
create table words (
eng varchar(50) primary key,
kor varchar(50) not null,
lev int default 1,
regdate datetime default now()
);
import java.sql.*;
public class StatementEx {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/java?serverTimezone=Asia/Seoul";
String user = "root";
String password = "1234";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
System.out.println("MySQL 연결 성공!");
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from words");
while(rs.next()){
String eng = rs.getString("eng"); // apple
String kor = rs.getString("kor"); // 김사과
int lev = rs.getInt("lev"); // 1
System.out.println(eng + "\t" + kor + "\t" + lev + "\t");
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
rs.close();
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
JDBC에서 SQL 문장을 미리 준비하고 실행할 수 있도록 해주는 객체.
Statement보다 보안과 성능 측면에서 훨씬 우수하다.
SELECT * FROM users WHERE name = ?
// ? 부분 : 바인딩 파라미터
// 실행 시 자바 코드에서 값을 넣음 (pstmt.setString(1, "김사과");)
setString(int index, String value) 문자열 설정
setInt(int index, int value) 정수 설정
setDate(int index, java.sql.Date) 날짜 설정
executeQuery() SELECT 실행
executeUpdate() INSERT/UPDATE/DELETE 실행
close() 자원 정리
import java.sql.*;
public class PreparedStatementEx {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/java?serverTimezone=Asia/Seoul";
String user = "root";
String password = "1234";
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
try{
Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection(url, user, password);
System.out.println("MySQL 연결 성공!");
// select
// String sql = "select * from words where eng = ?";
// insert
// String sql = "insert into words (eng, kor, lev) values (?, ?, ?)";
// update
// String sql = "update words set kor = ?, lev=? where eng = ?";
// delete
String sql = "delete from words where eng = ?";
pstmt = conn.prepareStatement(sql);
// select
// pstmt.setString(1, "apple");
// insert
// pstmt.setString(1, "banana");
// pstmt.setString(2, "바나나");
// pstmt.setInt(3, 1);
// update
// pstmt.setString(1, "애플");
// pstmt.setInt(2, 1);
// pstmt.setString(3, "apple");
// delete
pstmt.setString(1, "apple");
// select
// rs = pstmt.executeQuery();
// insert, update, delete
int count = pstmt.executeUpdate();
// select
// while(rs.next()){
// String eng = rs.getString("eng"); // apple
// String kor = rs.getString("kor"); // 김사과
// int lev = rs.getInt("lev"); // 1
// System.out.println(eng + "\t" + kor + "\t" + lev + "\t");
// }
// insert, update, delete
System.out.println(count + "개 행이 처리되었습니다.");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
// rs.close();
pstmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
try 구문 안에서 선언한 AutoCloseable(또는 Closeable) 타입의 자원을 블록이 끝날 때 자동으로 close() 한다.
수동으로 finally 블록을 작성할 필요 없이 깔끔하고 안전하게 자원을 관리할 수 있다.
try (리소스 선언 및 초기화) {
// 자원을 사용하는 코드
} catch (예외타입 e) {
// 예외 처리
}
close()가 역순으로 자동 호출된다.close()를 호출한다.import java.sql.*;
public class SelectWithResources {
public static void main(String[] args) {
String url = "jdbc:mysql://localhost:3306/nodejs?serverTimezone=Asia/Seoul";
String user = "root";
String password = "1234";
String sql = "SELECT * FROM words WHERE lev >= ?";
// try(...) 안에서 선언된 자원은 자동으로 close()
try (
Connection conn = DriverManager.getConnection(url, user, password);
PreparedStatement pstmt = conn.prepareStatement(sql)
) {
Class.forName("com.mysql.cj.jdbc.Driver");
pstmt.setInt(1, 2);
// ResultSet 또한 try-with-resources에 포함 가능
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
String eng = rs.getString("eng");
String kor = rs.getString("kor");
int lev = rs.getInt("lev");
System.out.println(eng + ": " + kor + " (레벨: " + lev + ")");
}
}
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
// 필요시 e.getSuppressed()로 억제된 예외 확인 가능
}
}
}
try(...)에 나열할 수 있다.