본문 바로가기

교육 및 세미나/신입사원 교육

8일차(2018.01.12)

JDBC (Java DataBase Connectivity)

JDBC (Java DataBase Connectivity)는 자바 프로그램이 DBMS 에 일관된 방식으로 접근할 수 있도록 API를 제공하는 자바 클래스들의 모임으로 다음의 특징을 가진다.

  • JDBC 는 함수 호풀용 SQL 인터페이스
  • JDBC 는 ANSI SQL-92 표준을 지원
  • JDBC 는 공통된 SQL 인터페이스를 바탕

--> JDBC 란 데이터베이스에 연결 및 작업을 하기 위한 자바 표준 인터페이스이다.

JDBC 구성

1) 응용 프로그램

- 데이터베이스에 연결을 요청

- 데이터베이스에 SQL 문을 전송

- SQL 문의 결과를 요청

- 오류가 발생하는 경우 오류 처리

- 트랜잭션을 제어

- 드라이버 매니저

    • 데이터베이스에 맞는 드라이버 검색
    • JDBC 초기화를 위한 작업을 수행

2) 드라이버

- 데이터베이스에 연결

- 데이터베이스에 SQL 문을 전달

- 응용프로그램에 검색 결과를 전달

- 필요한 경우 커서를 조작

- 필요한 경우 트랜잭션을 시작


3) DBMS

- 데이터가 저장되어 있는 장소

System Architecture

JDBC API는 2-tier 와 3-tier를 모두 지원한다.

1) 2-tier

- 자바 애플릿이나 어플리케이션이 JDBC 를 이용하여 DBMS 데이터베이스에 직접 접근

- 가장 대표적인 C/S 구조

- 프로그래밍이 간단하다는 장점

- 보안, 로드밸런싱, 확장성(오브젝트 재사용) 등의 문제점

- 2-tier 디자인이 적합한 경우

          • 애플리케이션이 하나의 데이터베이스만을 사용
          • 데이터베이스 엔진이 하나의 CPU에서 동작
          • 데이터베이스가 계속 거의 같은 크기로 유지
          • 사용자 기반이 같은 크기로 유지
          • 요구가 확정되어 변화 가능성이 극히 적거나 없는 경우
          • 애플리케이션을 종료한 후에도 최소한의 지속성을 요구

2) 3-tier

- 자바 애플릿이나 어플리케이션이 DBMS 를 직접 접근하는 것이 아니라 중간에 미들웨어(미들티어)를 거쳐 데이터베이스에 접근

- 데이터베이스와의 연동 부분을 분리시킴으로써 Presentation Layer가 데이터 저장 방법에 신경을 쓰지 않아도 된다.

- 클라이언트는 단지 미들티어를 참조

- 미들티어 서버는 DBMS와 같이 특정한 작업만 수행하는 최종 서버와 통신을 하여 결과를 얻은 후 이 결과를 클라이언트에게 전달

- 2-tier 모델보다 안정적이고 유연하며 보안이 강화    

        • tier 1 : 사용자 인터페이스를 담당하는 클라이언트
        • tier 2 : http, 코바 등을 지원하는 응용 처리 서버
        • tier 3 : DBMS 와 같이 사용자가 최종적으로 원하는 기능을 수행할 서버

JDBC Driver 유형

Type 1

- JDBC-ODBC Bridge


- 특징

    • 데이터베이스를 연동하기 위해 브릿지 기술을 사용
    • ODBC API로의 게이트웨이를 제공하여 실제로는 ODBC의 API를 구현함으로써 데이터베이스를 연동
    • 브릿지 솔루션은 보통 클라이언트에 소프트웨어가 설치될 것을 요구
    • JDBC-ODBC 드라이버는 ODBC 드라이버가 풍부하기 때문에 거의 대부분 데이터베이스 시스템에서 사용할 수 있으며 JDBC-ODBC 드라이버를 사용하는 클라이언트에 사전에 ODBC 드라이버가 설치되어 있는 경우 매우 유용하게 사용할 수 있다.
    • 속도와 관련한 가장 큰 문제 : JDBC 를 통해 호출된 명령이 다시 ODBC 를 통해 나가야 하기 때문에 두개의 브릿지를 거치며, 이로 인해 빠른 속도를 기대하기 어렵다. 빠른 성능을 요구하는 애플리케이션의 경우에는 Type1 . JDBC-ODBC 브릿지는 적당하지 않다.
    • JDBC-ODBC 브릿지를 사용하는 시스템에는 반드시 해당 데이터베이스에 연결하기 위한 ODBC 드라이버가 설치되어야 하며, 이 단점은 애플릿에서 JDBC 를 사용하여 프로그램 하는 경우 많은 문제가 된다. 애플릿을 이용하여 JDBC-ODBC 를 사용할 경우, 애플릿을 다운받은 클라이언트에 미리 ODBC 드라이버가 설치되어 있어야 하기 때문에 배포 등에 많은 문제가 발생하게 된다.

Type 2

- Native-API / Partly Java Driver(사용 일부 자바)


- 특징

    • 각각의 데이터베이스 제조업체들이 제공한 C 혹은 C++ 메소드를 자바 코드가 호출하는 방식
    • 부분적으로 자바 드라이버인 원시 API 라고 일컬어짐
    • 데이터베이스와 연결되는 부분이 Native Code로 구현되어 있는 만큼 JDBC-ODBC 브릿지에 비해 빠른 속도를 제공한다.
    • JDBC 드라이버를 사용하고자 하는 각각의 클라이언트에 DBMS Vendor 의 데이터베이스 라이브러리가 로드되어야 하기 때문에 인터넷이나 CS 환경에서는 사용하기 적합하지 않다. 또한 Type 3, 4 드라이버에 비해 낮은 성능

Type 3

- Net-Protocol/All-Java Driver(순수 자바)


- 클라이언트에서 일반적인 Network API를 이용해 보낸 정보를 서버가 Database에 독점적인 형태로 변환하는 방식


- 특징

    • 클라이언트에 존재하는 JDBC 드라이버는 소켓을 사용하여 서버에 존재하는 미들웨어(Middleware) 애플리케이션에 연결
    • 애플리케이션은 클라이언트의 요청을 사용하고자 하는 데이터베이스에 독점적인 API 로 전환
    • 하나의 드라이버로 여러 개의 데치터베이스를 연동
    • 클라이언트에 소프트웨어를 설치할 필요가 없음

Type 4

- Native-Protocol / All-Java Driver


- Database Engine 에 사용되는 Network Protocol을 자바 소켓으로 직접 Database에 교신하는 방식


- 특징

    • 가장 직접적인 순수 자바 솔루션
    • 거의 대부분 데이터베이스의 제조업체가 제공한다.
    • ODBC 나 Native Lib 형태로 request 를 변환하지 않기 때무에 Performance 가 매우 좋다. 또한 특별하기 Driver 나 Lib, Middleware 등을 설치할 필요가 없기 때문에 배포 등이 매우 용이하다.

Oracle JDBC Driver

Type 2

오라클 "OCI Driver" 라고 불리운다.

ex) - OCI8 드라이버 : Oracle8 데이터베이스를 지원

     - OCI9 드라이버 : Oracle9 데이터베이스를 지원

이러한 드라이버는 한정된 플랫폼으로 모든 오라클 드라이버는 JDK 1.0과 1.1.x 에 종속적이며 JDBC 1.22 표준을 지원한다.

또한 Net8 을 포함하는 Oracle Client를 설치해야 사용이 가능하다.

☆ Type4 ☆

오라클 "Thin driver"라고 불리운다.

자바로 작성된 Net8의 TCP/IP 버전의 자체 실행을 포함하며 플랫폼에 독립적이고 실행 시간에 브라우저로 다운로드 된다. 그리고 서버 측에서는 TCP/IP Listener 가 필요하며 연결 스트링은 TNSNAMES 엔트리가 아닌 TCP/IP 주소와 포트번호가 된다.

URL Format → jdbc:oracle:thin:@[host]:[port]:[database]

JDBC API

JDBC API 는 데이터베이스의 데이터를 액세스할 수 있도록 제공되는 표준 자바 API 클래스와 인터페이스를 구성되어 다음 기능을 실행하기 위한 클래스와 인터페이스를 제공한다.

  • Java 프로그램에서 데이터베이스에 서버 접속
  • SQL 문을 구성, 데이터베이스 서버에서 실행
  • 데이터베이스 서버가 처리한 결과 가져오기
  • 데이터베이스의 정보, 처리 결과에 대한 정보 등을 가져오기

※ java.sql.* 패키지(package)

  • Java Application 으로부터 Database 를 조작하는 API 는 JDK 의 코어 API 로 『java.sql.*』 패키지에 설정되어 있다.
  • JDBC 는 데이터베이스에 접속하기 위해 한개의 클래스(java.sql.DriverManager)와 두 개의 인터페이스(java.sql.Driver 와 java.sql.Connection)를 사용한다.

사전 설정(주의 사항)

오라클이 설치되어 있는 경우

- 시스템의 classpath 를 다음과 같이 변경

(11g Express Edition 의 설치 경로가 C:\oraclexe 인 경우)

.;C:\oraclexe\app\oracle\product\11.2.0\server\jdbc\lib\ojdbc6.jar;

(10g Enterprise Edition 의 설치 경로가 C:\oracle 인 경우 )

.;C:\oracle\product\10.x.x\db_x\jdbc\lib\ojdbc14.jar;

오라클이 설치되어 있지 않은 경우

- Oracle 용 JDBC 드라이버르 다운로드 해야한다.

가. 다운로드 경로

① www.oracle.com 이동

http://www.oracle.com/technetwork

/database/features/jdbc

/jdbc-drivers-12c-download-1958347.html 이동

③ Driver 항목들 중 JDBC Driver를 버전에 맞는 항목을 선택하여 다운로드 진행

나. 파일 명

- ojdbc.jar 또는 ojdbc14.jar

다. 시스템의 classpath 항목에 ojdbc6.jar(ojdbc14.jar) 추가 → 경로 포함

공통

JDBC 드라이버 설치를 위한 ojdbc6.jar(ojdbc14.jar) 파일을 경로에 복사&붙여넣기

1. C:\Program Files\Java\jdk-9.0.1\jre\lib\ext

2. C:\Program Files\Java\jre\lib\ext

JSP 실습을 위한 추가 설정

- 웹 서버에서 실질적으로 Oracle 용 JDBC 드라이버를 찾는 경로는

『톰캣루트\lib』이므로 이 경로에 ojdbc6.jar(ojdbc14.jar) 파일을 복사&붙여넣기 한다.

- http://www.apache.org

JDBC 프로그래밍 절차

1. 드라이버 로딩 : Class.forName() - Oracle Driver 를 Java 에서 사용하기 위해 드라이버를 JVM에 로딩하는 과정.

2. 커넥션 할당받기 : DriverManager.getConnection()

3. 쿼리문 전송을 위한 Statement 또는 PreparedStatement(security programming) 또는 CallableStatement(oracle에서 함수나 프로시저 call해서 실행) 할당받기: conn.createStatement() 또는 conn.prepareStatement()

4. Statement 또는 PreparedStatement 를 통한 쿼리문 전송

○ DML (INSERT, UPDATE, DELECT) 문인 경우 : int updateCount = stmt.executeUpdate(sql)

- 영향받은 레코드 수 반환

○ SELECT 구문의 경우: ResultSet rs = stmt.executeQuery(sql)

→ ResultSet에서 result를 받고 db의 connection을 끊으면 ResultSet을 컨트롤할 수 없다.

5. (SELECT 구문의 경우, DML은 상관없음)

ResultSet 의 논리적 커서의 이동을 통해 각 컬럼의 데이터를 바인딩해 온다. : boolean b = rs.next()

- 커서 이동.

커서가 위치한 지점 레코드가 존재하면 true를 반환, 없으면 false를 반환.

커서는 가장 선두 첫 번째 레코드의 직전에 위치하고 있다가... next()가 호출되면 진행한다.

실습

DBConn.java

- 싱글톤 패턴을 이용한 Database 연결 객체 생성 전용 클래스 → DB 연결 과정이 부하가 가장 크기 때문에 한번 연결된 객체를 계속 사용하는 것이 좋다.

/*==========================================================
  DBConn.java
  - 싱글톤 패턴을 이용한 Database 연결 객체 생성 전용 클래스
   → DB 연결 과정이 부하가 가장 크기 때문에
      한번 연결된 객체를 계속 사용하는 것이 좋다.
 ===========================================================*/
package com.util;

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConn {
	
	private static Connection dbConn;
	//-- 자동으로 null 초기화
	
	public static Connection getConnection() //throws SQLException, ClassNotFoundException
	{
		// try ~ catch 대신 getConnection() 메소드명 뒤에 『throws Exception』 (SQLException, ClassNotFoundException)
		// 을 사용하면 try ~ catch 문을 사용하지 않아도 된다.
		// 단, throws Exception 을 사용할 경우 예외가 발생하게 되면
		// 프로그램 자체가 종료되어 버린다.
		// 하지만, try ~ catch 문을 사용할 경우 프로그램이 종료되는 것은 아니며
		// 연결 실패에 대한 원인 분석을 할 수 있다.
		// 또한, 이 오류가 발생되었을 경우 클라이언트에게 별도의 안내를 할 수도 있게 된다.
		// ex) 공사중
		if(dbConn == null)
		{
			try
			{
				String url ="jdbc:oracle:thin:@172.27.166.18:1521:xe";
				//--IP 주소는 오라클 서버의 주소, 1521은 오라클 Port Number
				//  xe 는 Express Edition을 사용할 경우 명시하게 되는 SID 이지만
				//  Standard Edition 이나 Enterprise Edition 등을 사용할 경우
				//  별도로 부여된 SID 명을 사용해야 한다.
				
				String user = "scott"; //--오라클 사용자 계정 이름
				String pwd = "tiger";  //--오라클 사용자 계정 암호
				
				Class.forName("oracle.jdbc.driver.OracleDriver");
				//-- OracleDriver 클래스에 대한 객체 생성
				
				// DriverManager.getConnection 은 static 클래스 기반이라서 원래는 DriverManager dm = new DriverManager(); 
				// 라고 선언해서 사용해야되는데 DriverManager.getConnection으로 사용한다.
				dbConn = DriverManager.getConnection(url, user, pwd);
				//-- 오라클 서버 실제 연결
				//   갖고있는 인자값은 오라클 주소, 계정명, 패스워드
			}catch (Exception e) // Exception 대신 SQLException, ClassNotFoundException 사용 가능
			{
				System.out.println(e.toString());
				//--오라클 서버 연결 실패 시 오류 메세지 출력 부분
			}
		}
		return dbConn;
	}
	public static Connection getConnection(String url, String user, String pwd)
	{
		if (dbConn == null) 
		{
			try
			{
				Class.forName("oracle.jdbc.driver.OracleDriver");
				dbConn = DriverManager.getConnection(url, user, pwd);
			}catch (Exception e)
			{
				System.out.println(e.toString());
			}
		}
		return dbConn;
	
	}
	public static void close()
	{
		if(dbConn != null)
		{
			try
			{
				if(!dbConn.isClosed()) //--isClosed() 메소드를 통해 연결 상태 확인 // 열려있다면....
					dbConn.close();    //--close() 메소드를 통해 연결 종료
			}catch(Exception e)
			{
				System.out.println(e.toString());
			}
		}
		dbConn = null;
	}
}

ConnectionTest.java

- DBConn(연결전용객체 생성 전용 클래스)를 통해 오라클 서버와 연결이 제대로 이루어지는지 확인

/*======================================
  ConnectionTest.java
 - DBConn(연결전용객체 생성 전용 클래스)를 통해
      오라클 서버와 연결이 제대로 이루어지는지 확인
========================================= */

package com.util;

import java.sql.Connection;

public class ConnectionTest {

	public static void main(String[] args) {
		Connection conn = DBConn.getConnection();
		//-- DB 연결 과정이 가장 부하가 크기 때문에
		//   한 번 연결된 객체를 계속 사용할 예정
		if(conn != null)
		{
			System.out.println("데이터베이스 연결 성공~!!!");
		}
		DBConn.close();
	}
}

Java로 Test 전에 sql로 파일 만들기

SELECT USER
FROM DUAL;
--==>> SCOTT

--○ SQL 구문 전송 실습을 위한 준비

-- 테이블 생성
CREATE TABLE TBL_MEMBER
( SID NUMBER
, NAME VARCHAR2(20)
, TEL  VARCHAR2(20)
, CONSTRAINT MEMBER_SID_PK PRIMARY KEY(SID)
);
--==>> Table TBL_MEMBER이(가) 생성되었습니다.

INSERT INTO TBL_MEMBER(SID, NAME, TEL) VALUES(1, '김준협', '010-1111-1111');
--==>> 1 행 이(가) 삽입되었습니다.

ROLLBACK;

SELECT *
FROM TBL_MEMBER;

SqlTest01.java

package com.test;

import java.sql.Connection;
import java.sql.Statement;

import com.util.DBConn;

public class SqlTest01 
{
	public static void main(String[] args) {
		Connection conn = DBConn.getConnection();
		
		if(conn == null)
		{
			System.out.println("데이터베이스 연결 실패~!!!");
			System.exit(0); //
		}
		
		// 데이터 입력 쿼리문 실행
		//   입력하면 다시 실행하지 못하는 상황  primary key 제약조건 위반
		try
		{
			// 작업 객체 생성
			Statement stmt = conn.createStatement();
			
			//쿼리문 준비
			String sql = "INSERT INTO TBL_MEMBER(SID, NAME, TEL) VALUES(1, '김준협', '010-1111-1111')";
			
			//-- 주의. 쿼리문을 문자열로 구성하는 과정에서 공백 발생 지점을 명확히 처리한다.
			//-- 주의. 문자열 영역 안에서 쿼리문 끝에다가 『;』을 붙이지 않는다.
			//-- 주의. 자바에서 실행한 DML 구문은 자동으로 COMMIT 된다.
			
			// 준비된 쿼리문 실행
			int result = stmt.executeUpdate(sql); // RECORD 갯수 반환
			
			if(result > 0)
				System.out.println("데이터 입력 성공~!!!");
			
		} catch (Exception e) 
		{
			System.out.println(e.toString());
		}
		
		DBConn.close();
	}
}

SqlTest02.java

package com.test;

import java.sql.Connection;
import java.sql.Statement;
import java.util.Scanner;

import com.util.DBConn;

public class SqlTest02 
{
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		
		Connection conn = DBConn.getConnection();
		
		do
		{
			System.out.print("번호를 입력하세요 : ");
			String sid = sc.next();
			
			if(sid.equals("-1"))
				break;
			System.out.print("이름을 입력하세요 : ");
			String name = sc.next();
			System.out.print("전화번호를 입력하세요 : ");
			String tel = sc.next();
			
			if(conn != null)
			{
				System.out.println("데이터베이스 연결 성공~!!!");
				
				try
				{
					Statement stmt = conn.createStatement();
					String sql = String.format("INSERT INTO TBL_MEMBER(SID,NAME,TEL) VALUES(%s,'%s','%s')"
							, sid, name, tel);
					int result = stmt.executeUpdate(sql);
					if(result > 0)
						System.out.println("회원 정보 입력 완료~!!!");
				}catch (Exception e)
				{
					System.out.println(e.toString());
				}
			}
		}while (true);
		
		DBConn.close();
		
		System.out.println("데이터베이스 연결 닫힘~!!!");
		System.out.println("프로그램 종료됨~!!!");
	}
}


'교육 및 세미나 > 신입사원 교육' 카테고리의 다른 글

10일차(2018.01.16)  (0) 2018.01.19
9일차(2018.01.15)  (0) 2018.01.15
7일차(2018.01.11)  (0) 2018.01.12
6일차(2018.01.10)  (0) 2018.01.12
5일차(2018.01.09)  (0) 2018.01.12