Skip to content

JDBC

Java에서 DB와 연결되어 데이터를 주고받을 수 있도록 제공하는 API
JDBC의 경우 대부분의 API가 인터페이스이다
API들을 상속하여 구현하는 자식 클래스가 필요한데, 그 자식 클래스들을 JDBC 드라이버가 제공한다

  • JDBC URL : 접속할 DB 서버와 사용할 드라이버 정보를 담고 있는 주소 문자열
    jdbc:DB서버공식이름:JDBC드라이버에대한정보(드라이버에 전달할 정보)
    graph LR
    A[애플리케이션] --> B[JDBC 인터페이스]
    B --> O[Oracle JDBC Driver];
    B --> M[MySQL JDBC Driver];
    B --> Ma[MariaDB JDBC Driver]
    
    O --> OI["<img src='https://icons.terrastruct.com/dev%2Foracle.svg' width='70' height='70'>"]
    M --> MI["<img src='https://icons.terrastruct.com/dev%2Fmysql.svg' width='70' height='70'>"]
    Ma --> MaI["<img src='https://icons.terrastruct.com/aws%2FDatabase%2FAmazon-RDS_MariaDB_instance_light-bg.svg' width='70' height='70'>"]

JDBC API

  • 클래스
    • DriverManager : JDBC를 Driver 관리, DB와 연결해서 Connection 구현 객체 생성
    • Date, Time, Timestamp
  • 인터페이스
    • Connection : Statement, PreparedStatement, CallableStatement 구현 객체 생성, 트랜잭션 처리 및 DB 연결 끊을 때 사용
    • Statement : SQL의 DDL, DML을 실행할 때 사용 (주로 변경되지 않는 정적 SQL문 실행)
    • PreparedStatement : 매개변수화된 SQL 문을 사용할 수 있어 Statement에 비해 편리성과 보안성 향상
    • CallableStatement : DB에 저장되어 있는 프로시저와 함수 호출 시 사용
    • ResultSet : DB에서 가져온 데이터 읽을 때 사용
    • DatabaseMetaData, ResultSetMetaData

Example code

// DriverManager로 사용할 DB의 Driver를 메모리로 로딩 (이제는 필요없는 코드)
Class.forName("com.mysql.cj.jdbc.Driver"); 

// DB 연결 정보 입력 및 DB 연결
String url = "jdbc:mysql:...";
String user = "username";
String passwd = "password";
Connection conn = DriverManager.getConnection(url, user, passwd); 

// DB 서버에 SQL 명령을 전달하여 실행시키기 위한 Statement 객체 생성
Statement stmt conn.createStatement(); 

// SELECT 명령을 실행, 결과는 JDBC 드라이버가 ResultSet이라는 객체로 반환
ResultSet rs = stmt.excuteQuery("SELECT ename, sal FROM emp"); 

// 데이터 꺼내오기
rs.next()
String name = rs.getString("ename"); // = rs.getString(1)
int salary = rs.getInt("sal"); // = rs.getInt(2)

//커넥션 반환
rs.close(); 
stmt.close();
conn.close();

Method VS Method

  • executeQuery : 테이블 조회, ResultSet 객체 반환 (결과가 없다면 비어있는 객체 반환)
  • executeUpdate() : 테이블 업데이트, 리턴값은 int(변경된 행의 수)
  • PreparedStatement : 동적 SQL 쿼리 실행. 미리 컴파일된 쿼리를 사용하고 매개 변수를 전달하여 사용한다
  • Statement : 정적 SQL 쿼리 실행. 매번 쿼리 문자열이 재구성되어야하며 재사용하기 어렵다
    두 번째 매개값은 DML문이 실행된 후 가져올 키 값
    바이너리 타입(blob)일 때는 setBinaryStream(), setBlob(), setBytes () 중 하나 택

ResultSet

SELECT문에 기술된 컬럼으로 구성된 행의 집합
커서가 있는 행의 데이터만 읽을 수 있다 (최초 커서는 beforeFirst를 가리키므로 next() 메소드 사용)

데이터 조회 SELECT - Statement, executeQuery

...(생략)
    try (Connection connection = DriverManager.getConnection(jdbcURL, username, password);
            Statement statement = connection.createStatement()) {

        String sql = "SELECT * FROM employees";
        ResultSet resultSet = statement.executeQuery(sql);

        if (resultSet.next()){
            do {
                int id = resultSet.getInt("id");
                String name = resultSet.getString("name");
                System.out.println("ID: " + id + ", Name: " + name);
            } while (resultSet.next())
        } else System.out.print("조회 결과가 없습니다.");
    } catch (SQLException e) {
        e.printStackTrace();
    }

데이터 삽입 INSERT - PreparedStatement, executeUpdate

...(생략)
    try (Connection connection = DriverManager.getConnection(jdbcURL, username, password);
            PreparedStatement preparedStatement = connection.prepareStatement("INSERT INTO employees (name, age) VALUES (?, ?)")) {

        String newName = "John Doe";
        preparedStatement.setString(1, newName);
         preparedStatement.setString(2, 23);

        int rowsAffected = preparedStatement.executeUpdate();
        if (rowsAffected > 0) {
            System.out.println("Insertion successful.");
        } else {
            System.out.println("Insertion failed.");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }

데이터 수정 UPDATE

...(생략)
    try (Connection connection = DriverManager.getConnection(jdbcURL, username, password);
            PreparedStatement preparedStatement = connection.prepareStatement("UPDATE employees SET name = ? WHERE id = ?")) {

        String updatedName = "Updated Name";
        int employeeId = 1;

        preparedStatement.setString(1, updatedName);
        preparedStatement.setInt(2, employeeId);

        int rowsAffected = preparedStatement.executeUpdate();
        if (rowsAffected > 0) {
            System.out.println("Update successful.");
        } else {
            System.out.println("Update failed.");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }

데이터 수정 UPDATE

...(생략)
    try (Connection connection = DriverManager.getConnection(jdbcURL, username, password);
            PreparedStatement preparedStatement = connection.prepareStatement("DELETE FROM employees WHERE id = ?")) {

        int employeeIdToDelete = 1;
        preparedStatement.setInt(1, employeeIdToDelete);

        int rowsAffected = preparedStatement.executeUpdate();
        if (rowsAffected > 0) {
            System.out.println("Deletion successful.");
        } else {
            System.out.println("Deletion failed.");
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }

트랜잭션


Data Type

1


Note

Java와 DB의 연동

  • JDBC
  • Mybatis(iBatis)
  • JPA

객체 생성

일반 클래스의 객체 생성은 new와 생성자 메서드를 사용한다
일반적인 객체 생성 방식 대신 static형 메서드를 호출하여 생성할 수도 있다

  • 여러 이유로 자식 클래스의 객체 생성을 대신하여 사용되도록 하려는 경우
  • 클래스의 객체 생성을 여러번 하더라도 하나의 객체만을 생성하려는 경우

추상 클래스인터페이스의 경우에는 new/생성자 메서드 대신 자식 클래스를 만들어 대신 객체를 생성하여 사용한다
JDBC의 경우 대부분의 API가 인터페이스이다


MVC (Model View Controller)

프로그램을 개발할 때 역할을 나눠서 개발하는 패턴 - Model - Domain Model(DTO, VO, Entity) : 변경은 DTO, 조회는 VO - Service Model(DAC) : Data Access Object - View : 사용자(User)와의 인터페이스 --> JSP, Thymeleaf, Vue.js - Controller : Model과 View 사이에서 여러 다양한 역할을 담당하는 객체 (비즈니스로직) --> Servlet

-- Java Application : JVM에 의해 단독으로 수행되는 프로그램 -- Java Android App : 안드로이드 운영체제에서 수행되는 심플한 프로그램 -- Java Servlet : 웹 서버에서 수행되는 자바 프로그램 (-> MVC!)


Quote

  • 이것이 자바다 특별판 부록(저자: 신용권 | 출판사: 한빛미디어)
  • MSA 3기
  • OpenAI