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) 파일을 복사&붙여넣기 한다.
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 |