JSP/서블릿 흝어 보기

JDBC 프로그래밍

JDBC란?

JDBC란, 자바 언어로 다양한 종류의 관계형 데이터베이스에 접속하고 SQL문을 수행하여 처리하고자 할 때 사용되는 표준 SQL 인터페이스 API입니다. JDBC는 자바의 표준 에디션에서 지원하는 기술로서, 접속하려는 DBMS 서버에 따라서 JDBC 드라이버가 필요합니다. 

JDBC 기술로 구현하는 자바 프로그램의 연동과정은 다음과 같다.

JDBC프로그램 - JDBC인터페이스 - JDBC드라이버 - DB

(1) JDBC 인터페이스

JDBC 인터페이스는 JDBC 프로그램을 하기 위한 API들로서, SE에서 제공하는 java.sql 패키지를 의미합니다.  JDBC 프로그램을 구현할 때 실제로 사용하는 객체들은 대부분 몸체가 없는 인터페이스 입니다.

(2)  JDBC 드라이버

그러므로 실제 DB관련 기능이 동작하려면 이 인터페이스 만으로는 작업할 수 없습니다. 그렇기 떄문에 java.sql의 인터페이스들을 상속하여 메소드의 몸체를 구현한 클래스 파일들이 필요하며 이 파일들을 JDBC 드라이버라고 한다.

JDBC프로그램을 위해서는 우선 JDBC 드라이버가 준비되어 있어야 한다. JDBC드라이버는 DB가 설치된 폴더 또는 사용하는 DB를 제공하는 벤더사의 홈페이지에서 내려받을 수 있습니다. 여기서는 오라클의 JDBC드라이버를 사용합니다.

JDBC드라이버를 가져왔으면 웹애플리케이션에서 자동으로 인식할 수 있도록 해줘야 한다. 자동으로 인식되는 곳은 두 군데이다. 첫째는 WAS가 설치된 HOME 폴더 및의 lib 폴더이고, 둘째는 각 웹 애플리케이션/WEB-INF/lib 폴더에 저장해야 합니다. WAS_HOME/lib에 저장하면 WAS에서 실행되는 모든 웹 애플리케이션에서 사용할 수 있으며, /WEB-INF/lib 폴더에 저장하면 해당 웹 애플리케이션에서만 사용할 수 있습니다.

여기서는 WAS가 설치된 HOME 폴더의 lib 폴더에 JDBC 드라이버를 저장합니다.

구현하기

(1) JDBC 드라이버 로딩

JDBC 프로그램을 위해 가장 먼저 해야할 것은 데이터베이스 작업을 위해 준비된 JDBC 드라이버 파일을 사용할 수 있도록 메모리에 로딩해야 한다. 사용방법은 다음과 같다.

Class.forName("oracle.jdbc.driver.OracleDriver");

JDBC 드라이버를 메모리에 동적으로 로딩하기 위해서는 Class.forName( )을 이용합니다. forName( ) 메소드의 인자값으로는 JDBC 드라이버 파일 안에서 드라이버 인터페이스를 상속하고 있는 클래스이름을 패키지 이름과 함께 정확하게 명시해주어야 합니다.

Class.forName( )에 의해 JDBC 드라이버 파일의 드라이버 인터페이스를 상속한 클래스가 동적으로 로딩될 때 자동으로 JDBC 드라이버 인스턴스가 생성되어 준비가 완료됩니다.

(2) DBMS 서버 접속

JDBC 드라이버의 사용준비가 완료되면 첫 번째 DB작업으로 DB서버와의 연결작업을 합니다. 이 작업은 java.sql 패키지의 DriverManager 클래스의 getConnection( ) 메소드를 이용합니다. 

Connection conn = DriverManager.getConnection
                  ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger");

getConnection 메소드의 인자 값은 다음과 같다.

  • String url : 접속할 서버의 URL이며, 프로토콜, 서버주소,서버포트, DB이름으로 구성된다.
  • String user : DB서버에 로그인할 계정
  • String password : DB서버에 로그인할 비밀번호

DriverManager.getConnection( ) 실제 자바 프로그램과 데이터베이스를 네트워크상에서 연결해주는 메소드이며 에 성공하면 DB와 연결된 상태를 Connection 객체로 표현하여 반환합니다.

(3) Statement

위에서 만든 Connection을 자바 프로그램과 DB 사이에 연결이 되었다면 이 연결을 통해 자바프로그램은 DB 쪽으로 SQL 문을 전송하고, DB는 처리된 결과를 다시 자바프로그램 쪽으로 전달해야 합니다. 바로 이 역활을 하는 객체가 Statement입니다.

Statement 생성하기

Statement 객체를 생성하려면 Connection 객체가 제공하는 createStatement( ) 메소드를 사용합니다.

Statement stmt = conn.createStatement();

DB로 SQL문을 요청하기 위해 생성하는 객체는 Statement 외에도 PreparedStatement 객체도 있습니다. 책에서는 PreparedStatement로 SQL을 작성할때 가독성과 유지보수성이 좋다고 설명하고 있습니다. 사실 현업에서는 PreparedStatement를 사용하므로써 얻는 장점이 너무도 많습니다.

그러므로 PreparedStatement에 대해서는 별도의 토픽으로 다루고자 합니다!!

(4) SQL문 실행

이번에는 Statement 객체를 이용해 DB서버로 SQL문을 전송하고 처리 결과를 받아올 것 입니다. 

SQL문을 실행하기 위해 Statement 객체에서 제공되는 메소드는 다음과 같습니다.

  • ResultSet executeQuery(String sql)
    executeQuery( ) 메소드가 반환하는 ResultSet은 select한 결과값을을 가지고 있습니다.
  • int executeUpate(String sql)
    executeUpdate( ) 메소드가 반환하는 숫자값은 SQL문이 실행된(update,delete,insert) 후 영양받은 레코드의 개수입니다.

ResultSet

ResulSet은 executeQuery( ) 메소드에서 실행된 select 문의 결과값을 가지고 있는 객체입니다.

ResultSet rs = stmt.executeQuery("select * from test");

위와 같은 SQL명령문을 실행했을 때 ResultSet 객체 rs가 가지는 값은 다음과 같다.

커서 ID PWD  
    시작빈행
  aa 11  
  bb 22  
      끝 빈행

ResultSet 객체가 가지고 있는 select 결과값은 ResultSet 객체의 메소드를 활용해 추출하여 사용합니다. ResultSet 객체의 특징은 내부적으로 위치를 나타내는 커서(Cursor)라는 개념이 있습니다. 

다음의 ResultSet 객체의 메소드들은 이 커서의 위치를 이동시킵니다.

  • void afterLast( )
    커서를 끝 빈 행으로 위치시키는 메소드 입니다.
  • void beforeFirst( )
    커서를 시작 빈행으로 위치시키는 메소드 입니다.
  • boolean next( )
    커서 다음에 레코드가 있는지 판단하여 없으면 false, 있으면 true를 반환하 다음에 커서를 다음 레코드로 이동 시킵니다.

이외에도 ResultSet 객체에는 현재 이동한 커서의 컬럼의 값을 데이터 타입에 따라 추출하는 getter 메소드를 가지고 있습니다. getter 메소드의 인자값으로는 칼럼의 이름을 지정할 수도 있고, 칼럼의 인덱스 값을 지정할 수도 있습니다. 칼럼의 인덱스는 ResultSet 결과값으로 나타난 칼럼의 순서라고 생각하면 됩니다.

  • String getString(int columnInde);
  • String getString(String columnLabel);

(5) 자원해제

앞에서 DB 관련처리 작업을 하면서 다음의 객체들을 사용했습니다.

  • Connection : DB 연결 객체
  • Statemet 또는 PreparedStatement 객체 : SQL 문 실행 객체
  • ResultSet 객체 : select 문 결과를 가지는 객체

이 객체들을 이용해 DB관련 처리 작업이 완료된 다음에는 사용했던 객체들을 메모리에서 해제해주어야 합니다. 해제하는 순서는 최근에 사용했던 객체부터 거꾸로 올라가며 해제합니다.

  • rs.close( )
  • stme.close( ) 또는 pstmt.close( )
  • conn.close( )

실습

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.sql.*" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
//1. JDBC 드라이버 로딩하기
Class.forName("oracle.jdbc.driver.OracleDriver");

//2. DB 서버 접속하기
String url = "jdbc:oracle:thin:@localhost:1521:xe";
Connection conn = DriverManager.getConnection(url,"scott","tiger");

//3. Statement or PreparedStatement 객체 생성하기
Statement stmt = conn.createStatement();

//4. SQL 실행
//'test' 테이블 생성
//stmt.executeUpdate("create table test(id varchar2(5), pwd varchar(5))");
/*
//행 삽입
stmt.executeUpdate("insert into test values('aa','11')");
stmt.executeUpdate("insert into test values('bb','22')");
stmt.executeUpdate("insert into test values('cc','33')");
*/

//select
ResultSet rs = stmt.executeQuery("select * from test");

while(rs.next()){
    out.println("<br>" + rs.getString("id")+":"+rs.getString(2));	
}

//5. 자원해제
rs.close();
stmt.close();
conn.close(); // 연결해제
%>

</body>
</html>

댓글

댓글 본문
  1. DongHyun Kim
    저도 감사합니다!!
    대화보기
    • spexle
      감사합니다ㅎㅎ
      정리가 너무 잘되어있네요! 좋은 자료 감사합니다~
    • DongHyun Kim
      도움이 되어 기쁩니다!
      대화보기
      • 대한설탕
        정리가 매우 잘 되어 있는 것 같습니다. 웹서버 노트를 작성하고 있는데 많이 참고할게요!!
      • 글쓴이
        감사합니다!
        대화보기
        • ㅇㅇ
          정리가 너무잘되있네요