JAKARTAPROJECT
JAKARTA TIPJSP TIPJSP 질문&답변DATABASE TIPJAVASCRIPT TIPWEBHACKING TIP기타 TIP
자카르타 프로젝트
자카르타 프로젝트
자카르타 프로젝트 팁 게시판 입니다
Commons-dbcp 총정리
GoodBug
이미지 슬라이더 보기

Commons-dbcp

 

 

I. DBCP (DataBase Connection Pool)

이제는 데이터베이스 풀을 이용한 커넥션 풀을 사용하지 않는다는것은 상상조차 할 수 없게 되었다. 각 WAS의 벤더들은 오래전부터 자사제품에 대해 최적화된 커넥션 풀을 기본적으로 제공을 하기까지 이르렀다. 또한 한스버그의 커넥션 풀링이나 풀맨의 풀등 여러 오픈된 커넥션 풀 소스들이 돌아다기기도 하였다.

여기서는 Jakarta Commons에서 진행하고있는 Commons-dbcp project에 대해 알아보고 간단한 예제를 소개하기로 하겠다

 

II. 다운로드 및 설치

dbcp는 commons의 pool과 collection을 사용하기때문에 다음3가지를 모두 설치해야 정상적으로 dbcp를 사용할 수 있다.

Commons-dbcp http://jakarta.apache.org/site/downloads/downloads_commons-dbcp.cgi

Commons-pool http://jakarta.apache.org/site/downloads/downloads_commons-pool.cgi

Commons-collections http://jakarta.apache.org/site/downloads/downloads_commons-collections.cgi

DBCP API http://jakarta.apache.org/commons/dbcp/apidocs/index.html

 

/WEB-INF/lib/ 에 다운받은 3가지 *.jar를 복사하도록 한다

 

III. DBCP 웹에서 사용하기!

이번 dbcp 강의는 웹에서 사용하는것을 전제로 설명하겠습니다 ^^

톰캣을 사용한다면 server.xml에 dbcp를 설정해도 되지만 web.xml에 설정하는것이 좀더 유연성을 지닙니다

 

1) JDBC 정보 정의

web.xml에 dbcp를 사용하기위한 jdbc 정보를 정의합니다.

   <servlet>
      <servlet-name>connectioninitialize</servlet-name>
      <servlet-class>db.ConnectionInitialize</servlet-class>
      <init-param>
         <param-name>driverClassName</param-name>
         <param-value>org.gjt.mm.mysql.Driver</param-value>
      </init-param>
      <init-param>
      <param-name>url</param-name>
      <param-value>jdbc:mysql://localhost/unicorn</param-value>
      </init-param>
      <init-param>
         <param-name>username</param-name>
         <param-value>unicorn</param-value>
      </init-param>
      <init-param>
         <param-name>password</param-name>
         <param-value>iloveyou</param-value>
      </init-param>
      <init-param>
         <param-name>defaultAutoCommit</param-name>
         <param-value>true</param-value>
      </init-param>
      <init-param>
         <param-name>defaultReadOnly</param-name>
         <param-value>false</param-value>
      </init-param>
      <init-param>
         <param-name>maxActive</param-name>
         <param-value>30</param-value>
      </init-param>
      <init-param>
         <param-name>maxIdle</param-name>
         <param-value>10</param-value>
      </init-param>
      <init-param>
         <param-name>maxWait</param-name>
         <param-value>10000</param-value>
      </init-param>
      <load-on-startup>1</load-on-startup>   
   </servlet>

 

driverClassName : 사용할 jdbc driver의 class name

url : jdbc driver의해 연결할 connection에 대한 url

username : connection을 연결할 사용자 이름

password : connection을 연결할 사용자 비밀번호

defaultAutoCommit : 풀에의해 생성된 커넥션의 auto-commit 상태

defaultReadOnly : 풀에의해 생성된 커넥션의 read-only 상태

                             jdbc에 따라 지원하지 않을수도 있다 (예 : informix)

maxActive : 커넥션풀의 Active한 커넥션의 최대 갯수

maxIdle : 커넥션풀의 idle한 커넥션의 최대 갯수

maxWait : 커넥션이 풀에 반납되기까지 기다리는 최대 시간 (millisecond)

 

2) JDBC 정보 로딩 및 초기화

이 클래스는 web.xml에 의해 서블릿 컨테이너가 구동될 때 딱 한번 실행됩니다.

db.ConnectionInitialize.java

package db;

 

import java.sql.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;

import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.PoolingDriver;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;

 

public class ConnectionInitialize extends HttpServlet {
 
 public void init() throws ServletException {
 
    String driverClassName = null;
    String url = null;
    String username = null;
    String password = null;
    boolean defaultAutoCommit = true;
    boolean defaultReadOnly = false;
    int maxActive = 0;
    int maxIdle = 0;
    long maxWait = 0;

 

    // web.xml에서 정의한 파라미터 이름을 enumeration에 담습니다.

    Enumeration names = getServletConfig().getInitParameterNames();
       do {
          if(!names.hasMoreElements())
             break;

 

          // web.xml에 정의한 파라미터값을 가져옵니다.

          String name = (String)names.nextElement();
          String value = getServletConfig().getInitParameter(name).trim();

          System.out.println(name+" : "+value);

 

          if (name.startsWith("driverClassName"))
             driverClassName = value;
          else if (name.startsWith("url"))
             url = value;
          else if (name.startsWith("username"))
             username = value;
          else if (name.startsWith("password"))
             password = value;
          else if (name.startsWith("defaultAutoCommit"))
             defaultAutoCommit = "true".equals(value);
          else if (name.startsWith("defaultReadOnly"))
             defaultReadOnly = "true".equals(value);
          else if (name.startsWith("maxActive"))
             maxActive = Integer.parseInt(value);
          else if (name.startsWith("maxIdle"))
             maxIdle = Integer.parseInt(value);
          else if (name.startsWith("maxWait"))
             maxWait = Long.parseLong(value);

        } while(true);
       
        try {

           // jdbc driver 및 기타 정의를 설정합니다.
           setupDriver(driverClassName,

                           url,

                           username,

                           password,

                           defaultAutoCommit,

                           defaultReadOnly,

                           maxActive,

                           maxIdle,

                           maxWait);


           System.out.println("Connection initialize success");
        } catch (Exception exception) {
           System.out.println("Connection initialize fail!");
           exception.printStackTrace();
      }
 }
 
 public void setupDriver(String driverClassName,
       String url,
       String username,
       String password,
       boolean defaultAutoCommit,
       boolean defaultReadOnly,
       int maxActive,
       int maxIdle,
       long maxWait) throws Exception {


       try {

            // jdbc class를 로딩합니다.
            Class.forName(driverClassName);
        } catch (ClassNotFoundException classnotfoundexception) {
            System.out.println(driverClassName+" is not found");
            classnotfoundexception.printStackTrace();
            throw classnotfoundexception;
        }
       

        // 커넥션 풀로 사용할 commons-collections의 genericOjbectPool을 생성합니다.
        GenericObjectPool connectionPool = new GenericObjectPool(null);
        connectionPool.setMaxActive(maxActive);
        connectionPool.setMaxIdle(maxIdle);
        connectionPool.setMaxWait(maxWait);
       

        // 풀이 커넥션을 생성하는데 사용하는 DriverManagerConnectionFactory를 생성합니다.
        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(url, username, password);
       

        // ConnectionFactory의 래퍼 클래스인 PoolableConnectionFactory를 생성한다
        PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, connectionPool, null, null, defaultReadOnly, defaultAutoCommit);
       

        // 마지막으로 PoolingDriver 자신을 로딩한다
        Class.forName("org.apache.commons.dbcp.PoolingDriver");

        PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:");

        // 그리고 풀에 등록한다. 풀이름을 "unicorn"이라고 지정하였다        
        driver.registerPool("unicorn",connectionPool);       
    }
}

 

 

3) 커넥션 래퍼 클래스

데이터베이스 커넥션을 관리하는 Interface로 다음 4가지 함수를 정의하였습니다.

db.ConnectionContext.java

package db;

 

public interface ConnectionContext {
   public java.sql.Connection getConnection();
   public void rollback();
   public void commit();
   public void release();
}

 

ConectionContext를 구현한 커넥션 클래스

db.ConnectionResource.java

package db;

import java.sql.Connection;
import java.sql.DriverManager;

public class ConnectionResource implements ConnectionContext {
   private Connection connection = null;
   private boolean transaction = false;

 

   public ConnectionResource() throws Exception {
      init(false); 
   }
   
    public ConnectionResource(boolean transaction) throws Exception {
       init(transaction);
    }
   
    public void init(boolean transaction) throws Exception {
       this.transaction = transaction;
       connection = DriverManager.getConnection("jdbc:apache:commons:dbcp:unicorn");

       if (connection == null) throw new Exception("fail to get connection");

      if (transaction) connection.setAutoCommit(false);

    }
     
    public Connection getConnection() {  
       return connection;
    }

 

    public void rollback() {
       if (transaction) {
          if (connection != null) try { connection.rollback(); } catch (Exception e) {}
      }
   }

 

   public void commit() {
      if (transaction) {
         if (connection != null) try { connection.commit(); } catch (Exception e) {}
      }
   }

 

   public void release() {
      if (connection != null) {
         if (transaction) {
            try { connection.setAutoCommit(true); } catch (Exception e) {}
         }
         try { connection.close(); } catch (Exception e) {}
      }
   }
}

 

4) 테스트 JSP

jsp에서 다음과 같이 사용하면 됩니다.

<%@ page contentType="text/html;charset=EUC_KR" %>
<%@ page import="java.sql.*,db.*" %>

 

<%

   ConnectionContext connectionContext = new ConnectionResource();
   Connection connection = null;

   try {
      connection = connectionContext.getConnection();

   } catch (Exception exception) {
       exception.printStackTrace();
   } finally {
       if (connection != null) try { connectionContext.release(); } catch (Exception exception) {}
   }

%>

관련 파일들을 첨부합니다 ^^&

 

IV. Struts와 DBCP

만약 Struts와 함께 사용한다면 다음과 같이 사용하세요. 현재 Unicorn이 다음과 같은 형식으로 되어있습니다.

1) struts-config.xml 에 DBCP 정보를 정의합니다.

 <data-sources>
  <data-source key="mysql" type="org.apache.commons.dbcp.BasicDataSource">
   <set-property property="defaultAutoCommit" value="true"/>
   <set-property property="defaultReadOnly" value="false"/>
   <set-property property="description" value="Tomcat Data Source"/>
   <set-property property="driverClassName" value="org.gjt.mm.mysql.Driver"/>
   <set-property property="maxActive" value="30"/>
   <set-property property="maxIdle" value="10"/>
   <set-property property="maxWait" value="10000"/>
   <set-property property="username" value="unicorn"/>
   <set-property property="password" value="iloveyou"/>
   <set-property property="url" value="jdbc:mysql://localhost/unicorn"/>
  </data-source>
 </data-sources>

 

2) Action classs에서 다음과 같이 커넥션을 얻어올 수 있습니다.

Connection connection = getDataSource(request, "mysql").getConnection();

이 getDataSource() 함수는 org.apache.struts.action.Action 클래스에 다음과 같이 정의되어 있습니다.

protected DataSource getDataSource(HttpServletRequest request) {
    return getDataSource(request, "org.apache.struts.action.DATA_SOURCE");
}

protected DataSource getDataSource(HttpServletRequest request, String key) {
    ServletContext context = getServlet().getServletContext();
    ModuleConfig moduleConfig = ModuleUtils.getInstance().getModuleConfig(request, context);
    return (DataSource)context.getAttribute(key + moduleConfig.getPrefix());
}

 

3) Struts에서 트랜잭션 관리를 위한 코딩으로는 unicorn의 소스에 충실히 구현되어 있습니다.

마찬가지로 Interface인 ConnectionContext와 이를 구현한 ConnectionResource를 사용하여 트랜잭션 관리를 하였습니다. 이 예제는 unicorn 소스를 참조하세요 ^^

 

V. 톰캣에서의 DBCP 사용

1) DBCP에 대한 정보를 server.xml에 정의할 수 있습니다.

<Context path="/unicorn" docBase="unicorn" debug="0"
                 reloadable="true" crossContext="true">
          <Logger className="org.apache.catalina.logger.FileLogger"
                     prefix="localhost_ktng_log." suffix=".txt"
              timestamp="true"/>


    <Resource name="jdbc/unicorn" auth="Container"

                    type="javax.sql.DataSource"/>
    <ResourceParams name="jdbc/unicorn">
       <parameter>
         <name>factory</name>
         <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
       </parameter>
       <parameter>
         <name>username</name>
         <value>unicorn</value>
       </parameter>
       <parameter>
         <name>password</name>
         <value>iloveyou</value>
       </parameter>
       <parameter>
         <name>driverClassName</name>
         <value>org.gjt.mm.mysql.Driver</value>
       </parameter>
       <parameter>
         <name>url</name>
         <value>jdbc:mysql://localhost/unicorn</value>
       </parameter>
       <parameter>
         <name>maxActive</name>
         <value>30</value>
       </parameter>
       <parameter>
         <name>maxIdle</name>
         <value>10</value>
       </parameter>
       <parameter>
         <name>maxWait</name>
         <value>10000</value>
       </parameter>
     </ResourceParams>

 

2) web.xml에 JNDI 리소스를 사용할 수 있도록 다음을 추가합니다.

<resource-ref>
   <description>unicorn db</description>
   <res-ref-name>jdbc/unicorn</res-ref-name> 
   <res-type>javax.sql.DataSource</res-type>
   <res-auth>Container</res-auth>
</resource-ref>

3) 실제 소스에서는 다음과 같이 DataSource를 사용합니다.

InitialContext context = new InitialContext();

DataSource dataSource = (DataSource) context.lookup("java:/comp/env/jdbc/unicorn");

Connection connection = dataSource.getConnection();

간단하죵?

 

=============================================

본문서는 자유롭게 배포/복사 할수 있지만

이문서의 저자에 대한 언급을 삭제하시면 안됩니다

저자 : GoodBug (unicorn@jakartaproject.com)

최초 : http://www.jakartaproject.com 

=============================================

2008-11-10 12:04:28
222.233.252.***

 

좋은생각 ^^

첨부파일 (총 5개)
  1. ConnectionResource.java 1.36 KB (236 다운로드)
  2. test.jsp 433 Bytes (217 다운로드)
  3. web.xml 1.65 KB (211 다운로드)
  4. ConnectionInitialize.java 3.47 KB (254 다운로드)
  5. ConnectionContext.java 175 Bytes (218 다운로드)
0점 (0명)
덧글 4개 | 태그 4개 | 관련글보기
태그입력
쉽표(,)구분으로 한번에 여러 태그를 입력할수 있습니다
commons (16) upload (3) dbcp (2) 52 (1)
마린보이
(0) (0)
웹기반이 아닌 어플리케이션에서 사용할려면 어떻게 해야하나요..
210.122.61.*** 2005-10-17 11:12:23
GoodBug
(0) (0)
어플리케이션에서 사용하는 방법도 동일합니다 단 web.xml에 기본 정보를 입력하는 대신 properties나 다른 xml파일을 만들어 ConnectionInitialize.java에서 기본 정보를 읽으면 될것 같군요 그리고 main함수에서 이를 처음 초기화해주세요
220.70.88.*** 2005-10-17 22:50:29
마린보이
(0) (0)
답변감사합니다. mysql4.1 에서 mysql-connector-java-3.1.7-bin.jar 를 가지고 해봤는데 커넥션이 일정시간 후 끊기는거 같네요. 좀더 연구를 해봐야겠습니다. 좋은 자료 정리해주셔서 넘 유익하네요 수고가많습니다.^^
210.122.61.*** 2005-10-19 11:46:46
손님
(0) (0)
커넥션이 일정시간후 끊어지는건 autoreconnect=true 해주면 없어지는것같더군요
211.169.225.*** 2006-01-25 15:13:32
이름 비밀번호
자카르타 프로젝트
자카르타 프로젝트 팁 게시판 입니다
! 번호 제목 글쓴이 일자 조회
Hierarchy of the Apache Software Foundation GoodBug 2005-10-14 10,741
Jakarta Project 강좌 게시판입니다 8 GoodBug 2005-04-03 11,614
44 Log4J log4j에서 e.printStackTrace() 메시지를 log에 남기는 방법 1 kaiser 2008-10-22 17,547
43 DBUtils DBUtils에서 Clob 사용하기 3 1 GoodBug 2007-08-28 10,569
42 Spring Spring 설정 파일 로딩 1 GoodBug 2007-07-16 11,253
41 POI POI의 HSLF를 이용하여 PowerPoint 문서를 읽어보자 2 GoodBug 2007-05-28 14,837
40 POI POI의 HWPF를 이용하여 MS WORD문서를 읽어보자 2 GoodBug 2007-05-28 16,758
39 Validator Validator 속성들 1 GoodBug 2007-05-11 10,329
38 dd Commons-Fileupload 1.2 1 2 GoodBug 2007-04-23 15,267
37 Apache Apache2 + Tomcat5.5 + mod_jk 4 바이러스天国 2007-01-29 10,970
36 DBUtils DBUtils에서 number 타입의 컬럼이 int형으로 안넘어올때.. 3 1 GoodBug 2006-06-28 10,679
35 흠흠 위험한 static Logger 필드... 2 1 서연아빠 2006-03-16 10,051
34 Installing Tomcat with commons-daemon (jsvc) GoodBug 2006-01-08 9,005
33 commons Commons DbUtils 몇가지 예제 3 2 GoodBug 2005-11-17 15,124
32 commons Jakarta Commons Net 에서 FTP 사용시 목록이 안보일 경우 2 GoodBug 2005-11-15 21,699
31 listFiles() 에서 null 을 반환 추적.. 신만두 2008-11-11 11,770
30 commons 목록이 안보일 경우 해결기 I탄 1 2 GoodBug 2005-12-23 15,859
29 POI POI로 엑셀파일 읽을때, Invalid header signature 에러 1 GoodBug 2005-11-12 16,468
28 log4j log4j, JSP에서 원하는 Appender 골라쓰기 1 GoodBug 2005-11-07 13,825
27 commons Commons-Email~ 7 2 GoodBug 2005-10-13 17,787
copyright 2005-2017 by Unicorn