1. 페이징
- boardList.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BoardList</title>
</head>
<body>
<h2>게시물 목록</h2>
<table border="1px">
<tr>
<td>번호</td>
<td>제목</td>
<td>내용</td>
<td>조회수</td>
</tr>
<tr th:each="item : ${list}">
<td th:text="${item.bno}"></td>
<td th:text="${item.title}"></td>
<td th:text="${item.content}"></td>
<td th:text="${item.view_cnt}"></td>
</tr>
</table>
<div>
<th:block th:if="${ph.beginPage}>1">
<a th:href="@{'/board/list?page='+${ph.beginPage+-1}}"><</a>
</th:block>
<th:block th:each="i : ${#numbers.sequence(ph.beginPage, ph.endPage)}">
<a th:href="@{'/board/list?page=' + ${i} + '&pageSize=' + ${ph.pageSize}}"><span th:text="${i}">1</span></a>
</th:block>
<th:block th:if="${ph.endPage}<${ph.page_cnt}">
<a th:href="@{'/board/list?page='+${ph.endPage+1}}">></a>
</th:block>
</div>
</body>
</html>
- BoardController
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
BoardDao boardDao;
// 게시판 목록
@GetMapping("/list")
public String list(Integer page, Integer pageSize, Model m){
if(page==null)
page=1;
if(pageSize==null)
pageSize=10;
PageHandler ph = new PageHandler(boardDao.count(), page, pageSize);
Map map = new HashMap();
map.put("offset", (page-1)*pageSize);
map.put("pageSize", pageSize);
List<BoardDto> list = boardDao.selectPage(map);
m.addAttribute("list", list);
m.addAttribute("page",page);
m.addAttribute("pageSize",pageSize);
m.addAttribute("ph",ph);
return "boardList";
}
}
2. 게시물 삭제
// 게시물 삭제
@PostMapping("/delete")
public String delete(Integer page, Integer pageSize, BoardDto boardDto, Model m, RedirectAttributes rattr, HttpSession session){
Map map = new HashMap();
map.put("bno", boardDto.getBno());
map.put("writer", boardDto.getWriter());
System.out.println("boardDto.getWriter() = " + boardDto.getWriter());
try{
int rowCnt=0;
// if(session.getAttribute("id").equals(boardDto.getWriter()))
rowCnt = boardDao.delete(map);
if(rowCnt==0){
m.addAttribute("msg", "DEL_ERR");
throw new Exception("delete Error");
}
rattr.addFlashAttribute("msg", "DEL_OK");
rattr.addFlashAttribute("page", page);
rattr.addFlashAttribute("pageSize", pageSize);
System.out.println("boardDto = " + boardDto);
return "redirect:/board/list";
}catch(Exception e){
e.printStackTrace();
return "board";
}
}
- post방식으로 Mapping된 delete라서 board.html에서도 post방식으로 데이터를 전송해줘야한다.
- a태그 사용시 Get방식으로 데이터가 전송되기때문에 a태그를 사용하지 않고 자바스크립트를 사용해줬다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<title>Board</title>
</head>
<body>
<h2>게시물 읽기</h2>
<form id="form">
<input name="bno" type="hidden" th:value="${boardDto.bno}"/>
<input name="title" type="text" th:value="${boardDto.title}"/>
<textarea name="content" th:text="${boardDto.content}"></textarea>
<button>글쓰기</button>
<button>수정</button>
<!-- <button type="submit" name="delBtn"><a th:href="@{'/board/delete?page='+${page}+'&pageSize='+${pageSize}+'&bno='+${boardDto.bno}+'&writer='+${boardDto.writer}}">삭제</a></button>-->
<button type="button" id="delBtn">삭제</button>
<button type="button" name="listBtn"><a th:href="@{'/board/list?page='+${page}+'&pageSize='+${pageSize}}">목록</a></button>
</form>
<script>
$(document).ready(function(){
$('#delBtn').on("click",function(){
if(!confirm("정말로 삭제하시겠습니까?")) return;
let form = $('#form');
form.attr("action", "/board/delete?page=[[${page}]]&pageSize=[[${pageSize}]]&bno=[[${boardDto.bno}]]&writer=[[${boardDto.writer}]]");
form.attr("method", "post");
form.submit();
});
});
</script>
</body>
</html>
- button태그를 input태그로 바꿔도 보고, type을 submit으로도 바꿔보았지만 a태그가 더 우선적인건지 무조건 Get방식으로 보내져서 자바스크립트로 delete를 작성해야했다.
3. 게시물 읽기
// 게시물 읽어오기
@GetMapping("/read")
public String read(Integer page, Integer pageSize, BoardDto boardDto, Model m){
// boardList.html 에서 title 을 누르면 /board/read 페이지로 넘어온다.
BoardDto boardDto2 = boardDao.select(boardDto.getBno());
m.addAttribute("page", page);
m.addAttribute("pageSize", pageSize);
m.addAttribute("boardDto", boardDto2);
System.out.println("read/page = " + page);
System.out.println("read/pageSize = " + pageSize);
System.out.println("read/boardDto = " + boardDto2);
return "board";
}
- 게시물 선택 쿼리
<select id="select" resultType="BoardDto" parameterType="int">
SELECT *
FROM board
WHERE bno=#{bno}
</select>
- page와 pageSize bno(게시물번호)를 read메서드로 넘겨준다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BoardList</title>
</head>
<body>
<h2>게시물 목록</h2>
<table border="1px">
<tr>
<td>번호</td>
<td>제목</td>
<td>내용</td>
<td>작성자</td>
<td>조회수</td>
</tr>
<tr th:each="item : ${list}">
<td th:text="${item.bno}"></td>
<td><a th:href="@{'/board/read?page='+${page}+'&pageSize='+${pageSize}+'&bno='+${item.bno}}"><span th:text="${item.title}"></span></a></td>
<td th:text="${item.content}"></td>
<td th:text="${item.writer}"></td>
<td th:text="${item.view_cnt}"></td>
</tr>
</table>
<div>
<th:block th:if="${ph.beginPage}>1">
<a th:href="@{'/board/list?page='+${ph.beginPage+-1}}"><</a>
</th:block>
<th:block th:each="i : ${#numbers.sequence(ph.beginPage, ph.endPage)}">
<a th:href="@{'/board/list?page=' + ${i} + '&pageSize=' + ${ph.pageSize}}"><span th:text="${i}">1</span></a>
</th:block>
<th:block th:if="${ph.endPage}<${ph.page_cnt}">
<a th:href="@{'/board/list?page='+${ph.endPage+1}}">></a>
</th:block>
</div>
</body>
</html>
4. 게시물 수정
- 게시물을 수정하기 버튼을 누르기 전에는 readonly속성으로 글을 변경할 수 없어야한다.
<form id="form">
<input id="bno" type="hidden" th:value="${boardDto.bno}" readonly="readonly"/>
<input id="title" type="text" th:value="${boardDto.title}" th:attr="readonly=${menu != 'write'}"/>
<textarea id="content" th:text="${boardDto.content}" th:attr="readonly=${menu != 'write'}"></textarea>
<button>새글쓰기</button>
<button type="button" id="wrtBtn" th:text="${menu eq 'write' ? '수정완료' : '수정'}"></button>
<button type="button" id="delBtn">삭제</button>
<button type="button" id="listBtn"><a th:href="@{'/board/list?page='+${page}+'&pageSize='+${pageSize}}">목록</a></button>
</form>
- th:attr을 사용해서 menu가 write가 아니면 readonly속성을 추가하도록 만들었다.
- update 쿼리문
<update id="update" parameterType="BoardDto">
UPDATE board
SET title=#{title}, content=#{content}
WHERE bno=#{bno} AND writer=#{writer}
</update>
- update메서드는 PostMapping으로 만들것이다.
@Controller
@RequestMapping("/board")
public class BoardController {
@Autowired
BoardDao boardDao;
// 게시물 수정
@PostMapping("/update")
public String update(Integer page, Integer pageSize, BoardDto boardDto, RedirectAttributes rattr){
System.out.println("update/boardDto = " + boardDto);
int rowCnt = boardDao.update(boardDto);
rattr.addFlashAttribute("boardDto",boardDto);
System.out.println("update/page = " + page);
System.out.println("update/pageSize = " + pageSize);
System.out.println("update/boardDto.getBno() = " + boardDto.getBno());
return "redirect:/board/read?page="+page+"&pageSize="+pageSize;
}
// 게시물 삭제
@PostMapping("/delete")
public String delete(Integer page, Integer pageSize, BoardDto boardDto, Model m, RedirectAttributes rattr, HttpSession session){
Map map = new HashMap();
map.put("bno", boardDto.getBno());
map.put("writer", boardDto.getWriter());
System.out.println("delete/boardDto.getWriter() = " + boardDto.getWriter());
try{
int rowCnt=0;
// if(session.getAttribute("id").equals(boardDto.getWriter()))
rowCnt = boardDao.delete(map);
if(rowCnt==0){
m.addAttribute("msg", "DEL_ERR");
throw new Exception("delete Error");
}
rattr.addFlashAttribute("msg", "DEL_OK");
rattr.addFlashAttribute("page", page);
rattr.addFlashAttribute("pageSize", pageSize);
System.out.println("delete/boardDto = " + boardDto);
return "redirect:/board/list";
}catch(Exception e){
e.printStackTrace();
return "board";
}
}
// 게시물 읽어오기
@GetMapping("/read")
public String read(Integer page, Integer pageSize, BoardDto boardDto, Model m){
// boardList.html 에서 title 을 누르면 /board/read 페이지로 넘어온다.
BoardDto boardDto2 = boardDao.select(boardDto.getBno());
m.addAttribute("page", page);
m.addAttribute("pageSize", pageSize);
m.addAttribute("boardDto", boardDto2);
System.out.println("read/page = " + page);
System.out.println("read/pageSize = " + pageSize);
System.out.println("read/boardDto = " + boardDto2);
return "board";
}
// 게시판 목록
@GetMapping("/list")
public String list(Integer page, Integer pageSize, Model m){
if(page==null)
page=1;
if(pageSize==null)
pageSize=10;
PageHandler ph = new PageHandler(boardDao.count(), page, pageSize);
Map map = new HashMap();
map.put("offset", (page-1)*pageSize);
map.put("pageSize", pageSize);
List<BoardDto> list = boardDao.selectPage(map);
m.addAttribute("list", list);
m.addAttribute("page",page);
m.addAttribute("pageSize",pageSize);
m.addAttribute("ph",ph);
return "boardList";
}
}
- board.html에서 데이터가 update메서드로 들어오지 않는것을 확인 후 수정된 클래스
- board.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<title>Board</title>
</head>
<body>
<h2>게시물 읽기</h2>
<form id="form">
<input name="bno" type="hidden" th:value="${boardDto.bno}" readonly/>
<input name="title" type="text" th:value="${boardDto.title}" readonly/>
<textarea name="content" th:text="${boardDto.content}" readonly></textarea>
<input name="writer" type="text" th:value="${boardDto.writer}" readonly/>
<input name="page" type="hidden" th:value="${page}" readonly/>
<input name="pageSize" type="hidden" th:value="${pageSize}" readonly/>
<button>새글쓰기</button>
<button type="button" id="wrtBtn">수정</button>
<button type="button" id="delBtn">삭제</button>
<button type="button" id="listBtn"><a th:href="@{'/board/list?page='+${page}+'&pageSize='+${pageSize}}">목록</a></button>
</form>
<script>
$(document).ready(function(){
$('#delBtn').on("click",function(){
if(!confirm("정말로 삭제하시겠습니까?")) return;
let form = $('#form');
form.attr("action", "/board/delete");
form.attr("method", "post");
form.submit();
});
$('#wrtBtn').on("click", function(){
let form = $('#form');
let isReadOnly = $("input[name=title]").attr('readonly');
if(isReadOnly=='readonly'){
$("textarea[name=content]").removeAttr("readonly");
$("input[name=title]").removeAttr("readonly");
$('h2').html('게시물 수정');
$('#wrtBtn').html('수정완료');
return;
}
if(!confirm("변경하시겠습니까?")) return;
form.attr("action", "/board/update");
form.attr("method", "post");
form.submit();
});
});
</script>
</body>
</html>
- form.submit()메서드를 실행하면 form태그 안에있는 데이터를 자동으로 매핑된 메서드로 전달해준다.
- URL뒤에 붙여줄 값들이 적어졌고 중복이 줄어들었다.
- read메서드와 update메서드에 데이터가 잘 전달된것을 볼 수 있었다.
5. 게시물 등록
- board.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<title>Board</title>
</head>
<body>
<h2>게시물 읽기</h2>
<form id="form">
<input name="bno" type="hidden" th:value="${boardDto.bno}" readonly/>
<input name="title" type="text" th:value="${boardDto.title}" readonly/>
<textarea name="content" th:text="${boardDto.content}" readonly></textarea>
<input name="writer" type="text" th:value="${boardDto.writer}" readonly/>
<input name="page" type="hidden" th:value="${page}" readonly/>
<input name="pageSize" type="hidden" th:value="${pageSize}" readonly/>
<input name="check" type="hidden" readonly />
<button type="button" id="creBtn">새글쓰기</button>
<button type="button" id="wrtBtn">수정</button>
<button type="button" id="delBtn">삭제</button>
<button type="button" id="listBtn">목록</button>
</form>
<script>
$(document).ready(function(){
$('#creBtn').on("click", function(){
let form = $('#form');
let isReadOnly = $("input[name=check]").attr('readonly');
if(isReadOnly=='readonly'){
$("input[name=check]").attr('readonly', false);
$("input[name=title]").attr('readonly', false);
$("textarea[name=content]").attr('readonly', false);
$('#creBtn').html('등록');
$('h2').html('게시물 등록');
return;
}
form.attr("action", "/board/insert");
form.attr("method", "post");
form.submit();
})
$('#listBtn').on("click", function(){
let form = $('#form');
form.attr("action", "/board/list");
form.attr("method", "get");
form.submit();
})
$('#delBtn').on("click",function(){
if(!confirm("정말로 삭제하시겠습니까?")) return;
let form = $('#form');
form.attr("action", "/board/delete");
form.attr("method", "post");
form.submit();
});
$('#wrtBtn').on("click", function(){
let form = $('#form');
let isReadOnly = $("input[name=title]").attr('readonly');
if(isReadOnly=='readonly'){
$("textarea[name=content]").removeAttr("readonly");
$("input[name=title]").removeAttr("readonly");
$('h2').html('게시물 수정');
$('#wrtBtn').html('수정완료');
return;
}
if(!confirm("변경하시겠습니까?")) return;
form.attr("action", "/board/update");
form.attr("method", "post");
form.submit();
});
});
</script>
</body>
</html>
- insert메서드
// 게시물 추가
@PostMapping("/insert")
public String insert(Integer page, Integer pageSize, BoardDto boardDto, RedirectAttributes rattr){
System.out.println("insert/page = " + page);
System.out.println("insert/pageSize = " + pageSize);
System.out.println("insert/boardDto = " + boardDto);
// BoardDto boardDto2 = new BoardDto(boardDto.getTitle(), boardDto.getContent(), (String)session.getAttribute("id"));
BoardDto boardDto2 = new BoardDto(boardDto.getTitle(), boardDto.getContent(), boardDto.getWriter());
boardDao.insert(boardDto);
return "redirect:/board/list?page="+page+"&pageSize="+pageSize;
}
- 기본적인 로그인 체크나 아이디 체크 같은건 생략하고 CRUD에만 집중해서 만들었다.
'MyBatis' 카테고리의 다른 글
10. REST API와 Ajax - 패스트캠퍼스 백엔드 부트캠프 3기 (2) | 2025.03.17 |
---|---|
9. SpringBoot로 검색, 게시물 표시 수 지정 - 패스트캠퍼스 백엔드 부트캠프 3기 (2) | 2025.03.06 |
7. SpringBoot로 MyBatis연동하기 - 패스트캠퍼스 백엔드 부트캠프 3기 (1) | 2025.03.04 |
6. 게시판 읽기, 쓰기, 삭제, 수정 기능구현(2) - 패스트캠퍼스 백엔드 부트캠프 3기 (0) | 2025.03.04 |
5. 게시판 읽기, 쓰기, 삭제, 수정 기능구현(1) - 패스트캠퍼스 백엔드 부트캠프 3기 (2) | 2025.03.03 |