반응형
List > Create > Read > Update > Delete
1. Mapper 작성
<select id="showBoard" resultMap="Board">
select
board_seq,
writer,
title,
content,
reg_date,
upt_date,
view_cnt
from board
where board_seq = #{seq}
</select>
<update id="incViewCnt">
update board
set
view_cnt = nvl(view_cnt, 0) + 1
where board_seq = #{seq}
</update>
조회수 컬럼이 있고 조회를 하면 조회수가 올라가야 하기 때문에 해당 PK의 게시물의 조회수를 조회하고 +1 해주는 쿼리도 같이 작성해 줍니다.
2. Dao, DaoImpl 작성
// Dao
// 이전 코드
Map<String, Object> showBoard(int seq);
void incViewCnt(int seq);
// DaoImpl
// 이전 코드
@Override
public Map<String, Object> showBoard(int seq) {
return sqlsession.selectOne("BoardMapper.showBoard", seq);
}
@Override
public void incViewCnt(int seq) {
sqlsession.update("BoardMapper.incViewCnt", seq);
}
게시글은 여러 정보의 집합체이기 때문에 Map으로 반환 해줍니다.
3. Service, ServiceImpl 작성
// Service
// 이전 코드
Map<String, Object> showBoard(int seq);
void incViewCnt(int seq);
// ServiceImpl
// 이전 코드
@Override
public Map<String, Object> showBoard(int seq) {
return boardDao.showBoard(seq);
}
@Override
public void incViewCnt(int seq) {
boardDao.incViewCnt(seq);
}
4. Controller 작성
// 이전 코드
@RequestMapping(value="/read/{seq}", method = RequestMethod.GET)
public ModelAndView readBoard(@PathVariable("seq") int seq, ModelAndView mav) {
Map<String, Object> boardMap = boardSer.showBoard(seq);
if(boardMap != null) {
boardSer.incViewCnt(seq);
}
mav.addObject("board", boardMap);
mav.setViewName("read");
return mav;
}
알아보니 ModelAndView는 유연성이 좋다고 합니다. 기존의 Model 변수 model의 addAttribute와 addObject가 유사하고, return "jspName" 과 setViewName("jspName")이 유사한 기능을 합니다. 다만 코드가 복잡해 질 수 있다고 하니 유의하며 사용해야겠습니다.
그리고 boardMap이 존재하지 않은 경우에는 조회수를 올리지 않도록 합니다. 애초에 안 되지 않나 싶지만 있는 것도 제대로 조회 못하는 경우도 있으니 조건문을 넣어줍니다. 왜 그런지는 차차 살펴보기로...
5. read.jsp 생성
6. read.jsp 작성
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<c:set var="path" value="${ pageContext.request.contextPath }" />
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="/resources/assets/css/style.css">
<title>Read Page</title>
</head>
<body>
<header>
<div class="container">
<h1>Read Page : ${board.title }</h1>
</div>
</header>
<nav>
<div class='container'>
<ul>
<li><a href='#'>Home</a></li>
<li><a href='#'>About</a></li>
<li><a href='#'>Contact</a></li>
</ul>
</div>
</nav>
<main>
<div class='container'>
<table>
<thead>
<tr>
<th rowspan="2">작성자</th>
<td rowspan="2">${board.writer }</td>
<th>업로드 날짜</th>
<td><fmt:formatDate value="${board.regDate }" pattern="yyyy-MM-dd"/></td>
</tr>
<tr>
<th>업데이트 날짜</th>
<td><fmt:formatDate value="${board.uptDate }" pattern="yyyy-MM-dd"/></td>
</tr>
</thead>
<tbody>
<tr>
<td colspan="4">${board.content }</td>
</tr>
</tbody>
</table>
<button>수정</button>
<button onclick='goToPrevPage()'>이전</button>
</div>
</main>
<aside>
<div class='container'>
<h2>Sidebar</h2>
<p>This is the sidebar</p>
</div>
</aside>
<script src="https://code.jquery.com/jquery-3.7.1.js" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>
<script>
function goToPrevPage(){
window.history.back();
}
</script>
</body>
</html>
수정 버튼은 위치만 잡아두도록 합니다.
7. listPage.jsp에서 read.jsp로 갈 수 있도록 a 태그를 추가해 줍니다.
<!-- 바꾸기 전 코드 -->
<td>${boardList.title}</td> <!-- title -->
<!-- 바꾼 후 코드 -->
<td><a href="${path}/read/${boardList.boardSeq}">${boardList.title}</a></td> <!-- title -->
8. 결과물
후기
이번에는 정말 이상한 에러들을 만났습니다. 검색하고 고쳐봐도 잘 안 돼서 이번 주제 관련 코드들만 싹 지우고 다시 그대로 썼는데 의아할 정도로 잘 돌아가서 아직도 왜 오류가 났었는지 이해가 가질 않습니다.
재부팅해서 해결되는 컴퓨터 문제 같은 걸까요...
다음번엔 Update로 돌아오겠습니다. 빠잇!
반응형
'Spring > CRUD Project' 카테고리의 다른 글
[CRUD] Delete : 글 삭제하기 (1) | 2023.11.27 |
---|---|
[CRUD] Update : 글 수정하기 (1) | 2023.11.24 |
[CRUD] Create : 글 쓰기 (0) | 2023.11.22 |
[CRUD] List : 목록 출력 (2) | 2023.11.21 |
[CRUD] 개요 & 준비 (1) | 2023.11.20 |