Controller

 

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

package com.board.study.web;

import com.board.study.dto.board.BoardRequestDto;
import com.board.study.service.BoardService;
import lombok.RequiredArgsConstructor;
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 org.springframework.web.bind.annotation.RequestParam;

@RequiredArgsConstructor
@Controller
public class BoardController {

    private final BoardService boardService;

    @GetMapping("/board/list")
    public String getBoardListPage(Model model, @RequestParam(required = false, defaultValue = "0") Integer page, @RequestParam(required = false, defaultValue = "5") Integer size) throws Exception {

        try {
            model.addAttribute("resultMap", boardService.findAll(page, size));
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return "/board/list";
    }

    @GetMapping("/board/view")
    public String getBoardViewPage(Model model, BoardRequestDto boardRequestDto) throws Exception {

        try {
            if (boardRequestDto.getId() != null) {
                model.addAttribute("info", boardService.findById(boardRequestDto.getId()));
            }
        } catch (Exception e) {
            throw new Exception(e.getMessage());
        }
        return "/board/view";
    }

    @PostMapping("board/view/action")
    public String boardVewAction(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";
    }

    @GetMapping("/board/write")
    public String getBoardWritePage(Model model, BoardRequestDto boardRequestDto) {
        return "/board/write";
    }

    @PostMapping("/board/write/action")
    public String boardWriteAction(Model model, BoardRequestDto boardRequestDto) throws Exception {

        try {
            Long result = boardService.save(boardRequestDto);

            if (result < 0) {
                throw new Exception("#Exception boardWriteAction!");
            }
        } 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

 

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

package com.board.study.service;

import com.board.study.dto.board.BoardRequestDto;
import com.board.study.dto.board.BoardResponseDto;
import com.board.study.entity.Board;
import com.board.study.repository.BoardRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

@RequiredArgsConstructor
@Service
public class BoardService {

    private final BoardRepository boardRepository;


    @Transactional
    public Long save(BoardRequestDto boardRequestDto) {
        return boardRepository.save(boardRequestDto.toEntity()).getId();
    }


//    @Transactional(readOnly = true)
//    public List<BoardResponseDto> findAll() {
//        return boardRepository.findAll().stream().map(BoardResponseDto::new).collect(Collectors.toList());
//    }

    @Transactional(readOnly = true)
    public HashMap<String, Object> findAll(Integer page, Integer size) {

        HashMap<String, Object> resultMap = new HashMap<String, Object>();

        Page<Board> list = boardRepository.findAll(PageRequest.of(page, size));

        resultMap.put("list", list.stream().map(BoardResponseDto::new).collect(Collectors.toList()));
        resultMap.put("paging", list.getPageable());
        resultMap.put("totalCnt", list.getTotalElements());
        resultMap.put("totalPage", list.getTotalPages());

        return resultMap;
    }

    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 int updateBoardReadCntInc(Long id) {
//        return boardRepository.updateBoardReadCntInc(id);
//    }

    public void deleteById(Long id) {
        boardRepository.deleteById(id);
    }

    public void deleteAll(Long[] deleteId) {
        boardRepository.deleteBoard(deleteId);
    }
}

 

 

 

 

Repository

 

상세 화면 조회 시 조회수 증가 및 삭제 구현

package com.board.study.repository;

import com.board.study.dto.board.BoardRequestDto;
import com.board.study.entity.Board;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;

public interface BoardRepository extends JpaRepository<Board, Long> {

    static final String UPDATE_BOARD = "UPDATE Board " +
            "SET TITLE = :#{#boardRequestDto.title}, " +
            "CONTENT = :#{#boardRequestDto.content}, " +
            "UPDATE_TIME = NEW() " +
            "WHERE ID = :#{#boardRequestDto.id}";

    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, nativeQuery = true)
    public int updateBoard(@Param("boardRequestDto") BoardRequestDto boardRequestDto);

    @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);
}

 

 

목록

 

list.html

<!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"); //id
                frm.attr("action","/board/delete");
                frm.attr("method","post");
                frm.submit();
            }
        } else {
            alert("Not selected.");
        }
    }
</script>
</body>
</html>

 

 

 

상세

 

view.html

<!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" cols="" 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>

 

 

복사했습니다!