2022/03/08 서버프로그램구현(board)

무간·2022년 3월 8일

저장소

https://docs.spring.io/spring-data/mongodb/docs/3.0.9.RELEASE/reference/html/#mongodb.repositories.queries

테이블 15

파일명 BoardRepository.java

package com.example.repository;

import java.util.Collection;
import java.util.List;

import com.example.entity.Board;

import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.data.mongodb.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
public interface BoardRepository extends MongoRepository<Board, Long>{
    
    // 정확하게 일치  findBy변수명
    // 작성자가 'a'인 사람의 목록 조회
    List<Board> findByTitle(String title);
    List<Board> findByWriter(String writer);
    // 조회수가 100인것 목록으로 조회
    List<Board> findByHit(long hit);

    // 크다 작다
    // 조회수가 200미만 인것 목록으로 조회
    List<Board> findByHitLessThan(long hit);
    // 조회수가 300이상 인것 목록으로 조회
    List<Board> findByHitGreaterThanEqual(long hit);

    // 여러개 포함, 
    // 글번호가 컬렉션에 담긴 1, 5, 7만 조회
    List<Board> findByNoIn(Collection<Long> nos);
    List<Board> findByNoNotIn(Collection<Long> nos);

    // 직접 구현
    // 컨트롤러에서 bRepository.getBoardTitle("제목")
    @Query(value =  "{'title' : ?0}") // 몽고DB 문법을 알아야함
    List<Board> getBoardTitle(String title);

    @Query(value =  "{'writer' : ?0}")
    List<Board> getBoardWriter(String writer);

    @Query(value =  "{'hit' : ?0}")
    List<Board> getBoardHit(long hit);

    @Query(value =  "{title : {$regex : ?0}}" )
    List<Board> getBoardTitleLike(String title);
    // ex) 컨트롤러에서 bRepository.getBoardTitleLike("가")
    // 제목에 "가" 내용이 포함된것 가져옴

    // 조회수가 n보다 작다 &lte, &gt, &gte
    @Query(value =  "{hit : {$lt : ?0}}" )
    List<Board> getBoardHitLt(long hit);

    // 제목과 장성자가 일치(AND)
    @Query(value =  "{title : ?0, writer : ?1}" )
    // @Query(value =  "{$and : [{title : ?0, writer : ?1}] }" )
    List<Board> getBoardTitleAndWriter(String title, String writer);

    // 제목과 작성자 둘중에 하나(OR)
    @Query(value =  "{$or : [{title : ?0, writer : ?1}] }"  )
    List<Board> getBoardTitleOrWriter(String title, String writer);

    // 전체 제목에 포함된것 중에서 개수
    @Query(value =  "{title : {$regex : ?0}}", count = true )
    long getBoardTitleLikeCount(String title);

    // 작성자가 정확하게 일치하는 목록
    @Query(value =  "{'writer' : ?0}", sort = "{_id:-1}")
    List<Board> getBoardWriterSort(String writer);
}

파일명 BoardController.java

package com.example.controller;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import com.example.entity.Board;
import com.example.repository.BoardRepository;
import com.example.service.SequenceService;

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.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.servlet.support.RequestContextUtils;

@Controller
@RequestMapping(value = "/board")
public class BoardController {

    // 서비스 => mybatis  => 설계 + 구현(SQL문)
    // 저장소 => jpa, hibernate => 설계 + 구현 
    @Autowired
    BoardRepository bRepository;
    
    @Autowired
    SequenceService sequenceService;

    @Autowired
    HttpSession httpSession;

    @GetMapping(value = "/selectlist")
    public String selectGET(Model model){
        List<Board> list = bRepository.findAll();
        model.addAttribute("list", list);

        return "board/selectlist";
    }
    
    @GetMapping(value = "/insert")
    public String insertGET(){
        return "board/insert";
    }

    @PostMapping(value = "/insert")
    public String insertPOST(
            Model model,
            @ModelAttribute Board board){
        System.out.println(board.toString());
        // "SEQ_BOARD4_NO"
        board.setNo( sequenceService.generatedSequence("SEQ_BOARD4_NO"));
        board.setRegdate(new Date());

        Board retBoard = bRepository.save(board);
        if(retBoard != null){
            model.addAttribute("msg","작성 완료");
            model.addAttribute("url","/board/selectlist");
            return "alert";
        }
        return "redirect:/board/insert";
    }

    // RedirectAttributes POST에서 GET으로 데이터를 전송
    @PostMapping(value = "/action")
    public String actionPOST(
        Model model,
        RedirectAttributes redirectAttributes,
        @RequestParam(name = "btn")String btn,
        @RequestParam(name = "rad")long no){

        try {
            System.out.println("누른버튼 : "+btn);
            System.out.println("체크한 라디오 : "+no);
            // int, long, char => if(btn == "1개 삭제")가능 (String은 불가능)
            // String  => if( btn.equals("1개 삭제")) 가용해야함
            if( btn.equals("1개 삭제") ){
                bRepository.deleteById(no);
                model.addAttribute("msg","삭제되었습니다.");
                model.addAttribute("url","/board/selectlist");
                return "alert"; // 알림창 띄우고 url변경 자동화
            }
            else if(btn.equals("1개 수정") ){
                // httpSession.setAttribute("rad", no);
                // GET방식 url에 parameter로 붙임
                redirectAttributes.addAttribute("no", no);
                // POST방식 1번만 전송 새로고침시 데이터는 소멸
                // 세션에 추가하는 방식
                redirectAttributes.addFlashAttribute("no1", no);

                return "redirect:/board/update";
                // bRepository.save를 이용 단, _id가 조건으로 됨.
            }
            return "redirect:/board/selectlist";
        } catch (Exception e) {
            e.printStackTrace();
            return "redirect:/home";
        }
    }

    @GetMapping(value = "/update")
    public String updateGET(
        Model model,
        HttpServletRequest request,
        @RequestParam(name = "no")long no ) {
            //long no = (long)httpSession.getAttribute("rad");
    
            // Optional<Board> obj = bRepository.findById(no);
            // Board board = obj.get();
            // model.addAttribute("board", board);
            
        System.out.println("no : "+no);
        Map< String, ? > map = RequestContextUtils.getInputFlashMap(request);
        if(map != null){
            long no1 = (long)map.get("no1");
            System.out.println("no1 : "+ no1);
        }

        Board board = bRepository.findById(no).orElse(null);
        model.addAttribute("board", board);
        return "board/update";
    }

    @PostMapping(value = "/update")
    public String updatePOST(
        Model model,
        @ModelAttribute Board board
        // @RequestParam(name = "no")long no,
        // @RequestParam(name = "title")String title,
        // @RequestParam(name = "content")String content
    ){  
        try{      
            // Board board = new Board();
            // board.setNo(no);
            // board.setTitle(title);
            // board.setContent(content);
            
            // 추가 => 기본키를 다르게 해서 저장
            // 수정 => 기본키에 해당하는 글번호를 동일하게 새로저장
            
            // 기존내용을 읽음
            Board board1 = bRepository.findById(board.getNo()).orElse(null);
            
            // 변경할 항목만 board1에 다시 저장
            board1.setTitle(board.getTitle());
            board1.setContent(board.getContent());
            board1.setWriter(board.getWriter());
            
            // 최종적으로 board1의 값을 저장
            bRepository.save(board1);
            
            model.addAttribute("msg","수정되었습니다.");
            model.addAttribute("url","/board/selectlist");
            return "alert"; // 알림창 띄우고 url변경 자동화
        }
        catch(Exception e){
            e.printStackTrace();
            return "redirect:/home";
        }        
    }

    // 127.0.0.1:8080/board/selectfind
    @GetMapping(value = "/selectfind")
    public String selectfindGET(Model model,
            @RequestParam(name = "type", defaultValue = "", required = false )String type,
            @RequestParam(name = "text", defaultValue = "", required = false )String text,

            @RequestParam(name = "type1", defaultValue = "0", required = false )String type1,
            @RequestParam(name = "hit", defaultValue = "0", required = false )long hit1,

            @RequestParam(name = "type2", defaultValue = "0", required = false )String type2,
            @RequestParam(name = "no", defaultValue = "0", required = false )List<Long> no
        ) {

        List<Board> list = null;
        // 1. 정확하게 일치하는 항목 가져오기
        if(type.equals("title")){
            // list = bRepository.findByTitle(text);
            list = bRepository.getBoardTitle(text);
        }

        else if(type.equals("writer")){
            // list = bRepository.findByWriter(text);
            list = bRepository.getBoardWriter(text);
        }

        else if(type.equals("hit")){
            long hit = 0L;
            try{
                // 문자로 되어 있는 숫자를 숫자형으로변경
                // "1234" => 1234
                // ""     => X
                hit = Long.parseLong(text);
            }
            catch(Exception e){
                hit = 0L;
            }
            // list = bRepository.findByHit( hit );
            list = bRepository.getBoardHit( hit );
        }

        if(text.length() == 0 ){
            list = bRepository.findAll();
        }
        
        // 2. 조회수가 이상, 미만 조회하기
        if(type1.equals("1")){ // 이상           
            list = bRepository.findByHitGreaterThanEqual(hit1);
        }

        else if(type1.equals("2")){ // 미만            
            list = bRepository.findByHitLessThan(hit1);
        }

        // 3. 포함, 포함하지 않음
        if(type2.equals("1")){ //포함
            list = bRepository.findByNoIn(no);
        }

        else if(type2.equals("2")) { //포함X
            list = bRepository.findByNoNotIn(no);
        }
        
        model.addAttribute("list", list);
        return "board/selectfind";
    }
}

파일명 selectlist.jsp

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시판</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script type="text/javascript" src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div style="padding: 20px;">
        <h3>board list</h3>
        <hr />

        <a th:href="@{/board/insert}" >글쓰기</a>
        <form th:action="@{/board/action}" method="post">
            <input type="submit" name="btn" value="1개 삭제" class="btn btn-primary"/>
            <input type="submit" name="btn" value="1개 수정" class="btn btn-primary"/>
            <hr />
            <table class="table table-striped">
                <tr>             
                    <th>radio</th>   
                    <th>글번호</th>
                    <th>제목</th>                
                    <th>작성자</th>
                    <th>조회수</th>
                    <th>작성일</th>
                </tr>

                <tr th:each="tmp, idx : ${list}">
                    <td><input type="radio" name="rad" th:value="${tmp.no}" /></td>
                    <td th:text="${tmp.no}"></td>
                    <td th:text="${tmp.title}"></td>
                    <td th:text="${tmp.writer}"></td>
                    <td th:text="${tmp.hit}"></td>
                    <td th:text="${tmp.regdate}"></td>                
                </tr>
            </table>
        </form>
    </div>    
</body>
</html>

파일명 selectfind.jsp

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시판</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script type="text/javascript" src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div style="padding: 20px;">
        <h3>board find</h3>
        <hr />
        <h5>1. 정확하게 일치하는 항목 가져오기</h5>
        <form th:action="@{/board/selectfind}" method="get">
            <select name="type" >
                <option value="title">제목</option>
                <option value="writer">작성자</option>
                <option value="hit">조회수</option>
            </select>
            <input type="text" name="text" placeholder="검색어" />
            <input type="submit" value="검색" />
        </form>
        <hr />

        <h5>2. 조회수가 이상, 미만 조회하기</h5>
        <form th:action="@{/board/selectfind}" method="get">
            <select name="type1" >
                <option value="1">이상</option>
                <option value="2">미만</option>                
            </select>
            <input type="text" name="hit" placeholder="검색어" />
            <input type="submit" value="검색" />
        </form>
        <hr />
        
        <h5>3. 포함, 포함하지 않음</h5>
        <form th:action="@{/board/selectfind}" method="get">
            <select name="type2">
                <option value="1">포함</option>
                <option value="2">포함하지않음</option>
            </select>
            <input type="number" name="no" placeholder="글번호1" />
            <input type="number" name="no" placeholder="글번호2" />
            <input type="number" name="no" placeholder="글번호3" />
            <input type="submit" value="검색" />
        </form>
        <hr />        

        <table class="table table-sm">
            <tr>                             
                <th>글번호</th>
                <th>제목</th>                
                <th>작성자</th>
                <th>조회수</th>
                <th>작성일</th>
            </tr>

            <tr th:each="tmp, idx : ${list}">                
                <td th:text="${tmp.no}"></td>
                <td th:text="${tmp.title}"></td>
                <td th:text="${tmp.writer}"></td>
                <td th:text="${tmp.hit}"></td>
                <td th:text="${tmp.regdate}"></td>                
            </tr>
        </table>
    
    </div>    
</body>
</html>

파일명 update.jsp

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>게시판 수정</title>
    <link rel="stylesheet" type="text/css" th:href="@{/css/bootstrap.css}"/>
    <script type="text/javascript" src="@{/js/bootstrap.min.js}"></script>
</head>
<body>
    <div style="padding: 20px;">

        <h3>board update</h3>
        <hr />

        <form th:action="@{/board/update}" method="post">
                        
            <input type="hidden" th:value="${board.no}" name="no" readonly/>

            <label style="width:95px; height: 30px; display:inline-block;">제목 : </label>
            <input type="text" th:value="${board.title}" name="title"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">내용 : </label>
            <input type="text" th:value="${board.content}" name="content"/></br>

            <label style="width:95px; height: 30px; display:inline-block;">작성자 : </label>
            <input type="text" th:value="${board.writer}" name="writer"/></br>
            
            <label style="width:95px; height: 30px; display:inline-block;"></label>        
            <input type="submit" class="btn btn-primary" value="수정하기" />
            <a th:href="@{/board/selectlist}" class="btn btn-primary">글목록</a>
        </form>
        
    </div>    
</body>
</html>
profile
당신을 한 줄로 소개해보세요

0개의 댓글