JDBC

현서·2025년 5월 30일
1

자바

목록 보기
22/32
post-thumbnail

1. JDBC (Java Database Connectivity)

자바에서 데이터베이스에 접근하고 SQL을 실행할 수 있도록 지원하는 표준 API(인터페이스).

JDBC는 데이터베이스별로 제공되는 드라이버를 통해 실제 연결을 처리한다.

주요 구성 요소

  • Connection : 데이터베이스와의 연결 관리
  • Statement 또는 PreparedStatement : SQL 실행
  • ResultSet : 결과 처리.

2. MySQL과의 연동

JDBC 드라이버 설치

  • MySQL Connector/J 이걸 다운 받을 수도 있지만...
  • Maven/Gradle을 사용할 경우, 자동으로 라이브러리를 추가 가능
  • JDBC 드라이버 의존성 추가 (Maven 기준)
<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
</dependencies>

🔧 Maven

  • XML 기반 설정 파일(pom.xml) 사용
  • 구조와 방식이 정형화되어 있음 (표준화 잘 되어 있음)
  • 설정이 직관적이지만, 유연성은 떨어짐
  • 플러그인도 많고 안정적
  • 학습하기 쉬움

⚡Gradle

  • Groovy 또는 Kotlin DSL 기반 설정 (build.gradle 또는 build.gradle.kts) 사용
  • 유연하고 빠름 (빌드 속도 빠름, 캐싱 등)
  • 스크립트처럼 자유롭게 작성 가능
  • Android 개발에서는 사실상 표준
  • 러닝 커브가 약간 있지만, 최근 더 많이 사용됨

3. Statement

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 반환

MySQL에서 테이블 생성

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();
            }
        }
    }
}

4. PreparedStatement

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();
            }
        }
    }
}

5. try-with-resources

try 구문 안에서 선언한 AutoCloseable(또는 Closeable) 타입의 자원을 블록이 끝날 때 자동으로 close() 한다.

수동으로 finally 블록을 작성할 필요 없이 깔끔하고 안전하게 자원을 관리할 수 있다.

try (리소스 선언 및 초기화) {
    // 자원을 사용하는 코드
} catch (예외타입 e) {
    // 예외 처리
}
  • try 괄호 안에 여러 개의 자원을 세미콜론(;)으로 구분해 나열할 수 있다.
  • 블록을 벗어날 때, 선언된 자원들의 close()가 역순으로 자동 호출된다.
  • 자원이 null이 아닌 경우에만 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()로 억제된 예외 확인 가능
        }
    }
}
  • Connection, PreparedStatement, ResultSet 모두 AutoCloseable을 구현하므로 try(...)에 나열할 수 있다.
profile
The light shines in the darkness.

0개의 댓글