12월 2일 - 수업 30일차 JSP/SQL

수아레스·2022년 12월 2일
post-thumbnail

1. group by에 대하여 설명하시오.

그룹으로 묶을 컬럼명이나 표현식을 GROUP BY 절에 명시해서 사용한다.

-- 사원 테이블을 부서 번호로 그룹 짓는 쿼리문
SELECT DEPTNO FROM EMP GROUP BY DEPTNO;

cf. having 절

GROUP BY절 다음에 위치해 GROUP BY한 결과를 대상으로 다시 필터를 거는 역할을 수행하는 조건문

-- 그룹 지어진 부서별 평균 급여가 2000 이상인 부서의 번호와 부서별 평균 급여를 출력하는 쿼리문

SELECT DEPTNO, AVG(SAL) FROM EMP GROUP BY DEPTNO 
HAVING AVG(SAL) >= 2000;

2. 아래의 SQL문을 작성하시오.

-- 사원들의 총 급여를 구하는 쿼리문
SELECT SUM(SAL) FROM EMP;

-- 커미션(COMM) 총액을 구하는 쿼리문
SELECT SUM(NVL(COMM,0)) FROM EMP;

-- 급여 평균을 구하는 쿼리문
SELECT AVG(SAL) FROM EMP;

-- 가장 높은 급여와 가장 낮은 급여를 구하는 쿼리문
SELECT MAX(SAL), MIN(SAL) FROM EMP;

-- 총 사원수
SELECT COUNT(*) FROM EMP;

-- 사원 테이블의 사원들 중에서 커미선(COMM)을 받은 사원의 수
SELECT COUNT(COMM) FROM EMP;

-- 사원들의 JOB의 종류를 뽑아내시오 (중복 제거)
SELECT DISTINCT JOB FROM EMP;

-- 담당 업무(JOB)의 개수를 구하시오.
SELECT COUNT(DISTINCT JOB) AS 담당업무 FROM EMP;

-- 사원 테이블을 부서 번호로 그룹 짓는 쿼리문
SELECT DEPTNO FROM EMP GROUP BY DEPTNO;

-- 소속 부서별 평균 급여를 구하는 쿼리문
SELECT AVG(SAL) FROM EMP GROUP BY DEPTNO;

-- 소속 부서별 급여 총액과 평균 급여를 구하는 쿼리문
SELECT DEPTNO, SUM(SAL), AVG(SAL) FROM EMP GROUP BY DEPTNO;

-- 부서별 사원의 수와 커미션을 받는 사원의 수를 계산하는 쿼리문
SELECT DEPTNO, COUNT(*), COUNT(COMM) FROM EMP GROUP BY DEPTNO;

-- 그룹 지어진 부서별 평균 급여가 2000 이상인 부서의 번호와 
부서별 평균 급여를 출력하는 쿼리문
SELECT DEPTNO, AVG(SAL) FROM EMP GROUP BY DEPTNO 
HAVING AVG(SAL) >= 2000;

-- 부서의 최대값과 최소값을 구하되, 최대 급여가 2900 이상인 부서만  출력하는 쿼리문
SELECT DEPTNO, MAX(SAL), MIN(SAL) FROM EMP GROUP BY DEPTNO HAVING MAX(SAL) >= 2900;

3. board 게시판 DB를 만들고, list.jsp를 model 2 방식으로 프로그램밍 하시오.


command 패키지

Bcommand

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public interface Bcommand {
	// 인터페이스이므로 메소드 선언만 가능하다.
	void execute(HttpServletRequest request, HttpServletResponse response);
}

BListcommand

package edu.global.ex.command;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.global.ex.dao.BDAo;
import edu.global.ex.dto.BDTo;

public class BListcommand implements Bcommand{

	// 자손이 구현하므로 interface의 메소드를 override한다.
	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		
		BDAo dao = new BDAo();
		// 테이블에 있는 모든 데이터를 끌고 온다는 뜻
		List<BDTo> dtos = dao.list();
		
		// request는 forwarding될 때까지 메모리에 살아있음☆★ 
		// 메모리에 올라가 있으면 EL로 request 영역에 접근 가능 ("list"로 올라가 있음)
		// BController에서 command.execute가 실행되면 list를 넣어줌
		request.setAttribute("list", dtos);
	}
}

BWritecommand

package edu.global.ex.command;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import edu.global.ex.dao.BDAo;
import edu.global.ex.dto.BDTo;

public class BWritecommand implements Bcommand{

	@Override
	public void execute(HttpServletRequest request, HttpServletResponse response) {
		
		String bname = request.getParameter("bname");
		String btitle = request.getParameter("btitle");
		String bcontent = request.getParameter("bcontent");
		
		BDAo dao = new BDAo();
		// 테이블에 있는 모든 데이터를 끌고 온다는 뜻
		dao.write(bname, btitle, bcontent);
	}
}

controller 패키지

BController

package edu.global.ex.controller;

import java.io.IOException;

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.global.ex.command.BListcommand;
import edu.global.ex.command.Bcommand;

// 모든 url들은 webServlet에서 받아내겠다는 뜻
@WebServlet("*.do")
public class BController extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public BController() {
        super();
        
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		System.out.println("doGet()..");
		actionDo(request, response);
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		System.out.println("doPost()..");
		actionDo(request, response);
	}
	
	private void actionDo(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	System.out.println("actionDo()..");
	
	request.setCharacterEncoding("UTF-8");
	
	String viewPage = null;
	Bcommand command = null;
	
	// 아래의 세 줄은 http://localhost:8282/jsp_mvc_board/list에서 꺼내기 위한 코드들
		String uri = request.getRequestURI();
		String conPath = request.getContextPath();
		String com = uri.substring(conPath.length());
		
		System.out.println("경로 확인 " + uri + ":" + conPath + ":" +  com);
		
		if(com.equals("/list.do")) {
			System.out.println("디버깅 문구");
			command = new BListcommand();
			command.execute(request, response);
			viewPage = "list.jsp";	// jsp는 서블릿에서 관리됨
		}else if(com.equals("/write_view.do")) {
			System.out.println("/write_view.do ..");
			viewPage = "write_view.jsp";
		}
		/*
		 * 클라이언트에게 list는 list.jsp로 forwarding 시키겠다는 의미이다.
		 * forwarding은 BListCommand 클래스에서 메모리에 올린 request, response 객체 정보를 
         list.jsp에서 사용 가능하다는 의미다.
		 * forwarding될 때까지 정보가 살아있으므로 list.jsp에서 
         forEach문을 사용하여 데이터를 꺼낼 수 있다.
		 */	
		
        RequestDispatcher dispatcher = request.getRequestDispatcher(viewPage);
		dispatcher.forward(request, response);
		
        // list.jsp에 request, response 객체를 포워딩해줌 -> 
        // 메모리로 올라가면서(클래스 생성, 실행됨) 유저한테 보여지게 됨	
	}
}

uri : 인터넷 기본 주소 제외 -> /jsp_mvc_board/list.do
conPath(= ContextPath) : 파일명or프로젝트명 -> jsp_mvc_board
com(=command) = uri.substring(conPath.length()) : 프로젝트명 뒤의 주소 -> list.do

cf.

컨텍스트 패스: 웹 어플리케이션 서버(Web Application Server) = Tomcat에서 웹상의 어플리케이션들을 구분하기 위한 Path

RequestDispatcher:

클라이언트로부터 최초에 들어온 요청을 JSP/Servlet내에서 원하는 자원으로 요청을 넘기는(보내는) 역할을 수행하거나, 특정 자원에 처리를 요청하고 처리 결과를 얻어오는 기능을 수행하는 클래스

서블릿에서 값을 넘겨주고 해당 페이지에서 처리할 수 있도록 함.

RequestDispatcher view = request.getRequestDispatcher("경로"); 
request.setAttribute("key",value);
view.forward(request, response);
  • 서블릿에서 처리한 데이터를 jsp에서 가져다가 사용해야 할 때 쓰는 객체
  • RequestDispatcher는 이동할 경로를 설정하고 생성
  • 생성된 객체를 가지고 forward 메소드를 통해 해당 경로 페이지로 이동할 수 있음
  • 이때, sendRedirect와는 다르게 requestresponse 객체를 가지고 이동할 수 있음 (경로 이동시 데이터를 가져갈 수 있음) -> 현재 request에 담긴 정보를 저장하고 있다가 이동한 페이지에서도 그 정보를 볼 수 있게 계속 저장해줌.
  • 호출된 페이지에서는 request.getAttribute() 메소드를 통해 넘겨받은 데이터를 처리할 수 있음.

dao 패키지

BDAo

package edu.global.ex.dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

import edu.global.ex.dto.BDTo;

public class BDAo {
	
	private DataSource datasource = null;
	
	public BDAo() {
		try {
			Context context = new InitialContext();
			datasource = (DataSource) context.lookup("java:comp/env/jdbc/oracle");
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}
	
	public void write(String bname, String btitle, String bcontent){
		System.out.println("write() ..");
		
		Connection conn = null;
		PreparedStatement ps = null;
		
		try {
			/*
			 * 파라미터로 받는 값이 bname, btitle, bcontent 3개므로 3개만 ?로 넣고 나머지는 0으로 설정했다.
			 *  글 작성시 조회수(bhit)는 0이고, 원본 글로 취급하므로 bstep, bindent는 지수를 넣어줄 필요가 없기 때문이다.
			 */
			String query = "insert into mvc_board "
		               + "(bid, bname, btitle, bcontent, bhit, bgroup, bstep, bindent)"
		               + "values (mvc_board_seq.nextval,?,?,?,0, mvc_board_seq.currval,0,0)";
													// ?는 각각 bname, btitle, bcontent (setString 메소드로 넣어줄 값)
			conn = datasource.getConnection();
			ps = conn.prepareStatement(query);
			
			ps.setString(1, bname);
			ps.setString(2, btitle);
			ps.setString(3, bcontent);
			
			int rn = ps.executeUpdate();	// 실행할때는 executeQuery()
			System.out.println("업데이트 개수: "+ rn);
			
		}catch(Exception e) {
			e.printStackTrace();
		  }finally {
		         try {         
		         
		            if(ps != null) ps.close();
		            if(conn != null) conn.close();
		            
		         } catch (Exception e2) {
		            
		         }  
		      }
		   }
		
	
	public List<BDTo> list(){
		ArrayList<BDTo> dtos = new ArrayList<>();
		
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		
		try {
			String query = "select * from mvc_board";
			conn = datasource.getConnection();
			ps = conn.prepareStatement(query);
			rs = ps.executeQuery();
			
			while(rs.next()) {
				int bid = rs.getInt("bid");
				String bname = rs.getString("bname");
				String btitle = rs.getString("btitle");
				String bcontent = rs.getString("bcontent");
				Timestamp bdate = rs.getTimestamp("bdate");
				int bhit = rs.getInt("bhit");
				int bgroup = rs.getInt("bgroup");
				int bstep = rs.getInt("bstep");
				int bindent = rs.getInt("bindent");
				
				BDTo dto = new BDTo(bid, bname, btitle, bcontent, bdate, bhit, bgroup, bstep, bindent);
				dtos.add(dto);
			}

		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if(rs != null) {
					rs.close();
				}if(ps != null) {
					ps.close();
				}if(conn != null) {
					conn.close();
				}
			}catch(Exception e2) {
				e2.printStackTrace();
			}
		}
		return dtos;
	}	
}

dto 패키지

BDTo

package edu.global.ex.dto;

import java.sql.Timestamp;

/*
이름       널?       유형            
-------- -------- ------------- 
BID      NOT NULL NUMBER(4)     
BNAME             VARCHAR2(20)  
BTITLE            VARCHAR2(100) 
BCONTENT          VARCHAR2(300) 
BDATE             DATE          
BHIT              NUMBER(4)     
BGROUP            NUMBER(4)     
BSTEP             NUMBER(4)     
BINDENT           NUMBER(4)  */

public class BDTo {
	private int bid;
	private String bname;
	private String btitle;
	private String bcontent;
	private Timestamp bdate;
	private int bhit;
	private int bgroup;
	private int bstep;
	private int bindent;
	
	public BDTo() {}

	public BDTo(int bid, String bname, String btitle, String bcontent, Timestamp bdate, int bhit, int bgroup, int bstep,
			int bindent) {
		this.bid = bid;
		this.bname = bname;
		this.btitle = btitle;
		this.bcontent = bcontent;
		this.bdate = bdate;
		this.bhit = bhit;
		this.bgroup = bgroup;
		this.bstep = bstep;
		this.bindent = bindent;
	}

	public int getBid() {
		return bid;
	}

	public void setBid(int bid) {
		this.bid = bid;
	}

	public String getBname() {
		return bname;
	}

	public void setBname(String bname) {
		this.bname = bname;
	}

	public String getBtitle() {
		return btitle;
	}

	public void setBtitle(String btitle) {
		this.btitle = btitle;
	}

	public String getBcontent() {
		return bcontent;
	}

	public void setBcontent(String bcontent) {
		this.bcontent = bcontent;
	}

	public Timestamp getBdate() {
		return bdate;
	}

	public void setBdate(Timestamp bdate) {
		this.bdate = bdate;
	}

	public int getBhit() {
		return bhit;
	}

	public void setBhit(int bhit) {
		this.bhit = bhit;
	}

	public int getBgroup() {
		return bgroup;
	}

	public void setBgroup(int bgroup) {
		this.bgroup = bgroup;
	}

	public int getBstep() {
		return bstep;
	}

	public void setBstep(int bstep) {
		this.bstep = bstep;
	}

	public int getBindent() {
		return bindent;
	}

	public void setBindent(int bindent) {
		this.bindent = bindent;
	}
}

list.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<table width="500" border="1"> 
	<tr>
		<td>번호</td>
		<td>이름</td>
		<td>제목</td>
		<td>날짜</td>
		<td>히트</td>
	</tr>
	<!-- BListcommand에서 request로 메모리에 올린 list에 EL객체로 접근함.
    포워딩할 때까지 살아있으므로 forEach문을 이용해 데이터를 꺼낼 수 있다.-->
	<c:forEach var="board" items="${list}">
		<tr>
			<td>${board.bid}</td>
			<td>${board.bname}</td>
			<td>${board.btitle}</td>
			<td>${board.bdate}</td>
			<td>${board.bhit}</td>
		</tr>
	</c:forEach>
	
	<tr>
		<td colspan="5"><a href="write_view.do">글 작성</a></td>
	</tr>
	
</table>
</body>
</html>

write_view.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
   pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<table width="500" cellpadding="0" cellspacing="0" border="1">
      <form action="write.do" method="post">
         <!--form action : form태그에서 submit시 write.do로 이동하도록 설정하는부분  -->
         <tr>
            <td>이름</td>
            <td><input type="text" name="bname" size="50"></td>
         </tr>
         <tr>
            <td>제목</td>
            <td><input type="text" name="btitle" size="50"></td>
         </tr>
         <tr>
            <td>내용</td>
            <td><textarea name="bcontent" rows="10"></textarea></td>
         </tr>                  
         <tr>
            <td colspan="2"> <input type="submit" value="입력">
            &nbsp;&nbsp;<a href="list.do">목록보기</a></td>
         </tr>      
      </form>
   </table>
</body>
</html>

4. 게시판 설계를 위한 설계도를 그리시오.

5. model, view, controller에 대하여 설명하시오.

Model: 애플리케이션의 데이터와 비즈니스 로직을 담는 객체

  • 데이터베이스와의 관계를 담당한다.
  • 클라이언트의 요청에서 필요한 자료를 데이터베이스로부터 추출하거나 수정하여 Controller로 전달한다.

JSP Servlet으로 웹 어플리케이션을 만들 때에는 보통 request나 session 내장객체에 정보를 담아 jsp에 넘겨주었는데, Spring에서는 Model을 쓴다.
즉, request.setAttribute() 와 비슷한 역할을 하는 것.

public String home(Model model) {
	model.addAttribute("time", new java.util.Date());
    	return "home";
}

개발자가 직접 model을 생성할 필요가 없다. 파라미터로 선언만 해주면 스프링이 알아서 만들어준다.

스프링 MVC의 Controller는 기본적으로 Java Beans 규칙에 맞는 객체는 자동으로 화면에 전달해준다. (Java Beans의 규칙에 맞는다는 것은 단순히 생성자가 없거나 빈 생성자를 가지며, getter/setter를 가진 클래스의 객체들을 의미한다.)

전달될 때는 클래스명의 앞글자를 소문자로 처리하여 전달한다.

View: 사용자에게 모델의 정보(데이터)를 보여주는 역할

  • 주로 .jsp파일로 작성하며 Controller에서 어떤 View 컴포넌트를 보여줄지 결정한다.
  • 비즈니스 로직을 포함하지 않으며 하나의 모델을 다양한 뷰에서 사용할 수 있다.

⁠Controller: 모델과 뷰 사이에 어떤 동작이 있을 때 조정하는 역할

  • 웹으로부터 받은 요청에 가장 적합한 모델을 생성하는 것을 처리하는 역할과 사용자에게 응답하는 적절한 뷰를 선택하여 해당 모델을 전달하는 역할을 한다.
  • 클라이언트의 요청을 받고 적절한 Model에 지시를 내리며, Model에서 전달된 데이터를 적절한  View에 전달한다. ⁠
  • 이렇게 작업을 분할하면 추후 유지보수에 좋다. 
profile
띵호와

2개의 댓글

comment-user-thumbnail
2022년 12월 5일

쌤 첨부터 끝까지 다 뽀려가요 ..... 💜

1개의 답글