본문으로 바로가기

FAQ 게시판 CRUD 구현

category My Project 2024. 10. 22. 10:32

MyBatis의 매퍼 XML

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
        namespace="com.damoa.repository.interfaces.FaqRepository">

    <select id="getAllQna" resultType="com.damoa.repository.model.Faq">
        select * from faq_tb
    </select>

    <select id="findById" resultType="com.damoa.repository.model.Faq">
        select * from faq_tb where id = #{id};
    </select>

    <update id="updateById" >
            UPDATE faq_tb SET title = #{title}, content = #{content} WHERE id = #{id}
    </update>

    <insert id="insert">
             INSERT INTO faq_tb (type, title, content, created_at)
              VALUES (#{type}, #{title}, #{content}, now())
    </insert>

    <delete id="delete">
        delete from faq_tb where id = #{id}
    </delete>

</mapper>

 

 

XML 바탕으로 FaqRepository 구현

 

package com.damoa.repository.interfaces;

import com.damoa.dto.admin.FaqUpdateDTO;
import com.damoa.repository.model.Faq;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.List;

@Mapper
public interface FaqRepository {

    public List<Faq> getAllQna();
    public Faq findById(int id);
    public int updateById(FaqUpdateDTO updateDTO);
    public int insert(Faq faq);
    public int delete(int id);
}

 

 

FaqRepository 기반 FaqService 구현

 

package com.damoa.service;

import com.damoa.dto.admin.FaqSaveDTO;
import com.damoa.dto.admin.FaqUpdateDTO;
import com.damoa.repository.interfaces.FaqRepository;
import com.damoa.repository.model.Faq;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class FaqService {

    @Autowired
    public FaqRepository faqRepository;

    public List<Faq> getAllQna(){
        return faqRepository.getAllQna();
    }

    public Faq getFaqById(int id){
        return faqRepository.findById(id);
    }

    public int updateById(FaqUpdateDTO updateDTO){
        return  faqRepository.updateById(updateDTO);
    }

    public int createFaq(FaqSaveDTO dto){
        return faqRepository.insert(dto.toFaq());
    }

    public int delete(int id){
        return faqRepository.delete(id);
    }



}

 

FaqService 기반 FaqController 구현

 

package com.damoa.controller;

import com.damoa.dto.admin.FaqSaveDTO;
import com.damoa.dto.admin.FaqUpdateDTO;
import com.damoa.repository.model.Faq;
import com.damoa.service.FaqService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Controller
@RequestMapping("/faq")
public class FaqController {

    @Autowired
    public FaqService faqService;


    @GetMapping("/list")
    public String qnaListPage(Model model) {
        List<Faq> faqList = faqService.getAllQna();
        model.addAttribute("faqList", faqList);
        return "admin/admin_faq_list";

    }

    @GetMapping("/detail/{id}")
    public String detailPage(@PathVariable int id, Model model) {
        Faq faq = faqService.getFaqById(id);
        model.addAttribute("faq", faq);
        return "admin/admin_faq_detail";
    }

    @GetMapping("/update/{id}")
    public String updatePage(@PathVariable("id") int id, Model model) {
        Faq faq = faqService.getFaqById(id);
        System.out.println(faq);
        model.addAttribute("faq", faq);
        return "admin/admin_faq_update";
    }

    @PostMapping("/update/{id}")
    public String updatePage(@PathVariable int id, @RequestParam String title, @RequestParam String content) {
        FaqUpdateDTO updateDTO = new FaqUpdateDTO(id, title, content);
        faqService.updateById(updateDTO);
        return "redirect:/faq/list";
    }
    @GetMapping("/save")
    public String savePage(){

        return "admin/faq_save_form";

    }

    @PostMapping("/save")
    public String saveProc(@ModelAttribute("reqDTO") FaqSaveDTO reqDTO){
        faqService.createFaq(reqDTO);
        return "redirect:/faq/list";
    }

    @PostMapping("/delete/{id}")
    public String delete(@PathVariable int id){
        faqService.delete(id);
        return "redirect:/faq/list";
    }


}

 

 

위 컨트롤러 기반으로 mustache 뷰 구현

 

 

admin_faq_detail.mustache

{{>admin/admin_header}}

<div class="container mt-5">
    {{#faq}}
        <h4>{{title}}</h4>
        <p><strong>등록일:</strong> {{createdAt}}</p>
        <hr>
        <p>{{content}}</p>
        <button onclick="location.href='/faq/list'" class="btn btn-primary">목록으로 돌아가기</button>
        <button onclick="location.href='/faq/update/{{id}}'" class="btn btn-primary">수정</button>
        <form action="/faq/delete/{{id}}" method="post" style="display:inline;">
            <input type="hidden" name="id" value="{{id}}"> <!-- ID를 숨긴 필드로 전송 -->
            <button type="submit" class="btn btn-danger">삭제</button>
        </form>    {{/faq}}
</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

 

 

admin_faq_list.mustache

 

{{>admin/admin_header}}

<div class="container mt-5">
    <h2 class="mb-4">FAQ 목록</h2>
    <table class="table table-striped">
        <thead class="thead-dark">
        <tr>
            <th>번호</th>
            <th>제목</th>
            <th>등록일</th>
        </tr>
        </thead>
        <tbody>
        {{#faqList}}
            <tr>
                <td>{{id}}</td>
                <td>
                    <a href="/faq/detail/{{id}}">{{title}}</a>
                </td>
                <td>{{createdAt}}</td>
            </tr>
        {{/faqList}}
        {{^faqList}}
            <tr>
                <td colspan="5" class="text-center">등록된 FAQ가 없습니다.여기이</td>
            </tr>
        {{/faqList}}
        </tbody>
    </table>
    <a href="/faq/save" class="btn btn-primary">새 FAQ 등록</a>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>

 

 

admin_faq_update.mustache

{{>admin/admin_header}}

<div class="container mt-5">
    {{#faq}}
        <form action="/faq/update/{{id}}" method="post">
        <input type="hidden"  value="{{id}}" name="id">
        <input type="text" value="{{title}}" name="title" class="form-control" >
        <hr>
        <input type="text" value="{{content}}" name="content" class="form-control" >
            <button type="submit">수정하기</button>
        </form>

    {{/faq}}
</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

 

faq_save_form.mustache

 

{{>admin/admin_header}}
<div class="container mt-5">
    <h2>FAQ 등록</h2>
    <form action="/faq/save" method="post">
        <div class="form-group">
            <input type="hidden" name="type" id="type" value="1"> <!-- 기본값을 설정 -->
        </div>
        <div class="form-group">
            <label for="title">제목</label>
            <input type="text" name="title" id="title" class="form-control" placeholder="제목을 입력하세요" required>
        </div>
        <div class="form-group">
            <label for="content">내용</label>
            <textarea name="content" id="content" class="form-control" rows="4" placeholder="내용을 입력하세요" required></textarea>
        </div>
        <button type="submit" class="btn btn-primary">저장하기</button>
    </form>
</div>

<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
</body>
</html>