20220915_thu
DB시험 문제 연습_ 6번문제
6. 사원의 사번, 이름, 부서번호, 부서명을 조회해보자. ( 조인서브쿼리 X )
부서명은 부서번호가 10일 때는 ‘인사부’, 20일 때는 ‘영업부’ 그 외의 값은 ‘생산부’로 조회되어야 한다. DECODE함수나 CASE 함수를 사용하여 쿼리문을 작성해보자. (10점) [수행준거 1.2, 2.2]
- 방법1) DECODE() 함수사용
-- //DECODE 함수//--- --(디코드함수 : 자바의 IF문과 같다 ) --DECODE(컬럼명,조건1,값1,조건2,값2,....,) SELECT * FROM EMP; -- DISTINCT : 중복제외 하나씩만 조회하기 SELECT DISTINCT JOB FROM EMP;--직급별조회 --시험문제 6번 -- 직급이 사원인 조건만 1의 값을 부여,그밖은 2의 값 출력 SELECT JOB , DECODE(JOB,'사원','1') , DECODE(JOB,'사원','1','2') , DECODE(JOB,'사원','1','대리','2','3') , DECODE(JOB,'사원','1','대리','2')--사원이면 1, 대리면 2, 나머지는 NULL FROM EMP;
- 방법2) CASE문 사용
- CASE 문법
CASE WHEN 조건1 THEN 값1 -- WHEN 조건2 THEN 값2 -- ... -- ELSE 값 -- END --시험문제 6번 SELECT ENAME , JOB , CASE WHEN JOB = '사원' THEN '1' WHEN JOB = '대리' THEN '2' ELSE '3' END FROM EMP;
-- 사용예시) 직급별 급여의 합 구하기
-- 해석) 직급이 사원이면 신입 아니면 고인물이라고 조회하고,
-- COMM 성과금이 NULL이면 0으로 조회하라
SELECT DECODE(JOB,'사원','신입','고인물')
, NVL(COMM,0)
FROM EMP;
-- 그룹함수(단일행함수) : 데이터 조회시, 하나(한줄)의 데이터만 나오는 함수.
-- MAX(),SUM() 해당
-- 단, 단일행함수는 여러 행으로 조회되는 함수와 같이 사용불가능!
-- 대신 단일행함수끼리는 같이 사용 가능!
SELECT MAX(SAL)
FROM EMP;
SELECT SUM(SAL)
FROM EMP;
-- 소속 부서별 평균 급여 조회
SELECT DISTINCT DEPTNO FROM EMP;
-- ROUND : 반올림함수
-- ROUND 값 뒤의 숫자는 반올림해서 몇번째까지 표현해라
SELECT ROUND(123.456)
, ROUND(123.456,1)
, ROUND(123.456,2)
FROM DUAL;
-- ROUND 이용
SELECT DEPTNO
, ROUND(AVG(SAL),2)
, NVL(ROUND(AVG(COMM),2),0) -- 인센티브가 NULL이면 안된다
FROM EMP
GROUP BY DEPTNO;-- 주의)조회되는 데이터의 행의 갯수가 동일하지않으면 사용불가능!
--(참고)
-- SUBSTR 이용
-- 부서별로 묶어서 평균을 구하라.
SELECT SUBSTR(AVG(SAL),1,6)
FROM EMP
GROUP BY deptno; -- 주의)조회되는 데이터의 행의 갯수가 동일하지않으면 사용불가능!
-- 직급별 인원수를 조회하되,
-- 직급이 과장은 직급은 조회에서 제외하라.
-- 순서중요!! FROM - WHERE - GROUP BY
SELECT JOB
, COUNT(EMPNO)
FROM EMP
WHERE JOB != '과장'
GROUP BY JOB;
-- 주의) 그룹결과값으로 조회해야할 때
-- HAVING 함수 사용!!!
-- 직급별 인원수를 조회하되,
-- 해당직급의 인원수가 2명 이상인 직급에 대해서만 조회
-- 순서) FROM - GROUP BY - HAVING
SELECT JOB
, COUNT(EMPNO)
FROM EMP
GROUP BY JOB
HAVING COUNT(EMPNO) >= 2;
-- 직급별 인원수, 급여의 합을 조회하되,
-- 직급이 과장인 직급은 제외하고 ,직급별 인원수가 2명이상인 직급에 대해서만 조회
-- 단, 조회시 급여의 합을 기준으로 내림차순 조회
-- <순서> FROM > WHERE > GROUP BY > HAVING > ORDER BY
SELECT JOB, COUNT(EMPNO) , SUM(SAL)
FROM EMP
WHERE JOB != '과장'
GROUP BY JOB
HAVING COUNT(EMPNO) >= 2
ORDER BY SUM(SAL) DESC
스프링부트에서 게시판 만들기
실습 : 새로운 게시판 프로젝트를 처음부터 만들어 게시판 기능 구현하기
- 프로젝트 생성 : FinalBoard
< 프로젝트 셋팅 순서>
- 설정 : application.properties
- porm.xml파일에 필요한 jar파일 추가 : dependecies 추가(2개)
- 필요한 파일 추가 (쿼리 로그 출력을 위한 파일) : log4jdbc.log4j2.properties , logback.xml
- DB파일 생성 : FINAL_BOARD.sql (SHOP_USER계정)
- cf)사용할 기능
- layout(fragment)
- bootStrap
- thymeleaf(detail)
- validation(input태그 유효성처리검사)
- spring security
1. 전체프로젝트에 폰트 설정
2. top.html 디자인 작업하기.
3. 회원가입 페이지 만들기
FinalBoard 프로젝트 파일 생성
BaordVO
package kh.study.board.board.vo; import groovy.transform.ToString; import org.springframework.stereotype.Service; import lombok.Getter; @Getter @Service @ToString public class BoardVO { private int boardNum; private String title; private String content; private String memberId; private String createDate; }
package kh.study.board.member.vo; import groovy.transform.ToString; import lombok.Getter; import lombok.Setter; @Getter @Setter @ToString public class MemberVO { private String memberId; private String memberPw; private String memberName; private String memberTell; private String isAdmin; private String memberStatus; }
커맨드객체
- 커맨드객체는 html로 데이터를 전달하는 코드를 작성하지 않아도 자동으로 넘어간다.
- 이때 데이터가 넘어가는 이름은 클래스명에서 앞글자만 소문자로 변경된 이름으로 넘어간다.
@Controller @RequestMapping("/board") public class BoardController { @Resource(name = "memberService") private MemberService memberService; //목록페이지 @GetMapping("/list") public String boardList() { return "content/board/board_list"; } //join @GetMapping("/join")//a태그는 무조건 get 방식!!!(암기) public String join(MemberVO memberVO) { //자동으로 커맨드 객체는 넘어간다.(memberVO) //커맨드객체에 아이디값 임의로 넣어주면, html로 넘어갈때 데이터 넘어감 System.out.println(memberVO); //memberVO.setMemberId(memberService.join(memberVO)); return "content/board/join"; } //로그인 @GetMapping("/login")//a태그는 무조건 get 방식!!!(암기) public String login() { return "content/board/login"; } }
<mapper namespace="memberMapper"> <!-- 회원가입 --> <insert id="join"> INSERT INTO BOARD_MEMBER ( MEMBER_ID, MEMBER_PW, MEMBER_NAME, MEMBER_TELL,MEMBER_STATUS ) VALUES( #{memberId},#{memberPw},#{memberName},#{memberTell},'ACTIVE' ) </insert> </mapper>
@charset "UTF-8"; @font-face { font-family: 'HallymGothic-Regular'; src: url('https://cdn.jsdelivr.net/gh/projectnoonnu/noonfonts_2204@1.0/HallymGothic-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; } body{ font-family: 'HallymGothic-Regular'; font-size: 25px; } a{ text-decoration: none; color: #224B0C; } a:hover { color: #A1C298; }
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout" layout:decorate="~{layout/base_layout}"><!-- 콘솔 warn 안뜨기위해 --> <div layout:fragment="content"> 게시글 목록.... </div> </html>
- th 타임리프사용하려면 경로이동은!!! 골뱅이+{}사용하기!!!
th:object="${memberVO}"
는 데이터받기위해 사용 : 컨트롤러에서 보낸 객체 받아오기!!!- 커맨드객체 memberVO는 자동으로 데이터 가져와서 사용가능하다
- 단, th:field는 th:object와 반드시 함께 사용하는 애트리뷰트
- formx태그에 th:object로 넘어오는 커맨드객체를 지정할 경우. 해당 폼 태그 내에서 th:field 속성으로 자동으로 id,name,value 값을 세팅할 수 있다.
- 개발자모드 콘솔을 보면 th:feild속성값만으로 name,id,value값 모두 확인가능하다!!!
- th:field 받지않고 원래 사용하던 방법
id :<input type="text" name="memberId" id="memberId">
th:field
받아와서 사용하는 방법
*{memberId}
라는 값으로 들어오는 데이터 받아와서 사용하겠다.
join.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout" layout:decorate="~{layout/base_layout}"> <div layout:fragment="content"> <!-- row justify-content-center : 가운데 정렬 --> <div class="row justify-content-center"> <div class="col-6"> <form th:action="@{/member/join}" class="row g-3" method="post" th:object="${memberVO}"> <div class="col-12"> <label for="memberId" class="form-label"> ID </label> <input type="text" class="form-control" th:field="*{memberId}"> </div> <div class="col-12"> <label for="memberPw" class="form-label">PASSWORD</label> <input type="password" class="form-control" th:field="*{memberPw}"> </div> <div class="col-12"> <label for="memberName" class="form-label">NAME</label> <input type="text" class="form-control" th:field="*{memberName}"> </div> <div class="col-4"> <!-- 연락처는 타임리프 사용하면 에러난다!!! --> <label for="memberTell" class="form-label">TELL</label> <select id="memberTell" class="form-select" > <option selected>010</option> <option>011</option> </select> </div> <div class="col-4"> <label for="" class="form-label"> </label> <input type="text" class="form-control" id="" name=""> </div> <div class="col-4"> <label for="" class="form-label"> </label> <input type="text" class="form-control" id="" name=""> </div> <div class="col-12 d-grid gap-2"> <button type="submit" class="btn btn-primary">JOIN</button> </div> </form> </div> </div> </div> </html>
login.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout" layout:decorate="~{layout/base_layout}"> <div layout:fragment="content"> login </div> </html>
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org"> <div th:fragment="topFragment"> <!-- 로그인 클릭시 로그인html파일 이동방법 --> <!-- 1번 <a href="/board/login">login</a> --> <!-- 2번 <a th:href="@{/board/login}"> login</a><!-- 타임리프 경로이동시!!! 골뱅이+중괄호 --> <div class="row"> <div class="col text-end" style="color:#224B0C;"> <a th:href="@{/board/login}">login</a><!-- a태그 -> get방식!!! --> <a th:href="@{/board/join}">join</a><!-- a태그 -> get방식!!! --> <!-- <span th:onclick="location.href='/board/join';"></span> --> </div> </div> <div class="row"> <div class="col text-center" style="background-color: #EEF2E6;"> <span style="font-weight: bold; font-size: 50px; color: #3D8361;">Board</span> </div> </div> </div> </html>
<!DOCTYPE html> <!-- 타임리프,레이아웃 기능 사용하겠다 --> <html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultra.net.nz/thymeleaf/layout"> <head> <meta charset="UTF-8"> <title>Insert title here</title> <!-- 부트스트랩 사용 1 --> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT" crossorigin="anonymous"> <link href="/css/common.css" rel="stylesheet"> </head> <body> <!-- 화면에 보여지는 모든 내용은 여기 div태그 안에서 표시된다 --> <div class="container"> <div class="row"> <div class="col"> <div th:replace="fragment/top::topFragment" ></div> </div> </div> <div class="row"> <div class="col"> <div layout:fragment="content"></div> </div> </div> </div> <!-- jquery 로딩 --> <script src="https://code.jquery.com/jquery-latest.min.js"></script> <!-- 부트스트랩 로딩 _사용 2 --> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8" crossorigin="anonymous"></script> </body> </html>
public interface MemberService { void join(MemberVO memberVO); }
@Service("memberService") public class MemberServiceImpl implements MemberService{ @Autowired//어노테이션으로 객체생성 private SqlSessionTemplate sqlSession; //회원가입 @Override public void join(MemberVO memberVO) { sqlSession.insert("memberMapper.join", memberVO); } }