개발 일지

JDBC 동작원리

북극곰은콜라 2022. 11. 15. 20:30
반응형

JDBC란?

출처: https://dyjung.tistory.com/50

Java DataBase Connectivity

자바와 데이터베이스 간의 커뮤니케이션을 위한 API 및 드라이버

JDBC API를 통해 자바는 해당 인터페이스만 바라보고 개발하면 된다.

이하 DB와의 커뮤니케이션은 JDBC API의 구현체가 담당한다.


JDBC 동작원리 (JDK 11)

DriverManager

getConnection(...)

1. JDBC의 Driver interface의 구현체가 로드된 상태인지 체크한다.

 - 기본적으로 Driver의 구현체는 자체적으로 DriverManager에 등록되게끔 구현해놓았다.

   - 일반적으로 JDBC 가이드를 보면 Class.forName(...)을 통해 드라이버를 로드하도록 하는 이유이다.

 - driver가 로드 안되어있다면, System.property에서 jdbc.drivers를 찾아서 로드 가능한지 체크

 - 그 외 ServiceLoader에 로드된 드라이버를 체크

 - 체크 후 내부적으로 load flag를 true 처리

// mysql-connector-java
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
    static {
        try {
            java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
            throw new RuntimeException("Can't register driver!");
        }
    }
    
    ...
}

 

2. 로드된 드라이버(구현체)들에게 jdbcURL과 함께 connection을 요청한다. 이후 구현체에서 exception이 안 나면 스킵

 - connection 요청은 드라이버가 로드된 순서대로 진행된다.

 - 제일 먼저 받은 커넥션을 돌려준다. (이후 드라이버는 connect() 호출 안 함)

 

setLogWriter(java.io.PrintWriter out)

 - 로그를 쓸 writer 세팅


DataSource

DriverManager와 비슷한 Interface를 가지지만, DB Connection Factory로 보면 된다.

DriverManager와 다르게 register를 자동으로 구현하지 않는다. (DataSource 인스턴스 생성 시 connection을 위한 모든 정보를 받아서 생성)

Connection Config에 대한 부분을 인스턴스 생성 이후 set 할 수 있어야 한다.


Connection

DB와 Connection 이후 커뮤니케이션할 수 있는 인터페이스

주요 메서드로 DB와의 작업을 표현하고 있다.

 - createStatement()

 - prepareStatement(String sql)

 - nativeSQL(String sql)

 - setAutoCommit(boolean autoCommit)

 - commit()

 - rollback()

 - close()

 - setTransactionIsolation(int level)

...


실험

public static void main(String[] args) throws ClassNotFoundException, SQLException {
  System.out.println("start ------->>>>");
  DriverManager.setLogWriter(new PrintWriter(System.out));
  Class.forName("oracle.jdbc.driver.OracleDriver");
  Class.forName("com.mysql.cj.jdbc.Driver");

  Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Seoul", "****", "****");
  connection.close();

  connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Seoul", "****", "****");
  connection.close();

  System.out.println("end ------->>>>");
}

시스템 콘솔로 오라클 드라이버와 mysql 드라이버를 register 후

DriverManager에서 커넥션을 2번 받아오도록 코딩

start ------->>>>
registerDriver: oracle.jdbc.OracleDriver@880ec60
registerDriver: com.mysql.cj.jdbc.Driver@6a01e23
DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Seoul")
DriverManager.initialize: jdbc.drivers = null
JDBC DriverManager initialized
    trying oracle.jdbc.OracleDriver
    trying com.mysql.cj.jdbc.Driver
getConnection returning com.mysql.cj.jdbc.Driver
DriverManager.getConnection("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Seoul")
    trying oracle.jdbc.OracleDriver
    trying com.mysql.cj.jdbc.Driver
getConnection returning com.mysql.cj.jdbc.Driver
end ------->>>>

로그

 - 오라클 드라이버, mysql 드라이버 구현체가 DriverManager에 클래스 호출만으로 register 한다.

 - 최초 connection 호출 시 DriverManager가 initialized가 안 되어있는 로그 확인

 - DriverManager가 initialized 되는 로그 확인

 - Connection을 가져올 때 먼저 register 된 OracleDriver로 요청하고, 그 후 MysqlDriver에게 요청하는 것 확인

 - 두 번째 Conneciton 호출 시 DriverManager가 initialized 이기 때문에 바로 Driver들에게 Connection 요청


Conclusion

 - 기본적으로 java에서 쉽게 DB와 통신할 수 있도록 제공하는 interface이다.

 - Interface 스펙은 Java Community Process(https://jcp.org/en/home/index) 단체에서 정의한다.

 - JDBC의 버전은 jdk버전에 dependency가 있다.

JDBC 3.1 JDK 1.4
JDBC 4.0 JDK 1.6
JDBC 4.1 JDK 1.7
JDBC 4.2 JDK 1.8

 - DriverManager를 통해 Connection을 받아오고 Connection을 통해 DB와 작업을 진행한다.

 - DB와 상관없이 일관된 Interface를 제공해주는 이점이 있다.


reference

 - https://en.wikipedia.org/wiki/Java_Database_Connectivity

 - https://dyjung.tistory.com/50

반응형

'개발 일지' 카테고리의 다른 글

OIDC 란  (0) 2022.11.23
Logstash 란  (0) 2022.11.23
[외부자료] Java ClassLoader 요약 글  (0) 2022.11.22
JsonPath란  (0) 2022.11.22
HikariCP 동작원리  (0) 2022.11.16