JSP

DBCP 구현하기

bang2001 2013. 7. 25. 19:39

ConnectionPoolBean은 웹에서 클라이언트에게 Connection을 개별적으로 할당하기 위한 클래스이다. 이 클래스는 미리 DB와 클라이언트가 연결되어 데이터를 주고받기 위해 필요한 Connection 객체를 미리 생성하여 클라이언트가 접속할 때마다 미리 만들어 놓은 객체를 클라이언트에게 할당하여 클라이언트가 입력한 데이터들을 DB에 저장할 수 있도록 하기 위한 클래스이다. 물론 클라이언트가 데이터를 입력하는 페이지에 DB연동을 구현하여 데이터값을 DB에 전달할 때 Connection을 생성해서 데이터값을 전달 할 수 있다. 하지만 그렇게 하게되면 매번 클라이언트가 접속할 때 클라이언트 입장에서는 DB와 연동하기 위해 필요한 객체생성이나 혹은 DB연결을 하는데까지 필요한 수초의 시간이 걸리게 된다. 그리고 이점은 웹 페이지를 이용하는 클라이언트에게 불편함을 호소하는 요인으로 작용할 것이다. 때문에 ConnectionPoolBean 클래스를 만들어서 DB와 연동에 필요한 요소를 미리 준비하고 클라이언트가 접속할 때 이렇게 생성한 요소를 할당해 줄 필요가 있다. 이 클래스는 Sun에서 제공하는것은 아니고, 수업시간에 만든 클래스이다. 하지만 이 코드를 블로그에 올린 이유는 추후 ConnectionPoolBean와 같은것을 제공하는 것들이 따로 있는데 그것들 또한 구현된 내부구조가 ConnectionPoolBean와 크게 차이가 나지 않기 때문에 어떤식으로 클라이언트에게 Connection을 할당하는지 알아보기 위해서 만든 것이다. 다음 아래 코드가 ConnectionPoolBean 

클래스에 대한 코드이다.

------------------------------------------------------------------------------------------

package my.dbpoll;

import java.util.*;
import java.sql.*;

/** 이 클래스는 이미 Connection객체를 생성하여 클라이언트에게 할당하는 클래스이다.<br>
 *  이와 같은 클래스를 이용하여 클라이언트로 하여금 작업속도를 높일 수 있다. */
public class ConnectionPoolBean
{
private Hashtable<ConnectionBoolean> ht;
private String url, user, pwd;
private int increment;
/** 이 기본생성자는 처음 객체생성시 미리 Connection객체를 생성하여 
 *  클라이언트에게 할당 할 수 있도록 한다. */
public ConnectionPoolBean() throws ClassNotFoundExceptionSQLException
{
increment = 3; //증가치 : 3
ht = new Hashtable<ConnectionBoolean>(5); // 매개변수 정수값은 초기용량
// Conncetion을 저장할 자료구조(집합체) 이다.
Connection con = null;
Class.forName("oracle.jdbc.driver.OracleDriver");
url = "jdbc:oracle:thin:@localhost:1521:orcl";
user="scott"; pwd="tiger";
// 컨넥션을 미리 5개 생성하여 저장해 놓는다.
for (int i=0 ; i<5 ; i++)
{
con = DriverManager.getConnection(url,user,pwd);
ht.put(con, Boolean.FALSE); // 처음에는 False로 마크한다. K(con), V(Boolean)
}
System.out.println("ConncetionPoolBean create....");
}//기본생성자()================================================================
/** 이 메소드는 클라이언트에게 Connection객체를 할당하고 만약 미리 대기중이었던
 *  Connection객체를 모두 소진하였다면 자동적으로 Connection객체를 생성하여 
 *  클라이언트에게 할당할 수 있도록 하는 메소드이다.
 *@return 클라이언트에게 할당할 Connection객체이다. */
public synchronized Connection getConnection() throws SQLException
{
Connection con = null;
Enumeration<Connection> en = ht.keys(); //key값을 집합체 형태로 추출
while(en.hasMoreElements())
{
con = en.nextElement(); //Key
Boolean b = ht.get(con); //Value
if(b == Boolean.FALSE)
                        //만약 해당 객체가 일하고 있지 않다면 일 한다고 마크작업
{
ht.put(con, Boolean.TRUE); //작업이 들어간 Connection객체에 마크작업
return con;
}
}//while()-------------------------------------------------
//놀고있는 con이 하나도 없다면 컨넥션을 증가시킨다.
for (int i=0 ; i<increment ; i++)
{
Connection con2 = DriverManager.getConnection(url,user,pwd);
ht.put(con2, Boolean.FALSE);
}
return getConnection(); //재귀호출
}//getConnection()==================================================================
public void returnConnection(Connection returnCon) throws SQLException
{
Connection con = null;
Enumeration<Connection> en = ht.keys(); //key값을 집합체 형태로 추출
while(en.hasMoreElements())
{
con = en.nextElement();
if (con == returnCon)
{
// 반환되는 컨넥션과 주소값이 값다면 false로 마크한다.
ht.put(con, Boolean.FALSE);
break;
}
}
removeCon(); //컨넥션을 기본적으로 5개만 유지할 수 있도록 하는 메소드이다.
}//returnConnection()==============================================================
/** 이 메소드는 항상 일정한 수준의 Connection객체를 유지할 수 있도록 하는 메소드이다. */
public void removeCon()
{
Connection con = null;
Enumeration<Connection> en = ht.keys();
int count = 0; // false인 con의 갯수를 의미하는 지역변수이다.
try
{
while (en.hasMoreElements())
{
con = en.nextElement();
Boolean b = ht.get(con);
if(!b) //자료구조에서 Vaule값이 false가 있다면.. 이라는 뜻이 된다.
{
count++;
if (count>5)
{
ht.remove(con);
con.close();//false로 마크된 con이 5개 이상이라면 
                                                ht에서 제거 후 연결종료
}
}//if()-----------------------------------------------
}//while()---------------------------------------
}//try---------------------------------------
catch(SQLException e)
{
}
}//removeCon()=====================================================================
/** 이 메소드는 서버가 Shut / Down 할 때에 현재까지 생성된 모든
             Connection객체를 닫아주는 메소드이다. */
public void classAll()
{
Enumeration<Connection> en = ht.keys();
while (en.hasMoreElements())
{
Connection con = en.nextElement();
try
{
con.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}//while()----------------------------------------
}//classAll()========================================================================
}

------------------------------------------------------------------------------------------

위 코드에서 중요하게 생각할 점은 바로 임계영역에 적절히 동기화를 했다는점과 

자료구조를 이용하여 객체를 저장하고 꺼내오는 방법, Hashtable의 Key와 Value를 이용하여

객체에 Mark(표시) 작업을 하여 해당 객체가 다른 클라이언트로부터 사용중인지 판단하는 방법등

이러한 것을 중요하게 생각해야 할 필요가 있다고 생각한다.