JDBC(Java DataBase Connectivity)는 자바로 데이터베이스에 접근하여 SQL문을 수행할 수 있도록 하는 API이다.
전에는 오라클, MySQL 등 DBMS마다 구조와 특징이 다르기 때문에 자바가 DB에 접근하는 방식이 각각 다를 수 밖에 없었다. 이에 모든 DBMS에서 사용 가능한 인터페이스와 클래스로 구성된 JDBC가 등장하게 되었다. 이제는 각 DBMS에 맞는 JDBC 드라이버를 연결해서 사용하면 된다.
JDBC로 자바 애플리케이션을 작성하기 위해서는 JDBC가 포함되어있는 java.sql 패키지를 import하고, 아래와 같은 과정이 필요하다. 아래의 예시 코드는 오라클 DBMS를 사용했다.
첫 번째, JDBC 드라이버를 메모리에 로드하기.
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException cnfe) {
cnfe.PrinStackTrace();
}
Class의 정적 메서드인 forName()은 매개변수로 오는 OracleDriver 클래스를 메모리에 로드할 수 있게 한다.
그런데 forName() 메서드는 실행할 때 매개변수 안의 클래스를 찾지 못할 경우 ClassNotFoundException을 발생시키므로 위의 코드처럼 예외 처리를 해야 한다.
두 번째, 데이터베이스에 연결해 Connection 객체 생성하기.
try {
String url = "jdbc:oracle:thin:@localhost:1521:xe";
Connection con = DriverManager.getConnection(url, "user", "1234");
} catch (SQLException se) {
se.printStackTrace();
}
DriverManager 클래스의 정적 메서드 getConnection()을 이용해서 Connection 객체를 얻어 오면 DBMS와 연결된 상태가 된다. 위의 getConnection() 메서드는 데이터베이스의 위치를 나타내는 url, 사용자 ID, 비밀번호를 인수로 가진다. 만약 getConnection() 메서드가 Connection 객체를 생성하지 못한다면 SQLException을 발생시키므로 예외처리를 한다.
세 번째, SQL문을 DBMS에 전송할 수 있는 Statement 객체 생성하기.( + ResultSet 객체 생성)
try {
Statement stmt = con.createStatement();
String sql = "SELECT * FROM DEPT"
ResultSet rs = stmt.executeQuery(sql);
} catch (SQLException se) {
se.printStackTrace();
}
위의 코드는 데이터베이스의 DEPT 테이블을 조회하는 쿼리문을 DBMS에 전송하고 실행하는 부분이다.
SQL문을 전송할 수 있는 Statement 객체는 Connection 인터페이스의 createStatment() 메서드를 사용하여 얻을 수 있다. Statement 객체를 생성하지 못할 경우 SQLException을 발생시킬 수 있기 때문에 예외 처리를 해야 한다.
Statement 인터페이스에는 SELECT문을 전송하는 executeQuery()와 SELECT문 이외의 SQL문을 전송하는 executeUpdate() 메서드 등이 있다. 위의 코드처럼 executeQuery()는 SELECT문의 결과를 ResultSet 객체로 반환하는데, executeUpdate()는 갱신된 행의 수를 반환한다는 점에서 차이가 있다.
네 번째, 결과물 처리하기.
try {
Statement stmt = con.createStatement();
String sql = "SELECT * FROM dept"
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
int deptno = rs.getInt("deptno");
String dname = rs.getString("dname");
String loc = rs.getString("loc");
System.out.printf("%5d\t%-15s%s\n", deptno, dname, loc);
}
} catch (SQLException se) {
se.printStackTrace();
}
ResultSet 인터페이스는 SQL문의 결과물을 추상화하므로 SQL문 실행 결과물이 있다면 ResultSet 객체를 생성한다.
ResultSet는 하나의 행을 지시하는 커서(Cursor)를 사용하기 때문에 next() 혹은 previous() 메서드를 호출하여 원하는 행의 위치로 이동해 결과물을 가져올 수 있다. 두 메서드는 boolean형으로 이동하는 행의 결과물이 있으면 true, 없으면 false를 반환한다.
next()와 previous() 메서드가 커서의 위치를 이동시킨다면, 결과물을 가져오는 메서드에는 대표적으로 getInt(), getString() 메서드가 있다. 현재 행에서 주어진 열의 값을 각각 int, String 타입으로 반환한다.
위의 코드는 next()를 반복문으로 처리해서 값을 가져오고 출력하고 있다.
마지막, 객체들 닫아주기.
Connection, Statement, ResultSet 객체들은 사용이 끝난 후 close() 메서드 호출하여 닫아준다.
위의 과정을 모두 정리하면 아래와 같다.
import java.sql.*;
public class Select {
public static void main(String[] args) {
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
String url = "jdbc:oracle:thin:@localhost:1521:xe";
con = DriverManager.getConnection(url, "user", "1234");
stmt = con.createStatement();
String sql = "SELECT * FROM DEPT";
rs = stmt.executeQuery(sql);
while (rs.next()) {
int deptno = rs.getInt("deptno");
String dname = rs.getString("dname");
String loc = rs.getString("loc");
System.out.printf("%5d\t%-15s%s\n", deptno, dname, loc);
}
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
} catch (SQLException se) {
se.printStackTrace();
} finally {
try {
if (rs != null)
rs.close();
if (stmt != null)
stmt.close();
if (con != null)
con.close();
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}
}
댓글