
package edu.global.ex.vo;
import java.sql.Timestamp;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
@Setter
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class BoardVO {
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;
}
package edu.global.ex.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import edu.global.ex.page.Criteria;
import edu.global.ex.vo.BoardVO;
@Mapper
public interface BoardMapper{
public List<BoardVO> getList();
BoardVO read(int bid); // 파라미터는 url로 넘어오는 bid값
void insert(BoardVO board); // 글쓰기
int delete(BoardVO board); // 글 삭제
int modify(BoardVO board); // 수정
public void hit(int bid);
// 답글 관련
void updateShape(BoardVO boardVO); // 답글 위치
void insertReply(BoardVO boardVO); // 답글 등록
// paging 관련
int getTotalCount();
public List<BoardVO> getListWithPaging(Criteria cri);
}
// 자식: BoardMapper.xml
// Mapper가 DAO, Service가 Command랑 비슷한 거
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="edu.global.ex.mapper.BoardMapper">
<select id="getList" resultType="edu.global.ex.vo.BoardVO">
<!-- 여기 들어가는 문구는 xml이 아니라는걸 표현해주는거임. -->
<![CDATA[
select * from mvc_board order by bgroup desc, bstep asc
]]>
</select>
<select id="read" resultType="BoardVO">
<![CDATA[
select * from mvc_board where bid = #{bid}
]]>
</select>
<insert id="insert"> <!-- id에는 함수명이 들어가야함. -->
<![CDATA[
insert into mvc_board (bid, bname, btitle, bcontent, bhit, bgroup, bstep, bindent)
values (mvc_board_seq.nextval, #{bname}, #{btitle}, #{bcontent}, 0, mvc_board_seq.currval, 0, 0)
]]>
</insert>
<delete id="delete">
<![CDATA[
delete from mvc_board where bid = #{bid}
]]>
</delete>
<update id="modify">
<![CDATA[
update mvc_board set btitle = #{btitle}, bcontent = #{bcontent} where bid = #{bid}
]]>
</update>
<update id="hit">
<![CDATA[
update mvc_board set bhit = bhit+1 where bid = #{bid}
]]>
</update>
<!--댓글을 하나씩 미뤄서 정렬을 해줘야 하기 때문에
세로 정렬을 bstep에 +1로 한칸씩 미뤄내줘야한다. -->
<update id="updateShape">
<![CDATA[
update mvc_board set bstep = bstep + 1 where bgroup =#{bgroup} and bstep > #{bstep}
]]>
</update>
<insert id="insertReply" >
<![CDATA[
insert into mvc_board (bid, bname, btitle, bcontent, bgroup, bstep, bindent)
values (mvc_board_seq.nextval, #{bname}, #{btitle},#{bcontent},
#{bgroup}, #{bstep}+1, #{bindent}+1)
]]>
</insert>
<select id="getTotalCount" resultType="int">
<![CDATA[
select count(*) from mvc_board
]]>
</select>
<select id="getListWithPaging" resultType="BoardVO">
<![CDATA[
SELECT * FROM (
SELECT ROWNUM AS RNUM, A.* FROM (
SELECT
*
FROM
mvc_board
order by bGroup desc, bStep asc
) A WHERE ROWNUM <= #{pageNum} * #{amount}
) WHERE RNUM > (#{pageNum}-1) * #{amount}
]]>
</select>
</mapper>
package edu.global.ex.service;
import java.util.List;
import edu.global.ex.page.Criteria;
import edu.global.ex.vo.BoardVO;
public interface BoardService {
public List<BoardVO> getList();
BoardVO read(int bid);
public void register(BoardVO boardVO);
int remove(BoardVO board);
int modify(BoardVO board);
void registerReply(BoardVO board);
// paging
int getTotal();
List<BoardVO> getList(Criteria criteria); // 리스트 메소드
}
//Mapper가 DAO, Service가 Command랑 비슷한 거
package edu.global.ex.serviceImpl;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import edu.global.ex.mapper.BoardMapper;
import edu.global.ex.page.Criteria;
import edu.global.ex.service.BoardService;
import edu.global.ex.vo.BoardVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Service
public class BoardServiceImpl implements BoardService{
@Autowired
BoardMapper boardmapper;
@Override
public List<BoardVO> getList() {
List<BoardVO> list = boardmapper.getList();
return list;
}
@Override
public void register(BoardVO boardVO) {
log.info("register()..");
boardmapper.insert(boardVO);
}
@Override
public BoardVO read(int bid) {
log.info("read()..");
boardmapper.hit(bid);
return boardmapper.read(bid);
}
@Override
public int remove(BoardVO board) {
log.info("remove()..");
return boardmapper.delete(board);
}
@Override
public int modify(BoardVO board) {
log.info("modify()..");
return boardmapper.modify(board);
}
@Transactional
@Override
public void registerReply(BoardVO board) {
log.info("registerReply()..");
boardmapper.updateShape(board);
boardmapper.insertReply(board);
}
@Override
public int getTotal() {
log.info("getTotal() ..");
return boardmapper.getTotalCount();
}
@Override
public List<BoardVO> getList(Criteria criteria) {
log.info("getList(Criteria criteria) ..");
return boardmapper.getListWithPaging(criteria);
}
}
package edu.global.ex.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import edu.global.ex.page.Criteria;
import edu.global.ex.page.PageVO;
import edu.global.ex.service.BoardService;
import edu.global.ex.vo.BoardVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Controller
public class BoardController {
@Autowired
private BoardService boardService;
//http://localhost:8282/list2?pageNum=5&amount=10">1</a>
@GetMapping("/list2")
public String list2(Criteria cri, Model model) {
log.info("list2() ..");
log.info("list2() Criteria " + cri);
model.addAttribute("boards", boardService.getList(cri));
int total = boardService.getTotal();
log.info("total" + total);
model.addAttribute("pageMaker", new PageVO(cri, total));
return "list2";
}
@GetMapping("/list")
public String list(Model model) {
log.info("list()..");
model.addAttribute("boards", boardService.getList());
return "list";
}
@GetMapping("/write_view")
public String write_view() {
log.info("write_view()..");
return "write_view";
}
@GetMapping("/content_view")
public String content_view(int bid, Model model) {
log.info("content_view()..");
model.addAttribute("result", boardService.read(bid));
return "content_view";
}
@PostMapping("/write")
public String write(BoardVO boardVO) {
log.info("write()..");
boardService.register(boardVO);
return "redirect:list";
}
@GetMapping("/delete")
public String delete(BoardVO boardVO) {
log.info("delete()..");
int rn = boardService.remove(boardVO);
log.info("delete().. result number::" + rn);
return "redirect:list";
}
@PostMapping("/modify")
public String modify(BoardVO boardVO) {
log.info("modify()..");
boardService.modify(boardVO);
return "redirect:list";
}
@GetMapping("/reply_view")
public String reply_view(BoardVO boardVO, Model model) {
log.info("reply_view()..");
model.addAttribute("reply_view", boardService.read(boardVO.getBid()));
return "reply_view";
}
@PostMapping("/reply")
public String reply(BoardVO boardVO, Model model) {
log.info("reply_view()..");
boardService.registerReply(boardVO);
return "redirect:list";
}
@GetMapping("/board/table")
public String table(BoardVO boardVO, Model model) {
log.info("table()..");
// EL {}
model.addAttribute("table", boardService.getList());
return "table";
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!-- C태그 쓰기 위해 넣은 taglib므로 반드시 확인 -->
<!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>
<!--이때 list는 BListCommand에서 메모리에 올린 list를 뜻함. 포워딩시까지 살아있으므로-->
<!--forEach문을 이용해 데이터를 꺼낼 수 있다.-->
<c:forEach var="board" items="${boards}">
<tr>
<td>${board.bid}</td>
<td>${board.bname}</td>
<td>
<c:forEach begin="1" end="${board.bindent}">[Re]</c:forEach>
<a href="content_view?bid=${board.bid}">${board.btitle}</a>
<!--bindent : 가로 (댓글이 보이는 순서 때문에 들어간 것)-->
</td>
<td>${board.bdate}</td>
<td>${board.bhit}</td>
</tr>
</c:forEach>
<tr>
<td colspan="5"> <a href="write_view">글 작성</a></td>
</tr>
</table>
<c:if test="${pageMaker.prev}">
<a href="list2${pageMaker.makeQuery(pageMaker.startPage - 1) }">«</a>
</c:if>
<c:forEach begin="${pageMaker.startPage }" end="${pageMaker.endPage }" var="idx">
<c:out value="${pageMaker.cri.pageNum == idx?'':''}" />
<a href="list2${pageMaker.makeQuery(idx)}">${idx}</a>
</c:forEach>
<c:if test="${pageMaker.next && pageMaker.endPage > 0}">
<a href="list2${pageMaker.makeQuery(pageMaker.endPage +1) }"> » </a>
</c:if> <br>
</body>
</html>

개발자가 직접 작성한 Class를 Bean으로 등록하고, DI를 위한 가장 기본적인 어노테이션
Spring에서 관리되는 객체임을 표시하기 위해 사용하는 가장 기본적인 annotation
Web MVC에 사용되는 어노테이션이다. (해당 클래스를 MVC 모듈의 컨트롤러로 인식하게 해준다.)
@RequestMapping, @GetMapping과 같은 URI 요청 어노테이션은 @Controller가 붙은 클래스에서만 동작한다.
@Component와 다른 기능은 없지만 비즈니스 로직에 해당 어노테이션을 사용하여 명시적으로 비즈니스 로직을 가지고 있는 클래스임을 나타내게 해준다.
해당 클래스를 데이터 접근 계층으로 인식하며, 데이터 계층의 예외를 추상화하여 스프링 예외로 변환하여 던져준다.
@Component, @Service, @Repository는 Bean객체를 만드는 역할을 한다. @Component가 가장 큰 단위고 @Service, @Repository 등을 구체적으로 사용하면 어떤 부분에 쓰이는지 시각적으로 판단하기 편하다.
Interface를 매퍼로 등록하기 위해 사용한다.
Spring Boot에서 어플리케이션을 실행한다.
@SpringBootApplication을 찾아서 테스트를 위한 빈들을 생성한다.
-- 이름에 A가 들어가는 모든 사원의 이름과 부서 이름을 출력하라.
SELECT E.ENAME, D.DNAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO
AND E.ENAME LIKE '%A%';
-- 커미션이 책정되어 있는 모든 사원의 이름, 부서이름 및 위치를 출력하라.
SELECT E.ENAME, D.DNAME FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO
AND E.COMM IS NOT NULL;
-- DALLAS에서 근무하는 모든 사원의 이름, 직업, 부서번호 및 부서이름을 출력하라.
SELECT E.ENAME, E.JOB, D.DNAME, E.DEPTNO FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO AND D.LOC = 'DALLAS';
-- 모든 사원의 이름, 직업, 부서이름, 급여 및 등급을 출력하라.
SELECT E.ENAME, E.JOB, D.DNAME, S.GRADE FROM EMP E, DEPT D, SALGRADE S
WHERE E.DEPTNO = D.DEPTNO AND E.SAL BETWEEN S.LOSAL AND S.HISAL;
-- Smith보다 늦게 입사한 사원의 이름 및 입사일을 출력하라.
SELECT ENAME, HIREDATE FROM EMP WHERE HIREDATE >
(SELECT HIREDATE FROM EMP WHERE ENAME = 'SMITH');
-- 모든 사원의 급여 최고액, 최저액, 총액 및 평균액을 출력하라.
SELECT MAX(SAL) AS Maximum, MIN(SAL) AS Minimum, SUM(SAL) AS Sum,
AVG(SAL) AS Average FROM EMP;
-- 각 직업별로 급여 최저액, 최고액, 총액 및 평균액을 출력하라.
SELECT JOB, MIN(SAL), MAX(SAL), SUM(SAL), AVG(SAL) FROM EMP GROUP BY JOB;
-- 직업이 동일한 사람 수를 직업과 같이 출력하라.
SELECT JOB, COUNT(*) FROM EMP GROUP BY JOB;