jdbc pool
** 타입1과 2는 순수 자바 드라이버가 지원이 안될때 사용하고 타입3과 4는 JDBC API를 통해 데이타베이스에 접근한다
타입 1: JDBC ODBC Brige + ODBC 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로 확인한다
인터페이스
Connection JDBC API를 통한 데이타베이스 연결
DatabaseMetaData 시스템 Catalog, Key, Table, Transaction에 관련된 사항둥 해당 데이타베이스에 관한
포괄적인 정보를 제공
ResultSetMetaData ResultSet 객체의 칼럼에 대한 타입과 프로퍼티 정보를 가져올 수 있는 인터페이스로
테이블의 칼럼 정보를 제공
ResultSet Statement 객체를 통해 데이타베이스에 전송된 SQL문에 의해 반환되는 데이타
Statement SQL문을 데이타베이스에 전송
PreparedStatement 반복되는 SQL문을 미리 컴파일 한 뒤 데이타베이스에 전송
CallableStatement 데이타베이스 내부의 스토어드 프로시저를 호출하기 위한 인터페이스
클래스
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일 경우 소수점 자리수를 지정한다
파라미터가 있는 프로시저 { 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
BLOB BLOB LONGBLOB getBinaryStream
TINYINT TYNYINT TINYINT
SMALLINT SMALLINT SMALLINT
INTEGER INT INTEGER/INT getInt
BIGINT NUMBER BIGINT BIGINT getLong
BIT BIT
BOOLEAN getByte
DECIMAL DECIMAL DECIMAL
NUMERIC NUMERIC
FLOAT FLOAT FLOAT
REAL REAL
DOUBLE NUMBER(p, s) DOUBLE getDouble
CHAR CHAR/NCAHR CHAR/NCHAR CHAR
VARCHAR VARCHAR2/NVARCHAR2 ARCHAR/NVARCHAR VARCHAR getString
BINARY BINARY
VARBINARY RAW(n) VARBINAR/IMAGE getBytes
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 65535*2 Byte
CLOB 4 GB TEXT/NTEXT 8000 Byte 이상 LONGTEXT 4 GB
RAW(n) n 바이트
LONG RAW 2 GB BOLB 65535*2 Byte
BLOB 4 GB IMAGE 8000 Byte 이상 LONGBLOB 4 GB
BFIL 외부
TYNYINT 1 Byte TINYINT 1 Byte
SMALLINT 2 Byte SMALLINT 2 Byte
INT 4 Byte INTEGER/INT 4 Byte
NUMBER 숫자 BIGINT 8 Byte 정수 BIGINT 8 Byte
BIT 1 Byte(0, 1)
MONEY/SAMLLMONEY 화페 FLOAT 4 Byte
NUMERIC/DECIMAL 고정 소수점 DECIMAL
NUMBER(p, s) p전체 s소수점 이하 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 4 Byte
TIMESTAMP YY/MM/DD/H/M/S/MS DATETIME 날짜 DATETIME 날짜(시간)
---------------------------------------------------------------------------------------------------------------------
** LONG, LONG RAW ** TABLE ** DECIMAL은 소수를 저장하지만
테이블에 칼럼 하나만 생성 SQL_VARIANT 내부적으로는 문자 형태로 저장
2 GB CURSOR TINYTEXT/TINYBLOB
SELECT 결과로 데이타를 리턴 UNIQUEIDENTIFIER MEDIUMTEXT/MEDIUMBLOB
데이타를 직접 저장 TIMESTAMP는 레코드가 변경 될 경우 ENUM
처음부터 순차적으로 읽음 자동으로 DB에 유일한 값으로 채워짐 YEAR
TO_LOB() 함수를 사용하여 LOB로 변환 시간과 전혀 관계가 없음
오브젝트 유형을 지원하지 않음
** CLOB, BLOB
테이블에 여러개의 칼럼을 생성
4 GB
SELECT 결과로 위치를 리턴
데이타를 직접 또는 간접 저장
랜덤 엑세스가 가능
LONG, LONG RAW로 변환할 수 없음
오브젝트 유형을 지원
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
** JDK 1.6: ojdbc14.jar
JDK 1.5: ojdbc14.jar
JDK 1.4: classes12.jar
Mssql 2005 driver: com.microsoft.sqlserver.jdbc.SQLServerDriver
url: jdbc:sqlserver://localhost:1433;databaseName=AdventureWorks
2000 driver: com.microsoft.jdbc.sqlserver.SQLServerDriver
url: jdbc:microsoft:sqlserver://localhost:1433;databasename=pubs(databasename=pubs는 작업하는 db 이름)
** 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 이름)
** 버전에 상관없이 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&characterEncoding=euckr</url>
** xml에서는 &를 참조자로 인식하기 때문에 &를 &로 변경해야 한다
그래도 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);
}
}