본문 바로가기

Spring boot/Blog 프로젝트 만들기(JPA)

완성 코드 STEP 02 - 게시글 수정 ( JPA API , JPQL 쿼리 사용, 인증(세션 로직 추가 )

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를 사용하는 것이 효율적이다.
  • 영속성 컨텍스트와 트랜잭션 관리를 올바르게 설정하여 데이터 일관성을 유지하는 것이 중요하다.
728x90