강사님이 내주신 과제로 미니프로젝트를 하다 정리할 만한 내용이 생겨서 글을 썼다.
Provides the API for accessing and processing data stored in a data source (usually a relational database) using the Java programming language. This API includes a framework whereby different drivers can be installed dynamically to access different data sources. Although the JDBC API is mainly geared to passing SQL statements to a database, it provides for reading and writing data from any data source with a tabular format. The reader/writer facility, available through the javax.sql.RowSet group of interfaces, can be customized to use and update data from a spread sheet, flat file, or any other tabular data source.
간추려보자면, 해당 패키지는 보통 RDB에 저장된 데이터를 접근하거나 프로세싱하기 위해 제공한다.
또, 다양한 드라이버를 동적으로 설치(수업시간에 사용하는 mariadb-java-client-3.5.0.jar)하여 서로 다른 데이터 소스에 접근할 수 있는 프레임워크를 포함하고 있다.
주로 데이터베이스에 SQL 문을 전달하는 데 중점을 두고 있지만, 표 형식의 모든 데이터 소스에서 데이터를 읽고 쓸 수 있는 기능을 제공한다.
위 설명을 기억해두고 파일들을 구경해보면 Class 파일보다 Interface 파일이 3배정도 더 많다. 그 이유는 위에서 설명했듯이 각자의 데이터베이스 맞게 구현 되어있는 즉, 구체 클래스가 들어있는 라이브러리를 추가해서 사용한다.
많이 사용하는 DriverManager, Connection, Preparedstatement, ResultSet 클래스 및 인터페이스에 대해서 정리해보고자 한다.
데이터베이스에 연결을 구하는 방법은 DataSource 또는 DriverManager를 이용해서 정의한다.
DataSource는 JDBC 2.0부터 도입된 인터페이스로, 커넥션 풀링과 분산 트랜잭션 등 엔터프라이즈(기업용 서버) 환경에서 필요한 기능을 지원한다. javax.sql 패키지에 정의된 DataSource 인터페이스를 각 벤더(HikariCP, Apache DBCP, MariaDB 등)가 구현한 구현체를 사용하여 데이터베이스 연결을 관리한다.
DriverManager는 JDBC 1.0부터 제공된 구체 클래스로, 데이터베이스 드라이버를 등록하고 관리하는 역할을 한다. getConnection(url, user, password) 메서드는 등록된 드라이버들 중에서 주어진 URL을 처리할 수 있는 드라이버를 찾아 해당 드라이버의 Connection 구현체를 반환한다.
예를 들어, MariaDB JDBC 드라이버를 사용할 경우, DriverManager.getConnection()은 org.mariadb.jdbc.Connection 구현체의 인스턴스를 반환한다. 이 구현체는 java.sql.Connection 인터페이스를 구현하여 데이터베이스와의 실제 연결을 담당한다.
DriverManager
DataSource
커넥션 풀은 데이터베이스 연결을 미리 생성하고 보관하는 기법이다. 애플리케이션이 데이터베이스 연결을 요청할 때마다 새로운 연결을 생성하는 대신, 이미 생성된 연결을 재사용함으로써 다음과 같은 이점을 제공한다:
성능 향상
리소스 관리
안정성
Connection을 사용하기 이전에 Class.forName("org.mariadb.jdbc.Driver") 를 통해 해당 드라이버를 먼저 로드시키는 작업이 필요하다.
Class.forName()의 호출은
이렇게 해서 JDBC 드라이버가 로드되고 초기화된다.
JDBC 4.0 부터는 Class.forName() 호출이 필수는 아니게 되었다. 하지만, 하위 호환성을 위해 여전히 이 코드를 사용한다.
java.sql 의 Connection 클래스는 인터페이스이므로 따로 설명할 건 없고,
MariaDB JDBC 드라이버의 경우 해당 인터페이스를 구현한 Connection 구체 클래스를 제공한다.
MariaDB JDBC 에서 PreparedStatement의 구현체는 ClientPreparedStatement 와 ServerPreparedStatement 두가지가 존재한다. (BasePreparedStatement 추상 클래스도 존재함 → 이 클래스를 상속받아 구현)
어떤것을 사용할지의 결정은 쿼리의 특성과 드라이버의 설정에 따라 자동적으로 결정된다.
명시적으로 설정할 수 있지만, 대부분의 경우 드라이버가 자동으로 적절한 구현체를 선택하므로, 특별한 이유가 없으면 기본 설정을 권장한다.
→ ClientPreparedStatement 의 설명을 보면 Statement 와의 차이점이 살짝 모호해진 감이 있다. 하지만 보안성(Injection), 특수문자처리, 코드품질, 유지보수 측면에서 PreparedStatement 가 훨씬 뛰어나므로 사용이 권장된다.
위의 PreparedStatement 와 비슷하게 Result라는 추상메서드가 정의되어있고, 이것을 상속받아 CompleteResult와 StreamingResult 라는 2개의 구현체가 존재한다.
각각의 특징은
이것도 드라이버가 상황에 따라 적절한 구현체를 선택하므로, 개발자가 직접 구현체를 선택할 일은 거의 없다.