
그룹으로 묶을 컬럼명이나 표현식을 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;
-- 사원들의 총 급여를 구하는 쿼리문
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;
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);
}
}
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
클라이언트로부터 최초에 들어온 요청을 JSP/Servlet내에서 원하는 자원으로 요청을 넘기는(보내는) 역할을 수행하거나, 특정 자원에 처리를 요청하고 처리 결과를 얻어오는 기능을 수행하는 클래스
서블릿에서 값을 넘겨주고 해당 페이지에서 처리할 수 있도록 함.
RequestDispatcher view = request.getRequestDispatcher("경로");
request.setAttribute("key",value);
view.forward(request, response);
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;
}
}
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="입력">
<a href="list.do">목록보기</a></td>
</tr>
</form>
</table>
</body>
</html>
Model: 애플리케이션의 데이터와 비즈니스 로직을 담는 객체
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: 사용자에게 모델의 정보(데이터)를 보여주는 역할
Controller: 모델과 뷰 사이에 어떤 동작이 있을 때 조정하는 역할
쌤 첨부터 끝까지 다 뽀려가요 ..... 💜