어느 가을날의 전환점

JAVA|JDBC Driver / API 본문

Development

JAVA|JDBC Driver / API

어느가을빛 2010. 10. 13. 14:42

Contents

JDBC Driver 종류

JDBC API

 

JDBC Driver 종류

** 타입1과 2는 순수 자바 드라이버가 지원이 안될 때 사용하고 타입3과 4는 JDBC API를 통해 데이터베이스에 접근한다

타입 1: JDBC-ODBC Bridge Driver

ODBC 드라이버를 통해 데이터베이스에 접근

타입 2: Native API Partly Java Driver

C로 작성된 자체 함수 인터페이스를 통해 데이터베이스에 접근

타입 3: JDBC Net pure Java Driver

미들 티어 서버를 통해 데이터베이스에 접근

타입 4: Native protocol pure Java Driver

데이터베이스 벤더가 제공하는 순수 자바 코드로 이루어진 JDBC 드라이버로 직접 데이터베이스에 접속

일반적으로 가장 많이 사용하는 드라이버이다

 

JDBC API

** 데이터베이스의 테이블 구조를 모르더라도 메타데이터를 통해 데이터베이스를 사용할 수 있다

** java.sql 패키지를 사용한다

** 좀 더 상세한 정보는 해당 API를 확인한다

인터페이스(Interface)

Connection 

JDBC API를 통한 데이터베이스 연결

DatabaseMetaData 

시스템 Catalog, Key, Table, Transaction에 관련된 사항 등 해당 데이터베이스에 관한 포괄적인 정보를 제공

ResultSetMetaData 

ResultSet 객체의 칼럼에 대한 타입과 프로퍼티 정보를 가져올 수 있는 인터페이스로 테이블의 칼럼 정보를 제공

ResultSet 

Statement 객체를 통해 데이터베이스에 전송된 SQL문에 의해 반환되는 데이터

Statement 

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

PreparedStatement 

반복되는 SQL문을 미리 컴파일 한 뒤 데이터베이스에 전송

CallableStatement 

데이터베이스 내부의 스토어드 프로시저(SP)를 호출하기 위한 인터페이스

 

클래스(Class)

DriverManager

JDBC 드라이버들을 관리

Types 

SQL 데이터 타입 선언

 

1.Conection

Statement createStatement()

Statement 객체 생성

PreparedStatement preparedStatement(String sql)

PreparedStatement 객체 생성

CallableStatement prepareCall(String sql)

CallableStatement 객체 생성

Transaction 처리 메소드

setAutoCommit(boolean autoCommit)

- 데이터베이스 연결에 대한 자동 커밋 모드를 설정/해제 한다

- 데이터베이스에 대한 새로운 연결이 생성되면 기본적으로 자동 커밋 모드로 설정되기 때문에 매번 SQL문이 수행될 때마다 자동 커밋을 수행한다

- 자동 커밋 모드를 해제했을 경우에는 SQL문 수행후 commit()을 명시적으로 호출하지 않으면

처리 결과가 데이터베이스에 반영되지 않는다

getAutoCommit() 

- 현재 설정되어 있는 자동 커밋 모드를 얻는다

commit()

- 작업 이후 발생한 모든 변경 사항을 커밋하여 데이터베이스에 반영하고 데이터베이스에 대한 락을 해제한다.

- 자동 커밋 모드를 해제했을 경우에만 사용할 수 있다

rollback()

- 작업 이후 발생한 모든 변경 사항을 취소하고 데이터베이스에 대한 락을 해제한다

- 자동 커밋 모드를 해제했을 경우에만 사용할 수 있다

작업 순서

** 트랜잭션을 관련 있는 작업 단위로 처리하고자 한다면 autoCommit을 false로 하고 사용자가 판단하는 시점에 commit()이나 rollback()을 처리 해서 트랜잭션을 종료한다

** 작업 수행 중 예외가 발생하면 작업 이후 변경된 내용을 작업하기 이전으로 rollback해야 한다

예제

try {

    Connection con = DriverManager.getConnection(); /* 커넥션을 얻는다 */

    Statement stmt = con.createStatement();

 

    con.setAutoCommit(false); /* 자동 커밋 모드를 끈다 */

    stmt.executeUpdate(); /* SQL문을 수행한다 */

    con.commit();         /* 커밋한다 */

}

catch (Exception e) {

    con.rollback();         /* 롤백한다 */

}

finally {    

    stmt.close();    

    con.close(); /* 커넥션을 닫는다 */

}

 

2. DatabaseMetaData

ResultSet getCatalogs()

서버의 데이터베이스 리스트

ResultSet getSchemas(...)

서버의 사용자 리스트

ResultSet getTables(...)

데이터베이스 테이블 리스트

ResultSet getColumns(...)

테이블의 칼럼 리스트

ResultSet getPrimaryKeys(...)

기본 키 리스트

ResultSet getIndexInfo(...)

인덱스 리스트

 

3. ReslutSetMetaData

String getColumnName(int column)

칼럼명

int getColumnType(int column)

칼럼의 SQL 타입

int getColumnDisplaytSize(int column)

NCHAR/NVARCHAR일 경우에는 *2

int getColumnCount()

테이블 칼럼의 갯수

int getScale(int column)

소수점 이하 자리수

 

4. ResultSet

** SELECT SQL문의 실행 결과로서 생성된 결과에 해당하는 테이블

** Statement를 닫을때, 다른 SQL을 실행할때, 여러 개의 결과를 생성한 상태에서 getMoreResults를 호출하면 이미 생성된 ResultSet은 내부적으로 자동으로 close된다

void close()

ResultSet 닫기

boolean first()

ResultSet의 첫번째 레코드로 이동

bollean last()

ResultSet의 마지막 레코드로 이동

boolean next()

다음 레코드로 이동

boolean previous()

이전 레코드로 이동

boolean wasNull()

칼럼의 값이 NULL인지 검사

칼럼 값 가져오는 메소드

int getInt(칼럼)

int

long getLong(칼럼)

long

double getDouble(칼럼)

double

String getString(칼럼)

String

Timestamp getTimestamp(칼럼)

날짜/시간/시분초

byte[] getBytes(칼럼)

binary, varbinary

Reader getCharacterStream(칼럼)

clob, longvarchar

InputStream getBinaryStream(칼럼)

blob, longvarbinary

예제

Statement stmt = Connection.createStatement();

ResultSet rs = stmt.executeQuery("slect 칼럼1, 칼럼2, 칼럼3, 칼럼4 from 테이블명");

while (rs.next())

{

    int i = rs.getInt(칼럼1);

    String s = rs.getString(칼럼2);

 

    Reader c_in = rs.getCharacterStream(칼럼3);

    char[] c_buffer = new char[4096];

    StringBuffer c_s = new StringBuffer();

    int c_read;

    while ((c_read = c_in.read(buffer, 0, 4096)) != -1) c_s.append(c_buffer, 0, c_read);

 

    InputStream b_in = rs.getBinaryStream(칼럼4);

    byte[[] b_buufer = new byte[4096];

    int b_read;

    while ((b_read = b_in.read(b_buffer, 0, 4096)) != -1) b_s.append(toHexString변환(b_buffer), 0, b_read);

}

 

5. Statement

** Statement는 오직 하나의 ResultSet만 생성하기 때문에 ResultSet 객체를 읽는 도중에 다른 ResultSet을 읽어야 한다면 반드시 서로 다른 두 개의 Statement 객체가 필요하다

** Statement의 메소드를 실행하기 전에 이미 열려 있는 ResultSet 객체가 있으면 닫아야 한다

ResultSet executeQuery(String sql)

단일 ResultSet을 리턴한다

int executeUpdae(String sql)

insert, delete, update등과 같이 데이터베이스를 변경하여 갱신하는 작업을 한다

boolean execute(String sql)

여러 개의 ResultSet, update count를 리턴한다

boolean getMoreResults()

리턴 결과가 ResultSet이면 true를 결과가 없거나 변경된 갯수이면 false이다

getMoreResults가 false이고 getUpdateCount가 -1이면 더 이상 결과가 없다는것을 의미한다

ResultSet getResultSet()

현재 결과에 해당하는 ResultSet을 얻는다

int getUpdateCount()

변경된 데이터의 갯수를 리턴한다

-1이면 변경된 데이터가 없거나 결과가 ResultSet이라는것을 의미한다

 

6. PreparedStatement

** Statement 상속한다

** 파라미터를 넘겨줄때는 칼럼의 타입과 일치하는 메소드를 사용해야 하지만 일반적으로 setString을 사용해도 상관없다

ResultSet executeQuery()

ResultSet을 리턴한다

int executeUpdate()

실행 결과 값을 리턴한다

boolean execute()

여러개의 결과를 리턴한다

ResultSetMetaData getMetaData

ResultSetMetaData를 리턴한다

예제

PrepatedStatement pstmt = Connection.preparedStatement("update 테이블명 set 칼럼1=? where 칼럼2=?");

pstmt.setString(1, "값1");

pstmt.setString(2, "값2");

pstmt.executeUpdate();

 

7. CallableStatement

** PreparedStatement 상속한다

void registerOutParameter(int parameterIndex, int sqlType)

주어진 위치에 해당하는 파라미터를 sqlType을 갖는 out 파라미터로 등록한다

void registerOutParameter(int parameterIndex, int sqlType, int scale)

파라미터 타입이 numeric이나 decimal일 경우 소수점 자리수를 지정한다

prepareCall 표현식

파라미터가 있는 프로시저

{ call 프로시저명(?, ?, ... ) }

결과 값을 리턴하는 프로시저(Function)

{ ? = call 프로시저명(?, ?, ...) }

파라미터가 없는 프로시저

{ call 프로시저명 }

예제

CallableStatement cstmt = Connection.prepareCall("{ call 프로시저명(?, ?) }");

cstmt.setString(1, "값1");

cstmt.registerOutParameter(2, java.sql.Types.INTEGER);

cstmt.executeQuery();

int 리턴값 = cstmt.getInt(2);

 

 

SQL 데이터 타입

** JDBC에서 사용하는 데이터 타입은 크게 4가지로 나뉘어 진다

정수

BYTE, SHORT, INT, LONG

실수

FLOAT, DOUBLE

문자

CHAR, VARCHAR

날짜/시간

DATE, TIME, TIMSTAMP

 

java.sql.Types

Oracle

MSSQL

MySql

java.sql.ResultSet

LONGVARCHAR

LONG

TEXT/NTEXT

TEXT

getCharacterStream

CLOB

CLOB

 

LONGTEXT

LONGVARBINARY

LONG RAW

 

BLOB

getBinaryStream

BLOB

BLOB

 

LONGBLOB

TINYINT

 

TYNYINT

TINYINT

getInt

SMALLINT

 

SMALLINT

SMALLINT

INTEGER

 

INT

INTEGER/INT

BIGINT

NUMBER

BIGINT

BIGINT

getLong

BIT

 

BIT

 

getByte

BOOLEAN

     

DECIMAL

 

DECIMAL

DECIMAL

getDouble

NUMERIC

 

NUMERIC

 

FLOAT 

 

FLOAT

FLOAT

REAL 

 

REAL 

 

DOUBLE 

NUMBER(p, s)

 

DOUBLE

CHAR 

CHAR/NCAHR

CHAR/NCHAR 

CHAR

getString

VARCHAR 

VARCHAR2

VARCHAR

VARCHAR

NVARCHAR2

NVARCHAR 

BINARY 

 

BINARY 

 

getBytes

VARBINARY 

RAW(n)

VARBINAR/IMAGE 

 

DATE 

DATE

SMALLDATETIME 

DATE

getDate

TIME

 

TIME 

 

getTime

TIMESTAMP 

TIMESTAMP

DATETIME 

DATETIME/TIMESTAMP

getTimestamp

** sql.Types.CLOB, Types.LONGVARCHAR일 경우 MySql은 getString으로 Oracle, MSSQL은 getCharacterStream으로 처리한다

** sql.Types.LONGVARBINARY, sql.Types.BLOB은 getBinaryStream으로 처리한다

** sql.Types.NUMERIC, sql.Types.DECIMAL일 경우 소수점이 없으면 getLong을 사용한다

** sql.Types.BINARY, sql.Types.VARBINARY는 바이트 배열(Byte[])로 데이터를 읽어온다

 

Oracle 

MSSQL 

MySQL 

LONG

2 GB

TEXT/NTEXT

8000 Byte 이상

TEXT

65535*2 Byte

CLOB

4 GB

LONGTEXT

4 GB

RAW(n)

n 바이트

IMAGE

8000 Byte 이상

   

LONG RAW

2 GB

BOLB

65535*2 Byte

BLOB

4 GB

LONGBLOB

4 GB

BFIL

외부

       

NUMBER

숫자

TYNYINT

1 Byte

TINYINT

1 Byte

SMALLINT

2 Byte

SMALLINT

2 Byte

INT

4 Byte

INTEGER/INT

4 Byte

BIGINT

8 Byte 정수

BIGINT

8 Byte 

   

BIT

1 Byte(0, 1)

   

NUMBER(p, s)

p전체

s소수점 이하

MONEY

/SAMLLMONEY

화폐

FLOAT

4 Byte

NUMERIC

/DECIMAL

고정 소수점

DECIMAL

 

FLOAT

/REAL

부동 소수점

DOUBLE

8 Byte

CHAR

/NCHAR 

고정

4000 Byte 

CHAR

/NCHAR

고정

8000 Byte

CHAR

고정

255 Byte

VARCHAR2

/NVARCHAR2 

가변

4000 Byte 

VARCHAR

/NVARCHAR

가변

8000 Byte

VARCHAR

가변

255 Byte

   

BINARY

/VARBINARY

8000 Byte 이하

   

DATE

날짜(시간)

SMALLDATETIME

 

DATE/TIME

3 Byte

TIMESTAMP

YY/MM/DD

/H/M/S/MS

DATETIME

날짜

TIMESTAMP

4 Byte

DATETIME

날짜(시간)

 

LONG, LONG RAW

CLOB, BLOB

테이블에 칼럼 하나만 생성

테이블에 여러 개의 칼럼을 생성

2 GB

4 GB

SELECT 결과로 데이터를 리턴

SELECT 결과로 위치를 리턴

데이터를 직접 저장

데이터를 직접 또는 간접 저장

처음부터 순차적으로 읽음

랜덤 액세스가 가능

TO_LOB() 함수를 사용하여 LOB로 변환

LONG, LONG RAW로 변환할 수 없음

오브젝트 유형을 지원하지 않음

오브젝트 유형을 지원

 

** TIMESTAMP는 레코드가 변경 될 경우 자동으로 DB에 유일한 값으로 채워짐, 시간과 전혀 관계가 없음

** DECIMAL은 소수를 저장하지만 내부적으로는 문자 형태로 저장

** 기타

  • TABLE
  • SQL_VARIANT
  • CURSOR
  • UNIQUEIDENTIFIER
  • TINYTEXT/TINYBLOB
  • MEDIUMTEXT/MEDIUMBLOB
  • ENUM
  • YEAR

 

 

JDBC 연결

** 한번 로드 된 드라이버는 서버를 restart 하지 않는 한 메모리에 남아 있는다

 

드라이버 클래스

** Mssql일 경우 WEB-INF\lib에 sqljdbc.jar(1.5)와, sqljdbc4.jar(1.6)를 같이 복사하지 않는데

JDK 1.6일 경우 sqljdbc4.jar를 인식하지 못하기 때문이다

반드시 현재 JDK 버전에 맞는 드라이버만을 복사한다

 

Oracle

Driver

oracle.jdbc.driver.OracleDriver

URL

jdbc:oracle:thin:@localhost:1521:XE (XE는 오라클10g express를 설치할때 사용자가 지정한 sid)

jdbc:oracle:thin:@localhost:1521:oracle9i

Jar

JDK 1.6: ojdbc14.jar

JDK 1.5: ojdbc14.jar

JDK 1.4: classes12.jar

 

MSSQL

Driver

Mssql 2005

jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks

Mssql 2000

com.microsoft.jdbc.sqlserver.SQLServerDriver

URL

Mssql 2005

jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks

Mssql 2000

jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs

Jar

JDK 1.6: sqljdbc4.jar

JDK 1.5: sqljdbc.jar

JDK 1.4: msbase.jar, mssqlserver.jar, msutil.jar

 

MySQL

Driver

org.gjt.mm.mysql.Driver

URL

jdbc:mysql://localhost:3306/mysql?useUnicode=true&characterEncoding=euckr
(mysql은 작업 DB 이름)

Jar

mysql-connector-java-5.1.10-bin.jar (버전 무관)

 

프로퍼티 파일

** 데이터베이스 연결 정보를 저장하는 파일 형식이다

 

db.xml

** 웹서버의 홈 디렉토리 c:\inetpub\wwwroot\WEB-INF\classes에 .xml 파일을 보관한다

multi driver를 기본으로 2개 이상 드라이버를 지정할 수 있다

Pool 처리를 한번 하고 나면 드라이버가 메모리에 로드 되어 있는 상태이기 때문에

Pool을 해제 하거나 connection을 추가 수정했을 경우에는 다시 서블릿 컨테이너를 restart 해야 한다

** xml 태그는 대소문자를 구분하기 때문에 주의해야 한다

<?xml version="1.0" encoding="UTF-8"?>

<property>

    <connection name="oracle10g">

        <driver>oracle.jdbc.driver.OracleDriver</driver>

        <url>jdbc:oracle:thin:@localhost:1521:XE</url>

        <user>system</user>

        <password>xxxx</password>

    </connection>

    <connection name="mssql2005">

        <driver>com.microsoft.sqlserver.jdbc.SQLServerDriver</driver>

        <url>jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks</url>

        <user>sa</user>

        <password>xxxx</password>

    </connection>

    <connection name="mysql51">

        <driver>org.gjt.mm.mysql.Driver</driver>

        <url>jdbc:mysql://localhost:3306/mysql?useUnicode=true&amp;characterEncoding=euckr</url>

        ** xml에서는 &를 참조자로 인식하기 때문에 &를 &amp;로 변경해야 한다

        그래도 sax은 잘려버리는 현상이 생기므로 dom 방식으로 읽어 들여야 한다

        <user>root</user>

        <password>p422755</password>

    </connection>

</property>

 

db.properties

** 웹 서버의 홈 디렉토리c:\inetpub\wwwroot\WEB-INF\classes에 .properties 파일을 보관한다

driver는 하나만 지정할 수 있는데 여러 개를 지정해도 마지막에 지정된 driver만 로드 된다

property name(= 이전까지)은 반드시 소문자로, 값(= 이후부터)은 대문자,소문자 상관없다

값이 없어도 = 은 반드시 써야 한다

/* MSSQL 2000 */

drivers=com.microsoft.jdbc.sqlserver.SQLServerDriver

mydb1.url=jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs

mydb1.user=sa

mydb1.password=xxxx

mydb2.url=jdbc:microsoft:sqlserver://localhost:1433;databasename=northwiind

mydb2.user=sa

mydb2.password=xxxx

 

드라이버 연결

** Class.forName()은 JDBC 스펙과 JVM 구현간의 충돌이 일어날 수 있는데

이것을 피하기 위해서는 Class.forNmae().newInstance()를 사용해야 한다

static Connection getConnection(String url, String user, String password)

JDBC URL, user, password를 이용하여 데이터베이스 연결을 하고 그 Connection을 리턴한다

 

try {

    java.lang.Class.forName(st.nextToken().trim()).newInstance();

    java.sql.DriverManager.getConnection(JDBC URL, user, password);

}

catch (ClassNotFoundException e) {

    throw new Exceptionx("driver not found");

}

catch (Exception e) {

    throw new Exception(e.getMessage());

}

 

데이터베이스 커넥션 풀(DBCP) 소스

** dbcp를 통해서 Connection 객체를 얻어왔다면, con.close()를 해주면 된다

실제적인 db컨넥션이 close 되는게 아니라 DBCP가 Pool 에다가 반납하는 작업이 이루어진다

import java.io.*;

import java.sql.*;

import java.util.*;

 

import org.apache.commons.pool.impl.*;

import org.apache.commons.dbcp.*;

 

//*************************************************************

// dbcp를 사용하기 위해서는 다음과 같은 라이브러리가 필요하다

// DBCP API 관련 Jar 파일

// DBCP API가 사용하는 자카르타 Pool API의 Jar 파일

// Pool API가 사용하는 자카르타 Collection API의 Jar 파일

// commons-dbcp-1.2.1 (Commons DBCP api)

// commons-collections-3.1 (Commons Collection api)

// commons-pool-1.2 (Commons Pool api)

//*************************************************************

 

public class DBCP {

private static DBCP instance = null;

 

public static Connection getConnection (String path, String propertyName, boolean autocommit, int type) throws Exception {

        Connection con = null;

 

        if (instance == null) {

            synchronized (DBCP.class) {

                if (instance == null) {

                    instance = new DBCP(path, autocommit, type);

                }

            }

        }

        

        // DBCP일 경우 해당 풀의 커넥션을 가져올 URL은 'jdbc:apache:commons:dbcp:+풀이름'이어야 한다

        // pool에 프로퍼티가 없으면 Configuration file not found 에러메시지가 발생한다

        // 에러메시지를 가로채기 위해서 try catch를 한다.

        try {

            con = DriverManager.getConnection("jdbc:apache:commons:dbcp:" + propertyName);

}

        catch (Exception ex) {

            throw new Exceptionx(ex.getMessage());

}

        return con;

}

 

private DBCP (String path, boolean autocommit, int type) throws Exception {

        if (type == Xmls.NONE) init(path, autocommit);

        else xmlInit(path, type, autocommit);

}

 

private void init (String path, boolean autocommit) throws Exception {

FileInputStream is;

Properties dbProps = new Properties();

 

try {

            is = new FileInputStream(path);

            dbProps.load(is);

}

        catch (Exception e) {

throw new Exceptionx("파일을 읽을 수 없습니다.");

}

        loadJDBCDrivers(dbProps);

        createPools(dbProps, autocommit);

}

 

    private void loadJDBCDrivers (Properties props) throws Exception {

String driverClasses = props.getProperty("drivers", "sun.jdbc.odbc.JdbcOdbcDriver");

        StringTokenizer st = new StringTokenizer(driverClasses);

        while (st.hasMoreElements()) {

            String driverClassName = st.nextToken().trim();

            loadDrivers(driverClassName);

        }

    }

 

    private void loadDrivers (String driverClassName) throws Exception {

        try{

            Driver driver = (Driver)Class.forName(driverClassName).newInstance();

            DriverManager.registerDriver(driver);

        }

        catch (ClassNotFoundException ex) {

            throw new Exceptionx("드라이버를 찾을 수 없습니다.");

        }

        catch (InstantiationException ex) {

            throw new Exceptionx("드라이버를 초기화 할 수 없습니다.");

        }

        catch (SQLException ex) {

            throw new Exceptionx("드라이버에 에러가 발생했습니다.");

        }

        catch (Exception ex) {

            throw new Exceptionx(ex.getMessage());

        }

    }

 

    private void createPools (Properties props, boolean autocommit) throws Exception {

        String[] keys = { ".url", ".user", ".password" };

        String[] propValues;

        String token;

 

        // getListProperties(...)는 예제에는 없는 메소드임.

        // props를 Vector로 변환하는 메소드인데 자rl만의 방법으로 처리를 할것

        Vector ve = (Vector)getListProperties(props, keys, CodeType.VECTOR);

        for (int i = 0; i < ve.size(); i++) {

            token = (String)ve.get(i);

            propValues = (new Stringx(token)).split(Codes.charPart());

 

            setup(propValues[0].trim(), propValues[1].trim(), propValues[2].trim(), propValues[3].trim(), autocommit);

        }

    }

 

/** 속성 설명

maxActive

커넥션 풀이 제공할 최대 커넥션 개수

whenExhaustedAction

커넥션 풀에서 가져올 수 있는 커넥션이 없을 때 어떻게 동작할지를 지정한다

1일 경우 maxWait 속성에서 지정한 시간만큼 커넥션을 구할 때 까지 기다리며

0일 경우 에러를 발생시킨다

2일 경우에는 일시적으로 커넥션을 생성해서 사용한다

maxWait whenExhaustedAction

속성의 값이 1일 때 사용되는 대기 시간. 단위는 1/1000초이며, 0 보다 작을 경우 무한히 대기한다

maxIdle

사용되지 않고 풀에 저장될 수 있는 최대 커넥션 개수. 음수일 경우 제한이 없다

minIdle 사용되지 않고 풀에 저장될 수 있는 최소 커넥션 개수.

testOnBorrow

true일 경우 커넥션 풀에서 커넥션을 가져올 때 커넥션이 유효한지의 여부를 검사한다

testOnReturn

true일 경우 커넥션 풀에 커넥션을 반환할 때 커넥션이 유효한지의 여부를 검사한다

timeBetweenEvctionRunsMillis

사용되지 않은 커넥션을 추출하는 쓰레드의 실행 주기를 지정한다

양수가 아닐 경우 실행되지 않는다. 단위는 1/1000 초이다

numTestsPerEvictionRun

사용되지 않는 커넥션을 몇 개 검사할지 지정한다

minEvictableIdleTimeMillis

사용되지 않는 커넥션을 추출할 때 이 속성에서 지정한 시간 이상 비활성화 상태인 커넥션만 추출한다

양수가 아닌 경우 비활성화된 시간으로는 풀에서 제거되지 않는다

시간 단위는 1/1000초이다

testWhileIdle

true일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은

커넥션은 풀에서 제거한다.

**/

 

private void setup (String name, String url, String user, String password, boolean autocommit) throws Exception {

// connection pool 생성

GenericObjectPool conPool = new GenericObjectPool(null);

// maxActive - 사이트의 최대 커넥션 사용량을 기준으로 지정. 동시 접속자수에 따라서 지정한다

conPool.setMaxActive(50);

// minIdle - 사용되지 않는 커넥션의 최소 개수를 0으로 지정하게 되면 풀에 저장된 커넥션의 개수가 0이 될 수 있으며

// 이 경우 커넥션이 필요할 때 다시 커넥션을 생성하게 된다

// 따라서 커넥션의 최소 개수는 5개 정도로 지정해두는 것이 좋다

conPool.setMaxIdle(10);

// testWhileIdle - 사용되지 않는 커넥션을 검사할 때 유효하지 않은 커넥션은 검사하는 것이 좋다

conPool.setTestWhileIdle(true);

// timeBetweenEvctionRunsMillis - 이 값을 알맞게 지정해서 사용되지 않는 커넥션을 풀에서 제거하는 것이 좋다

// 커넥션의 동시 사용량은 보통 새벽에 최저이며 낮 시간대에 최대에 이르게 되는데

// 이 두 시간대에 필요한 커넥션의 개수 차이는 수십 개에 이르게 된다

// 이때 최대 상태에 접어들었다가 최소 상태로 가게 되면 풀에서 사용되지 않는 커넥션의 개수가 점차 증가하게 된다

// 따라서 사용되지 않는 커넥션은 일정 시간 후에 삭제되도록 하는 것이 좋다

// 보통 10~20분 단위로 사용되지 않는 커넥션을 검사하도록 지정하는 것이 좋다

conPool.setTimeBetweenEvictionRunsMillis(600000); // 1/1000초, 600000은 10분이 된다

// 실제 db와의 커넥션을 연결해 주는 팩토리 생성

ConnectionFactory conFactory = new DriverManagerConnectionFactory(url, user, password);

 

try {

            // connection pool이 PoolableConnection 객체를 생성할때 사용할 poolableConnectionFactory 생성

            new PoolableConnectionFactory(conFactory,

conPool,

null, // statement pool

null, // 커넥션 데스트 쿼리: 커넥션의 유효성을 테스트할때 사용

false, // 읽기 전용 ResultSet을 사용할지 여부. readonly 여부

// 외부에서 트랜잭션을 별도로 지정을 하면 false로 아니면 true로 지정을 한다

autocommit); // 커넥션의 autocommit 여부

}

catch (Exception ex) {

            throw new Exceptionx(ex.getMessage());

}

PoolingDriver driver = new PoolingDriver();

driver.registerPool(name, conPool);

}

}

 

 

 

 

 

 

# 출처: http://www.okjsp.pe.kr/bbs?act=DOWN&maskname=1273883897011&fileName=jdbc+pool.txt

Comments