본문 바로가기
교재 실습/자바 웹 개발 워크북

69. DB 커넥션풀 (3)

by Jint 2022. 7. 14.

3. MemberDAO에 DB 커넥션풀 적용하기

MemberDao 클래스에 DBConnectionPool을 적용한다.

 

- DBConnectionPool 객체를 주입하기 위한 코드 준비

MemberDao 클래스 코드를 수정한다.

public class MemberDao {
    //Connection connection;
	
    //Connection 객체 주입(의존성 주입, 역제어)
    /*public void setConnection(Connection connection) {
        this.connection = connection;
    }*/
	
    DBConnectionPool connPool;
	
    //DBConnectionPool 객체 주입
    public void setDbConnectionPool(DBConnectionPool connPool) {
        this.connPool = connPool;
    }
    
    ...
}

이제 MemberDao 클래스는 커넥션 객체를 직접 보관하지 않기 때문에 인스턴스 변수와 셋터 메서드를 제거한다. 대신 DBConnectionPool 객체를 저장하는 인스턴스 변수와 셋터 메서드를 추가한다.

 

- 메서드에서 DB 커넥션 풀 사용

MemberDao 클래스의 selectList() 메서드, selectOne() 메서드, insert() 메서드, update() 메서드, delete() 메서드, exist() 메서드에 커넥션 객체를 얻는 코드를 추가한다.

//회원 목록 조회
public List<Member> selectList() throws Exception {
    Connection connection = null;
    Statement stmt = null;
    ResultSet rs = null;
    try {
        connection = connPool.getConnection(); //DB 커넥션 객체 가져오기
        stmt = connection.createStatement();
        rs = stmt.executeQuery(
                "SELECT MNO,MNAME,EMAIL,CRE_DATE" + 
                " FROM MEMBERS" +
                " ORDER BY MNO ASC");
        ArrayList<Member> members = new ArrayList<Member>();
        while(rs.next()) {
            members.add(new Member()
                   .setNo(rs.getInt("MNO"))
                   .setName(rs.getString("MNAME"))
                   .setEmail(rs.getString("EMAIL"))
                   .setCreatedDate(rs.getDate("CRE_DATE"))	);
        }
        return members;
    } catch (Exception e) {
        throw e;
    } finally {
        try {if (rs != null) rs.close();} catch(Exception e) {}
        try {if (stmt != null) stmt.close();} catch(Exception e) {}
        if (connection != null) connPool.returnConnection(connection); //DB 커넥션 객체 반환(반납)
    }
}

Connection 객체를 담기 위한 로컬 변수를 선언하고, DBConnectionPool 클래스로부터 커넥션 객체를 꺼낸다. 작업을 완료한 다음에는 다시 DBConnectionPool 클래스에 커넥션을 돌려준다. selectList() 메서드 외에 다른 메서드들도 이와 같이 수정했다.

 

4. ContextLoaderListener에서 DBConnectionPool 생성 및 DAO에 주입

ContextLoaderListener 클래스 코드를 수정한다.

package spms.listeners;

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

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
//import javax.servlet.annotation.WebListener;

import javax.servlet.annotation.WebListener;

import spms.dao.MemberDao;
import spms.util.DBConnectionPool;

//리스너의 배치 : @WebListener 어노테이션 사용
@WebListener
public class ContextLoaderListener implements ServletContextListener {
	//Connection conn; //인스턴스 변수
	DBConnectionPool connPool;
  
	@Override
	public void contextInitialized(ServletContextEvent event) {
		try {
			//DB 커넥션 객체 준비
			ServletContext sc = event.getServletContext();
			/*Class.forName(sc.getInitParameter("driver"));
			conn = DriverManager.getConnection(
					sc.getInitParameter("url"),
					sc.getInitParameter("username"),
					sc.getInitParameter("password"));*/
			connPool = new DBConnectionPool(sc.getInitParameter("driver")
										   ,sc.getInitParameter("url")
										   ,sc.getInitParameter("username")
										   ,sc.getInitParameter("password")); //DB커넥션 생성에 필요한 값 준비
			//MemberDao 객체 준비하여 ServletContext에 보관
			MemberDao memberDao = new MemberDao();
			//memberDao.setConnection(conn);
			memberDao.setDbConnectionPool(connPool); //DAO에 DBConnectionPool 객체 주입
			sc.setAttribute("memberDao", memberDao);
		} catch(Throwable e) {
			e.printStackTrace();
		}
	}

	@Override
	public void contextDestroyed(ServletContextEvent event) {
		/*try {
			conn.close(); //데이터베이스와 연결 끊기
		} catch (Exception e) {}*/
		connPool.closeAll(); //웹 애플리케이션 종료 전 데이터베이스와 연결된 것 끊기
	}
}

Connection 객체를 다루는 인스턴스 변수, 객체 생성, 커넥션 닫는 코드는 제거하고 DBConnectionPool 객체를 위한 코드를 추가한다. 먼저 인스턴스 변수를 선언한다.

DBConnectionPool connPool;

그리고 웹 애플리케이션이 시작될 때(contextInitialized() 메서드가 호출될 때) DBConnectionPool 객체를 생성한다.

connPool = new DBConnectionPool(sc.getInitParameter("driver")
                               ,sc.getInitParameter("url")
                               ,sc.getInitParameter("username")
                               ,sc.getInitParameter("password")); //DB커넥션 생성에 필요한 값 준비

MemberDao 객체를 생성할 때, 커넥션풀 객체를 주입(Injection)한다.

memberDao.setDbConnectionPool(connPool); //DAO에 DBConnectionPool 객체 주입

웹 애플리케이션이 종료될 때(contextDestroyed() 메서드가 호출될 때) DBConnectionPool 클래스에 들어있는 모든 커넥션 객체를 닫는다.

connPool.closeAll(); //웹 애플리케이션 종료 전 데이터베이스와 연결된 것 끊기

 

톰캣 서버를 다시 시작하고, 기능을 테스트하면 이전과 같이 잘 실행된다.

 

참고도서 : https://freelec.co.kr/book/1674/

 

[열혈강의] 자바 웹 개발 워크북

[열혈강의] 자바 웹 개발 워크북

freelec.co.kr

'교재 실습 > 자바 웹 개발 워크북' 카테고리의 다른 글

71. DataSource와 JNDI (2)  (0) 2022.07.17
70. DataSource와 JNDI (1)  (0) 2022.07.16
68. DB 커넥션풀 (2)  (0) 2022.07.13
67. DB 커넥션풀 (1)  (0) 2022.07.12
66. ServletContextListener와 객체 공유 (3)  (0) 2022.07.11

댓글