์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

STEP 02 - ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ํ•˜๊ธฐ

๋ฏธ๋กœ910 2024. 10. 11. 11:25
๐Ÿ’ก
JPA๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ํ•™์Šตํ•ฉ๋‹ˆ๋‹ค

 

boardController - ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ํ•˜๊ธฐ ํ™”๋ฉด ์š”์ฒญ
    // ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ํ™”๋ฉด ์š”์ฒญ
    // board/id/update
    @GetMapping("/board/{id}/update-form")
    public String updateForm(@PathVariable(name = "id") Integer id, HttpServletRequest request) {
        // 1. ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ
        Board board = boardNativeRepository.findById(id);
        // 2. ์š”์ฒญ ์†์„ฑ์— ์กฐํšŒํ•œ ๊ฒŒ์‹œ๊ธ€ ์†์„ฑ ๋ฐ ๊ฐ’ ์ถ”๊ฐ€
        request.setAttribute("board", board);
        // ๋ทฐ ๋ฆฌ์กธ๋ธŒ - ํ…œํ”Œ๋ฆฟ ๋ฐ˜ํ™˜ 
        return "board/update-form"; // src/main/resources/templates/board/update-form.mustache
    }

 

board/update-form.mustache
{{> layout/header}}

<main class="container p-5 content">
    <article>
        <div class="card">
            <div class="card-header"><b>๊ธ€์ˆ˜์ •ํ™”๋ฉด ์ž…๋‹ˆ๋‹ค</b></div>
            <div class="card-body">
                <form action="/board/{{board.id}}/update" method="post">
                    <!--์ž‘์„ฑ์ž ์ด๋ฆ„-->
                    <div class="mb-3">
                        <input type="text" class="form-control" placeholder="enter username" name="username" value="{{board.user.username}}" readonly >
                    </div>

                    <!--์ œ๋ชฉ ์ž…๋ ฅ -->
                    <div class="mb-3">
                        <input type="text" class="form-control" placeholder="enter title" name="title" value="{{board.title}}"  required>
                    </div>

                    <!--๋‚ด์šฉ ์ž…๋ ฅ -->
                    <div class="mb-3">
                        <textarea class="form-control" rows="5" name="content" required>{{{board.content}}}</textarea>
                    </div>

                    <button class="btn btn-primary form-controller">๊ธ€ ์ˆ˜์ •ํ•˜๊ธฐ</button>
                </form>

            </div>
        </div>
    </article>

</main>

{{> layout/footer}}

 

Board.UpdateDTO ๋งŒ๋“ค๊ธฐ
package com.tenco.blog_v1.board;

import com.tenco.blog_v1.user.User;
import lombok.Data;

public class BoardDTO {

    @Data
    public static class SaveDTO {
        private String title;
        private String content;

        public Board toEntity(User user) {
            return Board.builder()
                    .title(title)
                    .content(content)
                    .user(user)
                    .build();
        }

    }

    @Data
    public static class UpdateDTO {
        private String username;
        private String title;
        private String content;
    }

}

 

BoardController
 // ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ์š”์ฒญ ๊ธฐ๋Šฅ
  // board/{id}/update
  @PostMapping("/board/{id}/update")
  public String update(@PathVariable(name = "id") Integer id, @ModelAttribute BoardDTO.UpdateDTO reqDto) {

      // 1. ๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ ๋ฐฉ์‹ ์ˆ˜์ •

      // 2. ์ธ์ฆ ๊ฒ€์‚ฌ - ๋กœ๊ทธ์€ ์—ฌ๋ถ€ ํŒ๋‹จ
      User sessionUser = (User) session.getAttribute("sessionUser");
      if(sessionUser == null) {
          return "redirect:/login-form";
      }
      // 3. ๊ถŒํ•œ ์ฒดํฌ - ๋‚ด ๊ธ€์ด ๋งž๋‹ˆ?
      Board board = boardRepository.findById(id);
      if(board == null) {
          return "redirect:/";  // ๊ฒŒ์‹œ๊ธ€์ด ์—†๋‹ค๋ฉด ์—๋Ÿฌ ํŽ˜์ด์ง€ ์ถ”ํ›„ ์ˆ˜์ •
      }
      if (!board.getUser().getId().equals(sessionUser.getId())) {
          return "redirect:/error-403"; // ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค. ์ถ”ํ›„ ์ˆ˜์ •
      }
      // 4. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ - ์ƒ๋žต

      // 5. ์„œ๋น„์Šค ์ธก ์œ„์ž„ (์ง์ ‘ ๊ตฌํ˜„) - ๋ ˆํŒŒ์ง€ํ† ๋ฆฌ ์‚ฌ์šฉ
      boardRepository.updateByIdJPA(id, reqDto.getTitle(), reqDto.getContent());

      // 6. ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ ์ฒ˜๋ฆฌ

      return "redirect:/board/" + id;
  }

 

BoardRepository ์ฝ”๋“œ ์ถ”๊ฐ€
@RequiredArgsConstructor
@Repository // IoC
public class BoardRepository  {

    private final EntityManager em;

    // ๋‘๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ์—ฐ์Šต - JQPL ์‚ฌ์šฉ, JPA API
    @Transactional
    public void updateByIdJPQL(int id, String title, String content) {
        // JPQL ์ฟผ๋ฆฌ ์ž‘์„ฑ
        String jpql = " UPDATE Board b SET b.title = :title, b.content = :content WHERE b.id = :id ";
        Query query = em.createQuery(jpql);
        query.setParameter("title", title);
        query.setParameter("content", content);
        query.setParameter("id", id);
        query.executeUpdate();
    }

    @Transactional
    public void updateByIdJPA(int id, String title, String content) {
        Board board = em.find(Board.class, id);
        if(board != null) {
            board.setTitle(title);
            board.setContent(content);
        }
        // flush ๋ช…๋ น, commit ๋ช…๋ น ํ•  ํ•„์š” ์—†์ด
        // ํŠธ๋žœ์žญ์…˜์„ ์„ ์–ธํ•˜๋ฉด ---> ๋”ํ‹ฐ ์ฒดํ‚น
    }
  • JPQL Update Query์™€ JPA API๋ฅผ ํ†ตํ•œ ์—”ํ‹ฐํ‹ฐ ์ˆ˜์ •์€ ๊ฐ๊ฐ์˜ ์žฅ๋‹จ์ ์ด ์žˆ์œผ๋ฏ€๋กœ, ์‚ฌ์šฉ ์ƒํ™ฉ์— ๋งž๊ฒŒ ์„ ํƒํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.
  • ๋‹จ์ผ ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š” JPA API ๋ฐฉ๋ฒ•์ด ๋” ์ ํ•ฉํ•˜๋ฉฐ, ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ˆ˜์ •์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋Š” JPQL Update Query๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํšจ์œจ์ ์ž…๋‹ˆ๋‹ค.
  • ์˜์†์„ฑ ์ปจํ…์ŠคํŠธ์™€ ํŠธ๋žœ์žญ์…˜ ๊ด€๋ฆฌ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ค์ •ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ์„ ์œ ์ง€ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.