참고 : 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 |