오봉이와 함께하는 개발 블로그

Servlet - Servlet DB연동(Connection Pool) 본문

BE/Servlet

Servlet - Servlet DB연동(Connection Pool)

오봉봉이 2021. 12. 28. 19:51
728x90

Connection Pool(커넥션 풀 : DBCP(DataBase Connection Pool))

  • 등장 배경
    • 기존 데이터베이스 연결 방법의 문제점
      • 애플리케이션에서 데이터베이스 연결 과정에서 시간이 많이 소요
    • 해결 방안
      • 애플리케이션 실행 시 미리 Connection 객체를 생성하고, 미리 데이터베이스 연결을 해 놓음
      • 애플리케이션은 데이터베이스 연동 작업 발생 시 미리 생성되어 있는 Connection객체를 이용해 작업

커넥션 풀

  • 일정량의 DB Connection 객체를 Pool에 저장해 두고 클라이언트 요청이 있을 때 마다 가져다 사용하고 반환
  • 클라이언트에서 다수의 요청이 발생될 경우 요청마다 DB Connection 객체를 생성하게 되면 데이터베이스에 부하가 발생하기 때문에 커넥션 풀 기법 이용
    • JDBC를 통하여 DB에 연결하게 되면 사용자의 요청이 있을 때마다 매번 드라이버를 로드하고 커넥션 객체를 생성하여 연겨라고 종료하는 작업을 반복하면 비효율적
  • 장점
    • 풀 속에 미리 커넥션이 생성되어 있기 때문에 커넥션 생성에 시간이 걸리지 않음
    • 커넥션을 계속 사용하고 반환하기 때문에 재사용 가능하므로 많은 수의 커넥션을 만들지 않아도 된다.
    • 매번 커넥션을 생성하고 해제하는데 시간이 소요되지 않으므로 애플리케이션 실행 속도가 빨라진다.
    • 생성되는 커넥션 수를 제어하기 때문에 동시 접속자 수가 증가해도 애플리케이션이 쉽게 Down되지 않는다.
    • 접속 시 사용할 커넥션이 없으면 대기 상태로 전환되고, 반환되면 대기 순서대로 커넥션 제공
  • 동작 과정
    • 톰캣 컨테이너를 실행한 후 응용프로그램 실행
    • 톰캣 컨테이너 실행 시 ConnectionPool 객체 생성
    • 생성된 커넥션객체는 DBMS와 미리 연결
    • 데이터베이스 연동 작업이 필요할 경우 응용 프로그램은 ConnectionPool에서 제공하는 메소드를
    • 호출하여 연동
  • context.xml, web.xml에 추가
<!-- context.xml -->
    <Resource
            name="jdbc/mysql"
            type="javax.sql.DataSource"
            auth="Container"
            driverClassName="com.mysql.cj.jdbc.Driver"
            url="jdbc:mysql://localhost:3306/servletdb?serverTimezone=UTC"
            username="root"
            password=""
            maxActive="50"
            maxWait="1000"
    />
    <!-- maxWait : 커넥션이 없을 때 대기 시간 (1000 : 1초) 음수이면 무한 대기
<Resource 

   name="데이터베이스 이름"
   auth="Container" 
   driverClassName="oracle.jdbc.driver.OracleDriver" 
   type="javax.sql.DataSource" 
   url="jdbc:oracle:thin:@ip주소:포트번호:전역 데이터베이스 이름" 
   username="데이터베이스 아이디"
   password="데이터베이스 비밀번호" 
   maxActive="20" 
   maxIdle="10" 
   maxWait="5000"  />
 -->
<!-- web.xml -->
    <resource-ref>
        <description>Connection</description>
        <res-ref-name>jdbc/mysql</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

    <!-- 
    <resource-ref>
    <description>Connection</description>
    <res-ref-name>자신의 데이터베이스 이름</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
    </resource-ref>          
    -->

커넥션 풀 예제 - MemberDAO.java, MemberVO.java, MemberSelectServlet.java

public class MemberDAO {
    private Connection con = null;
    DataSource dataSource = null;
    // 생성자에서 DB연결 설정
    public MemberDAO() {
        try {
            Context init = new InitialContext();
            dataSource = (DataSource)init.lookup("java:comp/env/jdbc/mysql");
            System.out.println("연결 성공");
        } catch (Exception e) {
            System.out.println("연결 실패");
            e.printStackTrace();
        }
    }
package com.example.servlet4.sec06;

import java.util.Date;

public class MemberVO {
    private String id;
    private String pwd;
    private String name;
    private String email;
    private Date joinDate;

    // 디폴트 생성자
    public MemberVO() { }
    // 현재는 매개변수 있는 생성자 필요 없다.
    public MemberVO(String id, String pwd, String name, String email, Date joinDate) {
        this.id = id;
        this.pwd = pwd;
        this.name = name;
        this.email = email;
        this.joinDate = joinDate;
    }

    public MemberVO(String id, String pwd, String name, String email) {
        this.id = id;
        this.pwd = pwd;
        this.name = name;
        this.email = email;
    }

    // Getter / Setter
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getJoinDate() {
        return joinDate;
    }

    public void setJoinDate(Date joinDate) {
        this.joinDate = joinDate;
    }
}
package com.example.servlet4.sec06;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;

//@WebServlet(name = "MemberSelectServlet", value = "/MemberSelectServlet")
@WebServlet("/sec06/MemberSelectServlet")
public class MemberSelectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }
    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        // 서버에서 클라이언트로 데이터 전송에 자바 IO스트림 이용
        PrintWriter out = response.getWriter();

        MemberDAO dao = new MemberDAO();
        ArrayList<MemberVO> memList = dao.memberSelect();
        out.print("<html><head></head><body>");
        out.print("<table border=1><tr align='center' bgcolor='gold'>");
        out.print("<td>아이디</td><td>비밀번호</td><td>이름</td><td>이메일</td>" +
                "<td>가입일</td></tr>");
        for(int i = 0; i < memList.size(); i++) {
            // 오브젝트 반환 MemberVO 타입으로 형변환
            MemberVO vo = (MemberVO)memList.get(i);
            String id = vo.getId();
            String pwd = vo.getPwd();
            String name = vo.getName();
            String email = vo.getEmail();
            Date joinDate = vo.getJoinDate();
            // 한 행씩 출력
            out.print("<tr><td>" + id + "</td><td>" +
                                    pwd + "</td><td>" +
                                    name + "</td><td>" +
                                    email + "</td><td>" +
                                    joinDate + "</td></tr>");
        }
        out.print("</table></body></head>");
    }
}

커넥션 풀 연습 - MemberDAO.java, MemberVO.java, MemberSelectServlet2.java, MemberInsertServlet.java, MemberDeleteServlet.java

package com.example.servlet4.sec06;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Date;

public class MemberDAO {
    private Connection con = null;
    DataSource dataSource = null;
    // 생성자에서 DB연결 설정
    public MemberDAO() {
        try {
            Context init = new InitialContext();
            dataSource = (DataSource)init.lookup("java:comp/env/jdbc/mysql");
            System.out.println("연결 성공");
        } catch (Exception e) {
            System.out.println("연결 실패");
            e.printStackTrace();
        }
    }

    // 회원 정보 조회 메소드(전체 회원 정보 select : MemberVO 반환)
    // MemberVO를여러 행 반환 : ArrayList<MemberVO>
    public ArrayList<MemberVO> memberSelect() {
        Connection con = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        ArrayList<MemberVO> memList = new ArrayList<MemberVO>();

        try {
            con = dataSource.getConnection();
            String query = "select * from member";
            preparedStatement = con.prepareStatement(query);
            resultSet = preparedStatement.executeQuery(query);

            while(resultSet.next()) { // 결과 세트에서 한 행씩 처리
                // 한 행(회원 1명당) 처리
                String id = resultSet.getString("memId");
                String pwd = resultSet.getString("memPwd");
                String name = resultSet.getString("memName");
                String email = resultSet.getString("memEmail");
                Date joinDate = resultSet.getDate("memJoinDate");
                // 한 행 정보 가져와 memberVO에 Setter 이용하여 저장
                MemberVO vo = new MemberVO();
                vo.setId(id);
                vo.setPwd(pwd);
                vo.setName(name);
                vo.setEmail(email);
                vo.setJoinDate(joinDate);
                // 각 memberVO를 ArrayList에 저장
                memList.add(vo);
            }
            System.out.println("회원 조회 성공");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("회원 조회 실패");
        } finally {
            try {
                resultSet.close();
                preparedStatement.close();
                con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return  memList;
    }
    // 회원 정보 등록하는 메소드
    public void memberInsert(MemberVO memberVO) {
        try {
            con = dataSource.getConnection();

            String sql = "insert into member values(?, ?, ?, ?, default)";
            PreparedStatement preparedStatement = con.prepareStatement(sql);

            preparedStatement.setString(1, memberVO.getId());
            preparedStatement.setString(2, memberVO.getPwd());
            preparedStatement.setString(3, memberVO.getName());
            preparedStatement.setString(4, memberVO.getEmail());
            int result = preparedStatement.executeUpdate();
            if (result > 0) {
                System.out.println("회원 정보 입력 성공");
            }
            preparedStatement.close();
            con.close();
        } catch (Exception e) {
            System.out.println("insert 오류 발생!");
            e.printStackTrace();
        }
    }

    // 회원 정보 삭제 메소드
    public void memberDelete(String id ) {

        try {
            con = dataSource.getConnection();

            String sql = "delete from member where memId=?";
            PreparedStatement preparedStatement = con.prepareStatement(sql);

            preparedStatement.setString(1, id);
            // 쿼리문 실행 : 영향을 받은 행의 수 반환
            //select : executeQuery - 결과 행 resultSet 반환.
            //insert / update / delete : executeUpdate() - 영향을 받은 행의 수 반환
            int result = preparedStatement.executeUpdate();

            if(result > 0) {
                System.out.println("회원 정보 삭제 성공!");
            }
            // 모든 객체 close() : 리소스 반납
            preparedStatement.close();
            con.close();
        } catch (Exception e) {
            System.out.println("delete 발생!");
            e.printStackTrace();
        }
    }
}
package com.example.servlet4.sec06;

import java.util.Date;

public class MemberVO {
    private String id;
    private String pwd;
    private String name;
    private String email;
    private Date joinDate;

    // 디폴트 생성자
    public MemberVO() { }
    // 현재는 매개변수 있는 생성자 필요 없다.
    public MemberVO(String id, String pwd, String name, String email, Date joinDate) {
        this.id = id;
        this.pwd = pwd;
        this.name = name;
        this.email = email;
        this.joinDate = joinDate;
    }

    public MemberVO(String id, String pwd, String name, String email) {
        this.id = id;
        this.pwd = pwd;
        this.name = name;
        this.email = email;
    }

    // Getter / Setter
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPwd() {return pwd;}

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Date getJoinDate() {
        return joinDate;
    }

    public void setJoinDate(Date joinDate) {
        this.joinDate = joinDate;
    }
}
package com.example.servlet4.sec06;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;

//@WebServlet(name = "MemberSelectServlet", value = "/MemberSelectServlet")
@WebServlet("/sec06/MemberSelectServlet2")
public class MemberSelectServlet2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }
    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        // 서버에서 클라이언트로 데이터 전송에 자바 IO스트림 이용
        PrintWriter out = response.getWriter();

        MemberDAO dao = new MemberDAO();
        ArrayList<MemberVO> memList = dao.memberSelect();
        out.print("<html><head></head><body>");
        out.print("<table border=1><tr align='center' bgcolor='gold'>");
        out.print("<td>아이디</td><td>비밀번호</td><td>이름</td><td>이메일</td>" +
                "<td>가입일</td><td>삭제</td></tr>");
        for(int i = 0; i < memList.size(); i++) {
            // 오브젝트 반환 MemberVO 타입으로 형변환
            MemberVO vo = (MemberVO)memList.get(i);
            String id = vo.getId();
            String pwd = vo.getPwd();
            String name = vo.getName();
            String email = vo.getEmail();
            Date joinDate = vo.getJoinDate();
            // 한 행씩 출력
            out.print("<tr><td>" + id + "</td><td>" +
                                    pwd + "</td><td>" +
                                    name + "</td><td>" +
                                    email + "</td><td>" +
                                    joinDate + "</td><td>" +
                                    "<a href='/MemberDeleteServlet?id=" + id + "'>삭제</a></td></tr>");
        }
        out.print("</table></body></head>");
    }
}
package com.example.servlet4.sec06;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Scanner;

@WebServlet("/sec06/MemberInsertServlet")
public class MemberInsertServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");

        String id = request.getParameter("user_id");
        String pwd = request.getParameter("user_pw");
        String name = request.getParameter("user_name");
        String email = request.getParameter("user_email1");

        MemberVO memberVO = new MemberVO();
        memberVO.setId(id);
        memberVO.setPwd(pwd);
        memberVO.setName(name);
        memberVO.setEmail(email);
        // or
        // MemberVO memberVO = new MemberVO(id, pwd, name,email);
        MemberDAO memberDAO = new MemberDAO();
        memberDAO.memberInsert(memberVO);
    }
}
package com.example.servlet4.sec06;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;

//@WebServlet("/MemberDeleteServlet")
@WebServlet(name = "MemberDeleteServlet", value = "/MemberDeleteServlet")
public class MemberDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doProcess(request, response);
    }

    protected void doProcess(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String id = request.getParameter("id");

        MemberDAO dao = new MemberDAO();
        dao.memberDelete(id);
        // select 결과 페이지로 포워딩
        response.sendRedirect("sec06/MemberSelectServlet2");
    }
}
728x90
Comments