본문 바로가기
JAVA

[JAVA] JDBC 기본 개념과 프로그래밍 단계

by Amy IT 2022. 6. 6.

▶ JDBC란?

 

JDBC(Java DataBase Connectivity)는 자바에서 표준화된 방법으로 데이터베이스에 접근할 수 있도록 하는 프로그래밍 API입니다. java.sql 패키지로 제공되는 JDBC API는 DBMS 종류에 상관없이 사용 가능하도록 대부분 몸체가 없는 인터페이스로 선언되어 있으며, 각 DBMS 회사에서는 이 인터페이스들을 구현한 클래스 파일들을 JDBC 드라이버로 묶어서 제공하고 있습니다. 자바 어플리케이션과 실제 데이터베이스가 연동하기 위해서는 각 DBMS 종류에 맞는 드라이버를 다운받아 사용해야 합니다. JDBC 프로그래밍으로 연동하는 과정을 다음과 같이 그려볼 수 있습니다.

 

 

 

 

▶ JDBC 환경설정

 

JDBC를 사용하기 위해 데이터베이스 서비스가 실행중인지 확인하고, 사용중인 DBMS 종류에 맞는 드라이버를 다운받아 클래스 패스에 설정하는 것이 필요합니다. 

 

제가 사용하는 오라클 11g xe 버전을 기준으로 살펴보겠습니다. 우선 작업관리자(ctrl + shift + esc)의 서비스에서 OracleServiceXE, OracleXETNSListener가 실행 중임을 확인할 수 있습니다.

 

 

오라클 드라이버는 오라클 데이터베이스를 설치할 때 자동으로 포함되어 설치됩니다. 오라클 11g xe 버전의 경우 다음의 경로에 ojdbc6_g.jar 파일명으로 제공됩니다. 

C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib

 

드라이버를 JRE System Library에 직접 추가하는 방법도 있지만, 저는 프로젝트 생성시 외부 라이브러리로 추가하는 방법을 이용해 보겠습니다. 프로젝트를 생성 후 우클릭하여 다음의 경로로 드라이버 파일을 추가해 줍니다. 

Build Path - Configure Build Path - Libraries - Add External JARs - 드라이버 선택 - Apply and Close

 

프로젝트에 Referenced Libraries가 추가된 것을 확인할 수 있습니다. 

 

 

 

 

▶ JDBC 프로그래밍 단계

 

다음은 JDBC를 구현하는 기본적인 프로그래밍 단계입니다. 

 

 

(1) 필요한 변수 선언 및 초기화

 

우선 데이터베이스 연동을 위한 네 가지 정보를 문자열에 저장합니다. 어떤 드라이버를 쓸 것이고, 어떤 DBMS를, 어느 계정으로 사용할 것인지에 대한 정보를 변수에 저장하는 작업입니다. 드라이버 내에 OracleDriver 클래스가 핵심이 되는 클래스 파일입니다. 접속할 DBMS의 주소는 현재 로컬 컴퓨터에 DBMS를 설치했기 때문에 localhost라고 지정하고, 오라클의 기본 포트번호인 1521번과, 11g xe 버전의 SID인 xe를 지정합니다. 마지막으로 접속하고자 하는 계정명과 비밀번호를 저장합니다. 

String driver = "oracle.jdbc.driver.OracleDriver";
String url = "jdbc:oracle:thin:@localhost:1521:xe";
String userid = "scott";
String passwd = "tiger";

 

데이터베이스 연동을 위해 필요한 객체도 선언합니다. 이후 반납해야 하는 자원들이므로 블록 바깥에서 선언해야 합니다.

Connection con = null;
Statement stmt = null; //또는 PreparedStatement
ResultSet rs = null;

 

 

 

(2) JDBC 드라이버 로딩

 

JDBC 드라이버 파일을 사용하기 위해 OracleDriver 클래스를 메모리에 올려야 합니다. 다음과 같은 방법으로 클래스 파일을 메모리에 로딩합니다. 

Class.forName(driver);

이때 forName() 메소드가 ClassNotFoundException을 던지고 있으므로 try~catch문으로 잡아야 합니다. 드라이버 파일을 클래스 패스에 설정하지 않았거나, 드라이버 이름을 잘못 지정한 경우 드라이버 로딩이 실패하여 예외가 발생하게 됩니다.

 

 

 

(3) DB 접속 - Connection

 

드라이버가 성공적으로 로딩되었다면 DB 서버와 연결해야 합니다. DriverManager 클래스의 getConnection() 메소드를 호출하며 접속할 DBMS의 주소와 계정 정보를 인자로 전달합니다. 이 정보를 이용해서 DB 연결에 성공하면 Connection 객체를 반환합니다. DB를 사용할 준비가 완료된 것입니다. 

con = DriverManager.getConnection(url, userid, passwd);

이때 getConnection() 메소드가 SQLException을 던지고 있으므로 마찬가지로 try~catch문으로 잡아야 합니다. 접속 정보를 잘못 지정한 경우 DB 접속에 실패하여 예외가 발생하게 됩니다. 이후 발생하는 예외들 역시 대부분 SQLException이므로 같은 catch블록으로 처리할 수 있게 됩니다.

 

 

 

(4) SQL 문 작성

 

자바에서 DB에 요청할 SQL문을 문자열로 저장합니다. 주의할 점은 SQL문 마지막에 세미콜론을 입력하지 않는다는 것입니다. dept 테이블의 모든 데이터를 검색하기 위한 SQL문입니다. 

String sql = "select * from dept";

 

 

 

(5) SQL 문 실행 후 결과값 얻기

 

자바에서 DB로 SQL문을 전송하고, DB에서 SQL문을 실행한 결과를 다시 자바로 받아오기 위해 Statement, PreparedStatement, 또는 CallableStatement 인터페이스를 사용합니다. Connection 객체의 createStatement() 메소드를 이용해 Statement 객체를 생성하고, prepareStatement() 메소드를 이용해 PreparedStatement 객체를 생성하고, prepareCall() 메소드를 이용해 CallableStatement 객체를 생성합니다. 여기서는 Statement 객체를 생성해 보겠습니다.

stmt = con.createStatement();

 

요청하는 SQL문에 따라서 Statement 객체가 제공하는 두 가지 메소드를 사용할 수 있습니다. 

 

SQL 종류 메소드 설명
DQL (SELECT) ResultSet executeQuery(String sql) DQL을 요청하여 SELECT한 결과값을 ResultSet 객체로 반환
DML (INSERT, UPDATE, DELETE) int executeUpdate(String sql) DML을 요청하여 변경된 레코드의 개수를 정수값으로 반환

 

executeQuery() 메소드를 사용해 SELECT문을 실행하고 실행한 결과를 ResultSet 객체로 반환받아 변수에 저장합니다. 테이블 형태의 SELECT한 결과를 자바의 객체로 표현한 것이 ResultSet 객체입니다. 

rs = stmt.executeQuery(sql);

 

 

 

(6) 데이터 출력

 

ResultSet 객체는 포인터를 이용해서 원하는 데이터를 얻을 수 있습니다. 포인터를 이용해서 레코드를 선택한 후, 포인터가 가리키는 레코드의 컬럼을 지정해서 데이터를 얻습니다. next() 메소드는 다음 레코드가 있는지 여부를 boolean 값으로 반환하고 다음 레코드로 포인터를 이동시킵니다. 컬럼의 데이터 타입에 따른 getXXX("컬럼명") 메소드로 데이터를 얻을 수 있으며, 컬럼명 대신 컬럼의 위치값(1부터 시작) 사용도 가능합니다. 컬럼에 alias를 지정한 경우에는 컬럼명 사용은 불가능합니다. 

while (rs.next()) {
	int deptno = rs.getInt("deptno");
	String dname = rs.getString("dname");
	String loc = rs.getString("loc");
	System.out.println(deptno+"  "+dname+"  "+loc);
}

 

 

 

(7) 자원 반납

 

파일 및 데이터베이스는 자바에서 사용하는 외부 자원이기 때문에 사용 후 반드시 자원을 해제해야 합니다. 사용한 역순으로 자원을 해제하며, 예외가 발생하든 발생하지 않든 항상 자원을 반납해야 하므로 finally 문으로 자원 반납 코드를 구현합니다.

if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (con != null) con.close();

어떤 작업이 실패하거나 변수를 초기화하지 않아 해당 변수가 null인 경우가 있을 수 있습니다. 이때 null값을 가지고 close() 메소드를 호출하게 되면 NullPointerException이 발생하기 때문에 null이 아닌 경우에만 close() 메소드를 호출하도록 조건식을 지정해 주어야 합니다. 또한, close() 메소드도 SQLException을 던지고 있기 때문에 finally 블록에서도 다시 try~catch 문으로 잡아주어야 합니다. 

 

 

 

이상의 과정을 구현하면 다음과 같습니다. 일반적으로 모든 작업을 한 클래스만으로 작성하지는 않지만, 실습을 위해 한 클래스로 종합해 보겠습니다. 

import java.sql.*;
public class JDBCTest {
	public static void main(String[] args) {
		//1.필요한 변수 선언 및 초기화
		String driver = "oracle.jdbc.driver.OracleDriver"; //드라이버 
		String url = "jdbc:oracle:thin:@localhost:1521:xe"; //접속정보
		String userid = "scott"; //접속계정
		String passwd = "tiger"; //패스워드 
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		try { //2.JDBC 드라이버 로딩
			Class.forName(driver);
			System.out.println("드라이버 로딩 성공");
			//3.DB 접속 - Connection
			con = DriverManager.getConnection(url, userid, passwd);
			System.out.println("DB 접속 성공");
			//4.SQL 문 작성
			String sql = "select * from dept";
			//5.SQL 문 실행 후 결과값 얻기
			stmt = con.createStatement();
			rs = stmt.executeQuery(sql);
			//6.데이터 출력
			while (rs.next()) {
				int deptno = rs.getInt("deptno");
				String dname = rs.getString("dname");
				String loc = rs.getString("loc");
				System.out.println(deptno+"  "+dname+"  "+loc);
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			System.out.println("드라이버 로딩 실패");
		} catch (SQLException e) {
			e.printStackTrace();
		} finally { //7.자원 반납
			try {
				if (rs != null) rs.close();
				if (stmt != null) stmt.close();
				if (con != null) con.close();
				System.out.println("자원반납 완료");
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

 

 

이상으로 JDBC의 기본 개념과 기본적인 프로그래밍 단계를 알아보았습니다.

 

 

'JAVA' 카테고리의 다른 글

[JAVA] JDBC - DAO, DTO 패턴  (0) 2022.06.09
[JAVA] JDBC - PreparedStatement  (0) 2022.06.07
[JAVA] 컬렉션 - Map 계열  (0) 2022.06.04
[JAVA] 컬렉션 - ArrayList  (0) 2022.06.02
[JAVA] 컬렉션 - Set 계열  (0) 2022.06.01

댓글