참고 : http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
: http://blog.naver.com/chocolleto?Redirect=Log&logNo=30084743153
○ 정의
- 데이터베이스와 연결된 커넥션을 미리 만들어 풀(pool)이란 저장소에 저장해 두고 있다가 필요할 때에 커넥션 풀에서 가져다 쓰고
○ 특징
- pool 속에 미리 커넥션이 생성되어 있기 때문에 커넥션을 생성하는데 드는 연결 시간이 소비되지 않음.
(어플리케이션의 실행속도가 빨라짐.)
- 커넥션을 계속해서 재사용하기 때문에 생성되는 커넥션 수가 많지 않음.
○ 정의
- Commons DBCP : apache에서 개발한 커넥션 풀 기능을 제공하는 API.
○ 특징
- JDBC의 Connection을 생성하고 사용하지 않는 Connection을 관리하여 Connection의 재사용을 높일 수 있음.
○ 처리 과정
2) 커넥션 풀 관련 설정 파일 초기화.
3) 커넥션 풀 관련 드라이버 로딩.
4) 커넥션 풀로부터 커넥션 사용.
○ Web Application에서 DBCP 설정
- jakarta commons Collections (Pool이 사용)
- jakarta commons Pool (DBCP가 사용)
(jakarta : http://jakarta-k.sourceforge.net/)
- collections : http://commons.apache.org/collections/download_collections.cgi
- pool : http://commons.apache.org/pool/download_pool.cgi
- 파일명 : pool.jocl (파일 이름은 사용자가 지정.)
(/WEB-INF/classes 폴더 혹은 /build/classes 폴더)
<object class = "org.apache.commons.dbcp.PoolableConnectionFactory" |
| 속성 | 설명 |
| 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일 경우 비활성화 커넥션을 추출할 때 커넥션이 유효한지의 여부를 검사해서 유효하지 않은 커넥션은 풀에서 제거한다. |
□ 속성 지정시 고려사항
■ maxActive
- 사이트의 최대 커넥션 사용량을 기준으로 지정.
- 동시 접속자 수에 따라서 지정.
■ minIdle
- 사용되지 않는 커넥션의 최소 개수를 0으로 지정하면 풀에 저장된 커넥션의 개수가 0이 될 수 있으며, 이 경우 커넥션이 필요
할때 다시 커넥션을 생성하게 됨. (최고 개수는 5개 정도로 지정.)
■ timeBetweenEvctionRunsMillis
- 이 값을 알맞게 지정해서 사용되지 않는 커넥션을 풀에서 제거하는 것이 좋음.
- 커넥션의 동시 사용량은 보통 새벽에 최저이며, 낮 시간대에 최대.
(최대 상태에 접어 들었다가 최소 상태로 가게 되면 풀에서 사용되지 않는 커넥션의 개수가 점차 증가.)
- 사용되지 않는 커넥션은 일정 시간 후에 삭제 되도록 하는 것이 좋음.
(보통 10 ~20분 단위로 사용되지 않는 커넥션을 검사하도록 지정하는 것이 좋음.)
■ testWhileIdle
- 사용되지 않는 커넥션을 검사할 때 유효하지 않은 커넥션은 검사하는 것이 좋음.
■ 드라이버 로드 프로그램 작성
○ HttpServlet을 상속받아 초기화.
- 서블릿이 초기에 실행될 때 실행되는 init() 메소드에 작성.
- jsp 페이지에서 DB를 사용하는 부분을 작성할 때 유용. (서버가 실행될 때 한 번만 실행되기 때문에.)
- 자바 파일을 작성한 다음 서블릿 설정파일인 web.xml에 반드시 추가.
● 예제
/* DBConInit.java */
package test.connection;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
public class DBConInit extends HttpServlet {
@Override
public void init(ServletConfig config) throws ServletException {
try {
Class.forName("com.mysql.jdbc.Driver");
Class.forName("org.apache.commons.dbcp.PoolingDriver");
System.out.println("Driver connection success");
}catch(Exception e) {
throw new ServletException(e);
}
}
} [출처] | commons | DBCP|작성자 외계인셩
Board index.html DBConInit test.connection.DBConInit 1
[출처] | commons | DBCP|작성자 외계인셩
<%@ page language="java" contentType="text/html; charset=EUC-KR"
pageEncoding="EUC-KR"%>
<%@ page import="java.sql.*"%>
<%
Connection con = null;
con = DriverManager.getConnection("jdbc:apache:commons:dbcp:boardpool");
if(con == null) {
out.print("connection is fail.");
} else {
out.print("connection is success");
con.close();
}
%>
■ DAO 사용 프로그램 작성
package com.chocolleto.board.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
/**
* DB Connection 하는 Singleton class.
*
* @author Administrator
*
*/
public class DBUtils {
private static final String DBCP_POOLING_DRIVER = "org.apache.commons.dbcp.PoolingDriver";
private static final String MYSQL_JDBC_DRIVER = "com.mysql.jdbc.Driver";
private static final String JDBC_URI = "jdbc:apache:commons:dbcp:/boardpool";
// 자기 스스로에 대한 인스턴스 생성. (생성자가 private이기 때문.)
private static volatile DBUtils instance = null;
private DBUtils() throws Exception {
try {
Class.forName(MYSQL_JDBC_DRIVER);
Class.forName(DBCP_POOLING_DRIVER);
} catch (Exception e) {
throw new Exception("Failed to create JDBC drivers.", e);
}
}
public static DBUtils getInstance() throws Exception {
if (instance == null) {
// 클래스를 생성하려면 클래스 자체에 대해 접근해야하므로 동기화를 걸어줌.
synchronized (DBUtils.class) {
if (instance == null) {
instance = new DBUtils();
}
}
}
return instance;
}
public Connection getConnection() throws SQLException {
return DriverManager.getConnection(JDBC_URI);
}
} /* UserDAO.java */[출처] | commons | DBCP|작성자 외계인셩
package com.chocolleto.board.user;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import com.chocolleto.board.db.DBUtils;
import com.chocolleto.board.user.model.User;
/**
* @author Administrator
*
*/
public class UserDAO {
private DBUtils db;
// private Logger log = Logger.getLogger(UserDAO.class);
public UserDAO() throws Exception {
// DB를 관리하는 객체의 인스턴스를 얻어온다.
db = DBUtils.getInstance();
}
/**
* 사용자 등록
*
* @param user
* @throws SQLException
*/
public void insertUser(User user) throws SQLException {
String sql = "insert into users(userid, password, nickname, birthday, email)"
+ "values(?,?,?,?,?)";
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
String birth;
if (user.getBirthday() == null) {
birth = null;
} else {
birth = dateformat.format(user.getBirthday());
}
Connection con = null;
try {
con = db.getConnection();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, user.getUserid());
st.setString(2, user.getPassword());
st.setString(3, user.getNickname());
st.setString(4, birth);
st.setString(5, user.getEmail());
st.executeUpdate();
st.close();
} catch (SQLException e) {
throw e;
} finally {
if (con != null) {
try {
// 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
con.close(); // 실제 컨넥션을 close하는게 아니라 가지고 있던 MySQL의 컨넥션을 풀에 반환.
} catch (SQLException e) {
// 컨넥션을 닫을때 생기는 문제는 무시한다
}
}
}
}
/**
* 사용자 정보 수정
*
* @param user
* @throws SQLException
*/
public void updateUser(User user) throws SQLException {
String sql = "update users set password=?,nickname=?,birthday=?,email=?"
+ " where userid=?";
SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd");
String birth;
if (user.getBirthday() == null) {
birth = null;
} else {
birth = dateformat.format(user.getBirthday());
}
Connection con = null;
try {
con = db.getConnection();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, user.getPassword());
st.setString(2, user.getNickname());
st.setString(3, birth);
st.setString(4, user.getEmail());
st.setString(5, user.getUserid());
st.executeUpdate();
st.close();
} catch (SQLException e) {
throw e;
} finally {
if (con != null) {
try {
// 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
con.close();
} catch (SQLException e) {
// 컨넥션을 닫을때 생기는 문제는 무시한다
}
}
}
}
/**
* 사용자 삭제
*
* @param userid
* @throws SQLException
*/
public void deleteUser(String userid) throws SQLException {
String sql = "delete from users where userid=?";
Connection con = null;
try {
con = db.getConnection();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, userid);
st.executeUpdate();
st.close();
} catch (SQLException e) {
throw e;
} finally {
if (con != null) {
try {
// 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
con.close();
} catch (SQLException e) {
// 컨넥션을 닫을때 생기는 문제는 무시한다
}
}
}
}
/**
* 사용자 검색.
*
* @param userid
* @param password
* @throws SQLException
*/
public User selectUser(String id) throws SQLException {
String sql = "select * from users where userid=?";
Connection con = null;
User user = null;
try {
con = db.getConnection();
PreparedStatement st = con.prepareStatement(sql);
st.setString(1, id);
ResultSet rs = st.executeQuery();
if (!rs.next()) {
// 검색된 내용이 없으면 회원이 아니므로 null을 반환.
rs.close();
st.close();
} else {
// 검색된 내용이 있으면 검색된 내용을 user에 저장.
user = new User();
user.setUserid(rs.getString("userid"));
user.setPassword(rs.getString("password"));
user.setNickname(rs.getString("nickname"));
user.setBirthday(rs.getDate("birthday"));
user.setEmail(rs.getString("email"));
}
rs.close();
st.close();
} catch (SQLException e) {
throw e;
} finally {
if (con != null) {
try {
// 컨넥션은 익셉션이 발생하더라도 항상 close() 될수 있도록 finally 에서 처리한다
con.close();
} catch (SQLException e) {
// 컨넥션을 닫을때 생기는 문제는 무시한다
}
}
}
return user;
}
}
'DBMS' 카테고리의 다른 글
| Virtual Hosting and Tomcat (가상 호스팅과 톰캣) - (직역) (0) | 2013.07.30 |
|---|---|
| JNDI 톰캣 구성의 예(직역) (0) | 2013.07.30 |
boardpool.jocl