본문 바로가기

Sever

4. JDBC - 연결 생성부터 자원반환까지

✓ 흐름

① 드라이버 로드: 데이터베이스 연결을 위해 해당 데이터베이스 JDBC 드라이버 로드

 연결 생성:  클래스를 이용하여 데이터베이스 연결 객체(Connection)생성(이때, 연결 정보를 지정)

 Statement 생성: Connection 객체를 이용해, SQL문 실행을 위한 Statement 객체 생성

 SQL문 실행: Statement 객체를 이용해 SQL문을 실행, 결과를 ResultSet 객체로 받아옴

 결과 처리: ResultSet 객체를 이용하여 SQL 실행 결과를 처리

 자원 반환: 모든 작업이 완료되면 사용한 자원(Connection, Statement, ResultSet 등)을 반드시 반환

                    (메모리 누수 방지, 다른 프로그램에서 해당 자원 접근 가능)

 

 

✓ 객체 생성

데이터베이스의 테이블과 1:1로 매핑되는 Java클래스들 정의: 생성자, gettet/setter, toString ... 

 

✓ Servlet 

 - Service와 View 계층 사이에서 동작.

 - HTTP 요청을 받아 분석하여 요청에 맞는 Service 메서드를 호출한다. Service 계층에서는 데이터베이스와의 연동 작업을 수행하고, 그 결과를 Servlet으로 반환한다. 

 - 즉, HTTP 요청에 대한 처리를 담당하고 데이터베이스와의 연동작업을 수행하는 등 비즈니스 로직을 처리한다. (View 계층에서는 데이터를 화면에 표시하는 등 UI 처리 담당) 

package edu.kh.jsp.student.controller;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
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 edu.kh.jsp.student.model.service.StudentService;
import edu.kh.jsp.student.model.vo.Student;

//------------------------------------------


@WebServlet("/student/selectDepartment")
// 이 클래스를 Servlet으로 사용하기 위해 url패턴 매핑

public class SelectDepartmentServlet extends HttpServlet{
// HTTPServlet 클래스를 상속받아 SelectDepartmentServlet클래스 정의 
// 상속받는 이유? 
// Serlvet API를 사용하는 웹 애플리케이션에서 HTTP프로토콜을 사용하는 요청(request)과 응답(response)에 
// 대한 처리를 담당하기 위해서이며, 상속 시 HTTP 요청을 처리하기 위해 사용할 수 있는 다양한 메서드를 제공받음. 
	
    
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
	// HTTP Get요청을 처리하기 위해 doGet() 메서드를 오버라이딩
    
    
		StudentService service = new StudentService();
		// 비즈니스 로직을 수행하기 위해 해당 객체 생성 후 객체의 매서드 호출 
        
		
		try {
			
			String inputDept = req.getParameter("inputDept");
			// inputDept 변수에 HTTP에서 가져온 파라미터 값 대입 
            
			
			List<Student> stdList = service.selectDepartment(inputDept);
			// 학생 전체 조회 서비스 호출 후 결과 반환받기
            
			
			req.setAttribute("stdList", stdList);
			// 조회 결과 request에 세팅
			
			
			RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/views/student/selectDepartment.jsp");
			// "/WEB~" 페이지로 RequestDispatcher 객체 생성 
            
            
			dispatcher.forward(req, resp);
			// 현재 요청 객체와 응답 객체를 "/WEB~" 페이지로 전달 
			
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
}

* RequestDispatcher

 - Servlet에서 다른 Servlet, JSP, HTML 등의 자원으로 제어권을 넘기는 기능 제공. 

 - 현재의 요청과 응답 객체를 다른 자원으로 전달하여 해당 자원에서 요청을 처리하고 응답을 생성 

 - 사용 메서드 

  º foward(): 현재의 요청과 응답 객체를 다른 자원으로 전달. 다른 자원에서 처리된 결과를 클라이언트에 반환. 

  º include(): 현재의 요청과 응답 객체를 다른 자원으로 전달. 다른 자원에서 생성된 응답을 현재의 응답에 포함.

 - 예를 들어, JSP파일에서 데이터베이스에서 조회한 결과를 출력하고자 한다면, 서블릿에서 데이터베이스 조회를 수행하고 JSP파일로 제어권을 전달할 수 있다. 이때, forward() 메서드를 사용하여 JSP파일로 요청과 응답 객체를 전달하면, JSP파일에서는 전달받은 데이터를 출력하여 클라이언트에게 응답한다.   

 

 

② 연결 생성 ~  자원 반환

 - DriverManager 혹은 Connection 인터페이스를 사용하여 데이터베이스와 연결 

 - Service: 비즈니스 로직(데이터 가공, 트랜잭션 제어) 처리를 하며, 실제 프로그램이 제공하는 기능을 모아놓은 클래스 

 - 하나의 Service 메서드에서 n개의 DAO 메서드(SQL실행)를 호출하여 이를 하나의 트랜잭션 단위로 처리해 한 번에 commit, rollback 을 수행할 수 있다. 

package edu.kh.jsp.student.model.service;

import java.sql.Connection;
import java.util.List;

import static edu.kh.jsp.common.JDBCTemplate.*;
import edu.kh.jsp.student.model.dao.StudentDAO;
import edu.kh.jsp.student.model.vo.Student;

// ----------------------------------------------

public class StudentService {


	// DAO 메서드 사용 위한 객체 생성 	
	private StudentDAO dao = new StudentDAO();
    
    
	// SELECT Department를 수행하기 위한 메서드 
	public List<Student> selectDepartment(String inputDept) throws Exception{
		
		// 커넥션 생성
		Connection conn = getConnection();
		

		List<Student> stdList = dao.selectDepartment(conn, inputDept);
		// DAO 메서드를 호출하여 수행 후 결과를 반환 받음. 
		//  → Service에서 생성한 Connection 객체를 반드시 같이 전달 
        
  		// 만약 DAO에서 DML구문을 실행한다면 여기서 트랜잭션 제어 
		// if(result > 0) commit(conn); 
		// else           rollback(conn);
		
		close(conn);
		
		return stdList;
	}

}

 

 

③ Statement 생성

 - DAO(Data Access Object): 데이터가 저장된 DB에 접근하는 객체로 SQL문 실행 및 결과를 반환 받는 기능 수행 

package edu.kh.jsp.student.model.dao;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import static edu.kh.jsp.common.JDBCTemplate.*;

import edu.kh.jsp.student.model.vo.Student;

// ------------------------------------------

public class StudentDAO {
	
	// JDBC 객체를 참조하기 위한 참조변수 선언 
	private Statement stmt; // 빈 SQL
	private PreparedStatement pstmt; // SQL문이 저장되어있음
	private ResultSet rs; // 결과를 반환받음
	

	private Properties prop;
 	// XML로 SQL을 다룰 것 → Properties 객체 사용     
	// Properties 객체
	// key:value 쌍으로 이루어진 데이터를 관리하기 위한 클래스
	// Property 파일에 저장되어 있는 설정 정보를 읽어와서 처리할 때 많이 사용
    
	
	public StudentDAO() {
    
		// StudentDAO 객체 생성 시 해당 쿼리 내용을 읽어와 Properties 객체에 저장
		try {
			String filePath 
				= StudentDAO.class.getResource("/edu/kh/jsp/sql/student-sql.xml").getPath();
			
			prop = new Properties();
			
			prop.loadFromXML(new FileInputStream(filePath));
			
		}catch(Exception e) {
			e.printStackTrace();
		}
	}
	

	/** selectDepartment SQL실행 매서드 
	 * @param conn
	 * @return
	 */
	public List<Student> selectDepartment(Connection conn, String inputDept) throws Exception{
		
		// 결과 저장용 변수 선언 
		List<Student> stdList = new ArrayList<>();
		
        
		try {
			// student-sql.xml애 작성된 SQL 얻어오기(prop이 저장하고 있음) 
			// "entry key 값"
			String sql = prop.getProperty("selectDepartment");
			
			// prepareStatement 객체 생성
			pstmt = conn.prepareStatement(sql);
			
			// 위치 홀더(?)에 알맞은 값 세팅 
			pstmt.setString(1, inputDept);
            
			/* 실행할 SQL문
			<entry key="selectDepartment">
			SELECT STUDENT_NO, STUDENT_NAME, STUDENT_ADDRESS, DEPARTMENT_NAME
			FROM TB_STUDENT
			JOIN TB_DEPARTMENT USING(DEPARTMENT_NO)
			WHERE DEPARTMENT_NAME = ?
			</entry>
			*/
            
            
			// SQL 실행 후 결과 반환 받음 
			rs = pstmt.executeQuery();
            
			// 만약, DML을 수행하는 결과라면 
			//result = pstmt.excuteUpdate();
            
			
			// next(): ResultSet 객체 메서드로 DB에서 조회한 결과 데이터를 가지고 있으며,
			//		   이 객체에서 다음으로 이동하며 데이터를 가져오기 위해 사용됨. 
			while(rs.next()) {
				String studentNo = rs.getString("STUDENT_NO");
				String studentName = rs.getString("STUDENT_NAME");
				String studentAddress = rs.getString("STUDENT_ADDRESS");
				String departmentName = rs.getString("DEPARTMENT_NAME");
				
				// 결과로 받을 List에 추가
				stdList.add(
					new Student(studentNo, studentName, studentAddress, departmentName )
				);
			}
			
		} finally {
			// 사용한 JDBC 객체 자원 반환
			close(rs);
			close(pstmt);
		}
		
		return stdList;
	}
	
}

 

'Sever' 카테고리의 다른 글

6. 이메일 중복 검사 및 인증번호 이메일 보내기 기능 구현하기  (0) 2023.04.05
5. 로그인 기능 구현하기  (1) 2023.04.05
3. JDBC의 흐름 및 JDBC Tamplate  (0) 2023.04.04
2. JSP? + AJAX?  (0) 2023.03.28
1. Sevlet?  (0) 2023.03.27