JDBC : Java Database Connectivity

Sixhustle·2020년 9월 10일
0

Java

목록 보기
4/10

JDBC란?

Java언어관계형 데이터베이스(RDBMS)에 접속하고, SQL문을 수행하여 처리하는 표준 SQL Interface API입니다.

JDBC는 Interface일 뿐, DBMS에 접속/실행을 위한 구현체는 각 Vendor에서 만든 Driver입니다.


MySQL Connector/J를 이용한 개발

import java.sql.*;

public class Main {

    public static void main(String[] args) {
        try (
                Connection connection = (new Main()).getConnection();
                Statement stmt = connection.createStatement();
                ResultSet rs = stmt.executeQuery("SELECT * FROM member LIMIT 2");
        ) {
            while (rs.next()) {
                Long id = rs.getLong("id");
                String name = rs.getString("name");
            }
        } catch (Exception e) {

        } finally {

        }
    }

    public Connection getConnection() throws Exception {
        String driver = "com.mysql.jdbc.Driver";
        String url = "jdbc:mysql://localhost:13308/jdbc";
        String username = "user";
        String password = "password";

        Class.forName(driver).newInstance();
        return DriverManager.getConnection(url, username, password);
    }
}

MySQL 서버 접속

Driver

아주 예전의 버전의 Connector/J가 아니라면, MySQL JDBC 드라이버 클래스는 항상 com.mysql.jdbc.Driver를 사용하면 됩니다.

JDBC URL

MySQL 서버 접속을 위해 JDBC URL을 설정해야 하는데, 선두 부분의 jdbc:mysql://은 고정된 값으로 JDBC URL임을 알려주는 프로토콜 역할을 합니다.
그 뒤에 IP주소나 도메인 네임, 포트 번호 그리고 사용할 DB명을 명시합니다.
위의 코드에는 없지만, 성능이나 작동 방식을 변경하기 위해 URL뒤에 Query Parameter를 붙일 수 있습니다.

Class.forName()

MySQL JDBC 드라이버 클래스를 동적으로 JVM으로 로딩시킵니다.
로딩이 완료되면, DrvierManager.getConnection() 명령을 이용해 Application이 MySQL 서버에 접속합니다.
DB Connection과 같은 네트워크 자원은 사용이 끝나면 즉시 해제하는 것이 좋습니다.(왜???)


Query 실행

SELECT 실행

MySQL 서버의 Connection이 준비되면 SELECT/INSERT 같은 SQL문을 실행할 수 있습니다.
Statement는 Query를 실행하고 결과를 참조하는 클래스인데, Query문에 따라 execute(), executeQuery(), executeUpdate()를 제공합니다.

  • executeQuery : ResultSet(Query의 결과)를 받아야할 때 사용합니다.
  • executeUpdate : ResultSet이 필요없는 INSERT/UPDATE/DELETE 또는 DDL 문장에 사용합니다.
  • execute : 실행하려는 쿼리가 어떤 것인지 모를 때 사용할 수 있습니다.

INSERT/UPDATE/DELETE 실행

SELECT 쿼리와는 달리 ResultSet을 반환하지 않으므로 Statement.executeUpdate() 함수를 사용해서 실행합니다.
executeUpdate함수는 Query문장에 의해 변경된 레코드 건수를 반환합니다.

Rollback

만약, 한 건의 DELETE Query에서 두 건 이상의 레코드가 삭제된다면 어떻게 해야할까?
문제가 될 수 있다면 변경된 레코드 건수를 반드시 체크해서 COMMIT 또는 ROLLBACK을 수행해주는 것이 좋습니다.

try (
	Connection connection = (new Main()).getConnection();
) {
    connection.setAutoCommit(false);
    Statement stmt = connection.createStatement();

    Integer affectedRows = stmt.executeUpdate("UPDATE member SET name='HUSTLE' WHERE id = 1");
    if (affectedRows == 1) {
        connection.commit();
    } else {
        connection.rollback();
    }
} catch (Exception e) {
	...
} finally {
    ...
}

MySQL에서는 매 쿼리가 정상적으로 실행되면 자동으로 트랙잭션이 commit됩니다.
이를 AutoCommit이라고 하는데, 별도로 모드를 변경하지 않았다면 매 쿼리마다 commit이 이뤄집니다. (commit이란?)
만약, 하나의 트랜잭션에 여러 개의 UPDATE, DELETE Query를 묶어서 실행하려면 AutoCommit 모드를 false로 설정해야 합니다.


Statement와 PreparedStatement

Statement

Statement로 실행되는 쿼리는 아래의 단계를 매번 거쳐서 실행됩니다.

쿼리 분석 > 최적화 > 권한 체크 > 쿼리 실행

PreparedStatement

PreparedStatement는 쿼리 분석이나 최적화의 일부 작업을 처음 한 번만 수행해 별도로 저장하고, 다음부터 요청되는 쿼리는 저장된 분석 결과를 재사용 합니다.
PreparedStatement는 Query의 분석 정보를 MySQL 서버의 메모리에 저장합니다.

만약, 아래처럼 WHERE절의 상수 값만 다른 쿼리가 100번 실행된다면 Statement는 100개의 분석 결과를 보관해야 합니다.

SELECT * FROM member WHERE name='member1';
SELECT * FROM member WHERE name='member2';
...
SELECT * FROM member WHERE name='member100';

하지만, PreparedStatement는 Query에 변수를 사용하여 쿼리의 분석 정보를 줄였고, 결국 MySQL 서버의 메모리 사용량을 줄일 수 있습니다.

SELECT * FROM member WHERE name=?;

PreparedStatement의 실행 시퀀스 다이어그램

  1. Application에서 실행하려는 쿼리와 함께 preparedStatement를 호출하면, MySQL 서버는 쿼리를 분석해서 별도로 저장하고, 분석 정보가 저장된 주소(Hash key)를 반환합니다.
  2. Application은 Query를 서버로 전달하지 않고, Hash key와 쿼리에 바인딩할 변수 값만 서버로 전달합니다.
  3. MySQL 서버는 분석 정보를 찾아 바인드 변수를 결합하고 쿼리를 실행합니다.

Reference

  • Real MySQL

0개의 댓글