Today
-
Yesterday
-
Total
-

ABOUT ME

-

  • Spring Boot (게시판) - 4 | 수정, 삭제 구현하기
    ▼ Backend/└ 게시판 만들기 2021. 11. 1. 14:58
    반응형

    [스프링 부트 (Spring Boot)/게시판 만들기] - 3 | 등록, 상세, 리스트 페이지 구현하기]

     

    구성환경

    SpringBoot, Gradle, Thymeleaf, Jpa(JPQL), Jar, MariaDB

     

    이번 포스팅에서는 지난번 내용에 이어서 Form 전송을 통한 수정과 삭제(단건, 다건) 처리를 진행해본다.

     

    컨트롤러(Controller)

    BoardController.java

     

    상세화면 수정, 상세화면 내에서 삭제, 목록에서 삭제에 대한 서비스 호출 처리

     

    @PostMapping("/board/view/action")
    public String boardViewAction(Model model, BoardRequestDto boardRequestDto) throws Exception {
    
        try {
            int result = boardService.updateBoard(boardRequestDto);
    
            if (result < 1) {
                throw new Exception("#Exception boardViewAction!");
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    
        return "redirect:/board/list";
    }
    
    @PostMapping("/board/view/delete")
    public String boardViewDeleteAction(Model model, @RequestParam() Long id) throws Exception {
    
        try {
            boardService.deleteById(id);
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    
        return "redirect:/board/list";
    }
    
    @PostMapping("/board/delete")
    public String boardDeleteAction(Model model, @RequestParam() Long[] deleteId) throws Exception {
    
        try {
            boardService.deleteAll(deleteId);
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
    
        return "redirect:/board/list";
    }

     

     

    서비스(Service)

    BoardService.java

     

    상세화면 수정, 상세화면 삭제, 목록에서 삭제 서비스 구현

     

    public BoardResponseDto findById(Long id) {
        boardRepository.updateBoardReadCntInc(id);
        return new BoardResponseDto(boardRepository.findById(id).get());
    }
    
    public int updateBoard(BoardRequestDto boardRequestDto) {
        return boardRepository.updateBoard(boardRequestDto);
    }
    
    public void deleteById(Long id) {
        boardRepository.deleteById(id);
    }
    
    public void deleteAll(Long[] deleteId) {
        boardRepository.deleteBoard(deleteId);
    }

     

    레파지토리(Repository)

    BoardRepository.java

     

    상세 화면 조회 시 조회수 증가 및 삭제 구현(단건, 다건)

     

    static final String UPDATE_BOARD_READ_CNT_INC = "UPDATE Board "
    			+ "SET READ_CNT = READ_CNT + 1 "
    			+ "WHERE ID = :id";
    	
    static final String DELETE_BOARD = "DELETE FROM Board "
    			+ "WHERE ID IN (:deleteList)";
                
    @Transactional
    @Modifying
    @Query(value = UPDATE_BOARD_READ_CNT_INC, nativeQuery = true)
    public int updateBoardReadCntInc(@Param("id") Long id);
    
    @Transactional
    @Modifying
    @Query(value = DELETE_BOARD, nativeQuery = true)
    public int deleteBoard(@Param("deleteList") Long[] deleteList);

     

    목록 HTML

    list.html (/src/main/resources/templates/board)

     

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    
    <head>
        <title>Board List</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <!--부트스트랩 css 추가-->
        <link rel="stylesheet" href="/css/lib/bootstrap.min.css">
    </head>
    
    <body>
        <div id="wrapper">
            <div class="container">
                <form action="/board/list" id="frm" method="get">
                    <div class="col-md-12 mt-4">
                        <button type="button" class="btn btn-danger" onclick="fnDelete()">Delete</button>
                        <button type="button" class="btn btn-primary" onclick="javascript:location.href='/board/write'">Register</button>
                        <table class="table table-striped table-horizontal table-bordered mt-3">
                            <thead class="thead-strong">
                                <tr>
                                    <th width="5%"><input type="checkbox" id="chkAll"></th>
                                    <th width="10%">게시글번호</th>
                                    <th width="">제목</th>
                                    <th width="20%">작성자</th>
                                    <th width="10%">조회수</th>
                                    <th width="20%">작성일</th>
                                </tr>
                            </thead>
                            <tbody id="tbody">
                                <tr th:each="list,index : ${resultMap.list}" th:with="paging=${resultMap.paging}">
                                    <td>
                                        <input type="checkbox" name="deleteId" th:value="${list.id}">
                                    </td>
                                    <td>
                                        <span th:text="${(resultMap.totalCnt - index.index) - (paging.pageNumber * paging.pageSize)}"></span>
                                    </td>
                                    <td>
                                        <a th:href="@{./view(id=${list.id})}">
                                            <span th:text="${list.title}"></span>
                                        </a>
                                    </td>
                                    <td>
                                        <span th:text="${list.registerId}"></span>
                                    </td>
                                    <td>
                                        <span th:text="${list.readCnt}"></span>
                                    </td>
                                    <td>
                                        <span th:text="${list.registerTime}"></span>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <div class="row">
                            <div class="col">
                                <ul class="pagination">
                                    <li class="page-item" th:each="index : ${#numbers.sequence(1, resultMap.totalPage)}" th:with="paging=${resultMap.paging}">
    									<a class="page-link" th:classappend="${paging.pageNumber ==  (index-1)} ? bg-primary : bg-secondary" th:href="@{./list(page=${index - 1},page=${paging.pageSize})}">
    							  			<span class="text-white" th:text="${index}"></span>
    						    		</a>
    						  		</li>
    					    	</ul>
    						</div>
    					</div>
    				</div>
    			</form>
    		</div>
    	</div>
    	<!--부트스트랩 js, jquery 추가-->
    	<script src="/js/lib/jquery.min.js"></script>
    	<script src="/js/lib/bootstrap.min.js"></script>
    	<script th:inline="javascript">
              // header checkbox event
              $("#chkAll").click(function () {
                  if (this.checked) {
                      $("input[name='deleteId']").prop("checked", true);
                  } else {
                      $("input[name='deleteId']").prop("checked", false);
                  }
              });
              // body checkbox event
              $("input[name='deleteId']").click(function () {
                  let delInpLen = $("input[name='deleteId']").length;
                  let delInpChkLen = $("input[name='deleteId']:checked").length;
                  if (delInpLen == delInpChkLen) {
                      $("#chkAll").prop("checked", true);
                  } else {
                      $("#chkAll").prop("checked", false);
                  }
              });
              function fnDelete() {
                  let delInpChkLen = $("input[name='deleteId']:checked").length;
                  if (delInpChkLen > 0) {
                      if (confirm("Do you want to delete it?")) {
                          let frm = $("#frm");
                          frm.attr("action", "/board/delete");
                          frm.attr("method", "post");
                          frm.submit();
                      }
                  } else {
                      alert("Not selected.");
                  }
              }
    	</script>
    </body>
    </html>

     

    상세 HTML

    view.html (/src/main/resources/templates/board)

     

    <!DOCTYPE html>
    <html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>Board List</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <!--부트스트랩 css 추가-->
        <link rel="stylesheet" href="/css/lib/bootstrap.min.css">
    </head>
    <body>
        <div class="container">
            <h1>Board View.</h1>
            <form id="frm" action="/board/view/action" method="post">
                <input type="hidden" name="id" th:value="${info.id}">
                <div class="mb-3">
                    <label class="form-label">Title.</label>
                    <input type="text" class="form-control" name="title" th:value="${info.title}">
                </div>
                <div class="mb-3">
                    <label class="form-label">Content</label>
                    <textarea class="form-control" rows="5" name="content" th:text="${info.content}"></textarea>
                </div>
                <div class="mb-3">
                    <label class="form-label">Writer.</label>
                    <input type="text" class="form-control" name="registerId" th:value="${info.registerId}">
                </div>
                <div class="float-left">
                    <button type="button" class="btn btn-success" onclick="javascript:location.href='/board/list'">Previous</button>
                    <button type="submit" class="btn btn-primary">Edit</button>
                </div>
                <div class="float-right">
                    <button type="button" class="btn btn-danger" th:onclick="fnViewDelete()">Delete</button>
                </div>
            </form>
        </div>
        <!--부트스트랩 js, jquery 추가-->
        <script src="/js/lib/jquery.min.js"></script>
        <script src="/js/lib/bootstrap.min.js"></script>
        <script th:inline="javascript">
            function fnViewDelete() {
                if (confirm("Do you want to delete it?")) {
                    let frm = $("#frm");
                    frm.attr("action", "/board/view/delete");
                    frm.submit();
                }
            }
        </script>
    </body>
    </html>

     

     

    Thymeleaf

    이름 설명
    th:if
    th:unless
    조건이 참 또는 거짓이면 해당 태그를 노출한다.

    <span th:if="${data} == 'data'"></span>
    <span th:unless="${data} == 'data'"></span>

    ※ th:unless if 의 조건과 unless 의 조건을 동일하게 적어야 동작한다.


    th:if 단독으로도 사용가능하다.
    th:classappend 조건이 참이면, 거짓이면 해당 클래스를 추가한다.
    <a th:classappend="${data == 'data'} ? bg-primary : bg-secondary"</a>

     

    마무리

    여기까지 SpringBoot, Gradle, Thymeleaf, Jpa(JPQL), MariaDB을 이용한 간단한 게시판 만들기였고,  CRUD 기능을 가볍게 구현해보기 위한 내용으로 디테일한 부분은 부족하니 직접 수정해보거나, 추가적으로 등록될 기능들을 아래에서 참고하여 구현해보도록 한다.

     

     

    GitHub

     

    Spring Boot (게시판) - 1 |  스프링 부트 프로젝트 만들기

    Spring Boot (게시판) - 2 |  데이터베이스(MariaDB) 연동 및 JPA CRUD

    Spring Boot (게시판) - 3 |  등록, 상세, 리스트 페이지 구현하기

    Spring Boot (게시판) - 4 |  수정, 삭제 구현하기

     

     

    프로젝트 Import

    압축을 풀고, 이클립스 import    General  →  Existing Projects into Workspace

    board_study.zip
    0.22MB

     

    반응형

    댓글

Designed by Tistory.