본문 바로가기

[JSP]

12.데이터베이스 프로그래밍 기초

1) JSP에서 JDBC 프로그래밍하기

자바에서 데이터베이스를 사용할 때에는 JDBC API를 이용해서 프로그래밍을 한다.

JDBC는 Java DataBase Connectivity의 약자로서 자바에서 데이터베이스와 관련된 작업을 처리할 수 있도록 도와주는 API이다.

자바는 DBMS의 종류에 상관없이 하나의 JDBC API를 사용해서 데이터베이스 작업을 처리 할 수 있다.

 

(1)JDBC의 구조

JSP를 비롯한 자바 기반의 어플리케이션에서 데이터베이스를 사용할 때에는 데이터베이스 종류에 상관없이 JDBC API를 이용해서 데이터베이스에 접근하게 된다. 각각의 DBMS는 자신에게 알맞은 JDBC 드라이버를 제공하고 있으며, JDBC API는 JDBC 드라이버를 거쳐 데이터베이스와 통신을 한다.

 

(2)JDBC 드라이버 준비하기

JDBC 프로그래밍을 하기 위해서는 사용할 DBMS에 알맞은 JDBC 드라이버를 준비해야 한다. 

JDBC 드라이버는 클래스 형태로 존재하며 일반적으로 Jar파일로 제공된다.

웹 어플리케이션 디렉터리의 WEB-INF\lib 디렉터리에 JDBC 드라이버 파일을 복사해서 웹 어플리케이션에서 JDBC 드라이버를 사용할 수 있도록 한다.

 

(3)JDBC 프로그래밍의 코딩 스타일

JDBC 프로그램의 일반적인 실행 순서는 다음과 같다.

①JDBC 드라이버 코딩한다.

②데이터베이스 커넥션을 구한다.

③쿼리 실행을 위한 Statement 객체를 생성한다.

④쿼리를 실행한다.

⑤쿼리 실행 결과를 출력한다.

⑥Statement를 종료한다.

⑦데이터베이스 커넥션을 종료한다.

 

예제)viewMemberList.jsp

<%@ page contentType="text/html; charset=euc-kr" %>

<%@ page import="java.sql.DriverManager" %>
<%@ page import="java.sql.Connection" %>
<%@ page import="java.sql.Statement" %>
<%@ page import="java.sql.ResultSet" %>
<%@ page import="java.sql.SQLException" %>

<html>
<head><title>회원 목록</title></head>
<body>
MEMBER 테이블의 내용
<table width="100%" border="1">
<tr>
     <td>이름</td><td>아이디</td><td>이메일</td>
</tr>
<%
     //1.JDBC 드라이버 코딩
     Class.forName("oracle.jdbc.driver.OracleDriver);
     
     Connection conn = null;
     Statement stmt = null;
     ResultSet rs = null;
     
     try {
          String jdbcDriver = "jdbc:oracle:thin:@localhost:1521:XE";
          String dbUser = "userName";
          String dbPass = "userPassword";

          String query = "select * from MEMBER order by MEMBERID";

          //2. 데이터베이스 커넥션 생성
          conn = DriverManager.getConnection(jdbcDriver, dbUser, dbPass);

          //3.Statement 생성
          stmt = conn.createStatement();

          //4. 쿼리 실행
          rs = stmt.executeQuery(query);

          //5. 쿼리 실행 결과 출력
          while(rs.next()) {
%>

<tr>
      <td><%=rs.getString("NAME"); %></td>
      <td><%=rs.getString("MEMBERID"); %> </td>
      <td><%=rs.getString("EMAIL"); %> </td>
</tr>

<%
            }
      } catch(SQLException ex) {
            out.println(ex.getMessage());
            ex.printStackTrace();
      } finally {
            //6.사용한 Statement 종료
            if(rs != null) try { rs.close(); } catch(SQLException ex) {}
            if(stmt != null) try {stmt.close(); } catch(SQLException ex) {}

            //7.커넥션 종료
            if(conn != null) try {conn.close(); } catch(SQLException ex) {}
      }
%>
</table>
</body>
</html>

실행 하기 전에 다음의 내용을 확인한다.

  • WEB-INF\lib 디렉터리에 JDBC 드라이버를 복사했는지 여부
  • 데이버베이스 생성 여부
  • 데이터베이스에 MEMBER 테이블 생성 여부

위의 코드를 실행하면 다음과 같은 결과가 출력된다.

vieMemberList.jsp 실행 결과

 

(4)DBMS와의 통신을 위한 JDBC 드라이버

JDBC 드라이버는 DBMS와의 통신을 담당하는 자바 클래스로서 DBMS마다 별도의 JDBC 드라이버가 필요하다.

JDBC 드라이버를 로딩해야 데이터베이스에 연결해서 원하는 작업을 수행할 수 있으며,

JDBC 드라이버를 로딩하는 방법은 다음과 같다.

try {
	Class.forName("JDBC드라이버 클래스의 완전한 이름");
} catch(ClassNotFoundException ex) {
	// 지정한 클래스가 존재하지 않을 경우 에러가 발생한다.
    //에러 처리
}

 

다음은 주요 데이터베이스에 대한 JDBC 드라이버에 해당하는 클래스이다.

  • MySQL: com.mysql.jdbc.Driver
  • 오라클: oracle.jdbc.driver.OracleDriver
  • MS SQL 서버: com.microsoft.sqlserver.jdbc.SQL.ServerDriver

Class.forName() 메서드는 지정한 클래스 정보를 담고 있는 Class 인스턴스를 구해주는 기능만을 제공한다.

실제로 JDBC 드라이버에 해당하는 클래스들은 Class.forName() 메서드를 통해서 로딩될 때 자동으로 JDBC 드라이버로 등록 해주기 때문에 Class.forName() 메서드를 사용해서 JDBC 드라이버를 등록하는 것이다.

(5)데이터베이스 식별을 위한 JDBC URL

각각의 웹사이트를 구분할 때 URL을 사용한다. 이와 비슷하게, 데이터베이스를 구분할 때에도 URL과 비슷한 형식을 취하는 JDBC URL을 사용한다.

JDBC URL은 사용하는 JDBC 드라이버에 따라서 표현 방식에 차이가 있는데 일반적인 형식은 다음과 같다.

jdbc:[DBMS]:[데이터베이스식별자]

예를 들어 오라클 JDBC 드라이버는 다음과 같은 JDBC URL을 사용한다.

jdbc:oracle:thin:@HOST:PORT:SID

여기서 HOST, PORT는 각각 오라클이 설치된 호스트의 주소와 포트 번호를 나타내며, SID는 사용할 데이터베이스의 SID를 나타낸다.

 

(6)데이터베이스 커넥션

데이터베이스 프로그래밍을 하기 위해서는 먼저 데이터베이스와 연결된 커넥션을 구해야 한다.

 

java.sql.Connection 클래스가 데이터베이스 커넥션을 나타내며,

커넥션은 java.sql.DriverManager 클래스가 제공하는 getConnection() 메서드를 사용해서 구할 수 있다.

DriverManager 클래스는 다음과 같은 두 개의 getConnection() 메서드를 제공하고 있다.

  • DriverManager.getConnection(String jdbcURL)
  • DriverManager.getConnection(String jdbcURL, String user, String password)

getConnection() 메서드의 jdbcURL은 데이터베이스를 연결할 때 사용할 JDBC URL을 나타내며,

user와 password는 데이터베이스의 계정과 암호를 나타낸다.

JDBC URL과 데이터베이스 사용자 계정/암호를 올바르게 지정했다면,

DriverManager.getConnection() 메서드는 Connection 객체를 리턴한다.

이 Connection 객체를 사용해서 필요한 작업을 시작할 수 있다.

 

DriverManager.getConnection() 메서드는 Connection 객체를 생성하지 못하면 SQLEXception 예외를 발생시킨다.

따라서 getConnection() 메서드를 사용할 때에는 try - catch 블록을 사용해서 SQLException에 대한 예외 처리를 해주어야 한다.

Connection conn = null;
try {
	conn = DriverManager.getConnection(...);
    ...
    ...
} catch(SQLException ex) {
	... //예외 처리
}

Connection 객체를 다 사용한 뒤에는 close() 메서드를 호출하여 Connection 객체가 사용한 시스템 자원을 반환해 주어야 한다. 그렇지 않을 경우 시스템 자원이 불필요하게 소모된다.

Connection conn = null;
try {
	String jdbcDriver = jdbc:oracle:thin:@HOST:PORT:SID
    String dbUser = username;
    String dbPass = userpasswd;
    
    conn = DriverManager.getConnection(jdbcDriver, dbUser, dbPass);
    ...
} catch(SQLException ex) {
	//에러 발생
} finally {
	if (conn != null) try {conn.close();} catch(SQLException ex) {}
}

위 코드를 보면 finally 블록에서 Connection 객체의 close() 메서드를 호출해서 사용한 자원을 반환하고 있다.

DriverManager.getConnection() 메서드가 예외를 발생시킬 경우 conn에는 Connection 객체가 할당되지 않으므로, 

null의 여부를 판단한 후에 close() 메서드를 호출해야 한다.

 

(7) Statement를 사용한 쿼리 실행

Connection 객체를 생성한 후에는 Connection으로부터 Statement를 생성한 뒤에 쿼리를 실행할 수 있다.

Statement는 다음과 같이 Connection.createStatement() 메서드를 사용하여 생성할 수 있다.

Statement stmt = conn.createStatement();

위와 같이 Statement 클래스를 생성한 다음에는 다음의 두 메서드를 사용해서 쿼리를 실행할 수 있다.

  • ResultSet executeQuery(String query) : SELECT 쿼리를 실행한다.
  • int executeUpdate(String query) : INSERT, UPDATE, DELETE 쿼리를 실행한다.

executeQuery() 메서드는 SELECT 쿼리의 결과값을 java.sql.ResultSet 객체에 저장해서 리턴한다.

두번째 executeQuery() 메서드는 INSERT, UPDATE, DELETE 쿼리를 실행하고, 그 결과로 변경된(또는 삽입된) 레코드의 개수를 리턴한다.

(8)ResultSet에서 값 읽어오기

Statement의 executeQuery() 메서드는 SELECT 쿼리를 실행할 때 사용되며, SELECT 쿼리의 실행 결과를 java.sql.ResultSet 객체에 담아서 리턴한다. 따라서 ResultSet 클래스가 제공하는 메서드를 사용해서 결과값을 읽어올 수 있다.

 

ResultSet 클래스는 next() 메서드를 제공하는데, next() 메서드를 사용해서 SELECT 결과의 존재 여부를 확인할 수 있다.

 

ResultSet은 SELECT 쿼리의 결과를 행으로 저장하며 커서를 통해서 각 행의 데이터에 접근한다. 

최초의 커서는 1행 이전에 존재하게 되며, ResultSet.next() 메서드는 커서의 다음 행이 존재할 경우 true를 리턴하고 커서를 그 행으로 이동시킨다. 

next() 메서드를 계속해서 호출하면 커서는 순차적으로 다음 행으로 이동하게 되며, 마지막 행에 커서가 도달하면 next() 메서드는 false를 리턴한다.

 

ResultSet은 현재 커서 위치에 있는 행으로부터 데이터를 읽어오기 위한 메서드를 제공한다.

메서드 리턴타입 설명
getString(String name)
getString(int index)
String 지정한 칼럼의 값을 String으로 읽어온다.
getCharacterStream(String name)
getCharacterStream(int index)
java.io.Reader 지정한 칼럼의 값을 스트림 형태로 읽어온다.
LONG VARCHAR 타입을 읽어올 때 사용한다.
getInt(String name)
getInt(int index)
int 지정한 칼럼의 값을 int 타입으로 읽어온다.
getLong(String name)
getLong(int index)
long 지정한 칼럼의 값을 long 타입으로 읽어온다.
getDouble(String name)
getDouble(int index)
double 지정한 칼럼의 값을 double 타입으로 읽어온다.
getFloat(String name)
getFloat(int index)
float 지정한 칼럼의 값을 float 타입으로 읽어온다.
getTimestamp(String name)
getTimestamp(int index)
java.sql.Timestamp 지정한 칼럼의 값을 Timestamp 타입으로 읽어온다. SQL TIMESTAMP 타입을 읽어올 때 사용된다.
getDate(String name)
getDate(int index)
java.sql.Date 지정한 칼럼의 값을 Date 타입으로 읽어온다. SQL DATE 타입을 읽어올 때 사용된다.
getTime(String name)
getTime(int index)
java.sql.Time 지정한 칼럼의 값을 Time 타입으로 읽어온다.
SQL TIME 타입을 읽어올 때 사용된다.

ResultSet의 get 계열의 메서드는 현재 커서에서 데이터를 읽어온다.

ResultSet은 처음에 첫 번째 행 이전에 커서가 위치하기 때문에 첫 번째 행에 저장된 데이터를 읽으려면 next() 메서드를 사용해서 커서를 이동시켜야 한다.

rs = stmt.executeQuery("select * from member");
if(rs.next()) { //다음 행(첫 번째 행)이 존재하면 rs.next()는 true를 리턴
	//rs.next()에 의해 다음 행(첫 번째 행)으로 이동
    String name = rs.getString("NAME");
	...
} else {
	//첫 번째 행이 존재하지 않은다. 즉, 결과가 없을 때
    ...
}

 

 

 

 

참고:최범균의 JSP 웹프로그래밍

'[JSP]' 카테고리의 다른 글

10.클라이언트와의 대화 2: 세션(session)  (0) 2021.07.13
5.필수 이해 요소  (0) 2021.07.08