Mybatis 되돌아보기

kkikki·2024년 11월 17일

공부하기 좋게
메모할 수 있도록 직접 구현한 프로젝트 파해치며 정리

[수정부분으로 정리]

DB

Table: tbl_memo

Columns:
memonum int(8) AI PK
memoText varchar(150)
reg_date datetime

메모 엔터티

package com.test.mvc.entity;

import lombok.*;
import org.checkerframework.checker.units.qual.N;

import java.time.LocalDateTime;

@Getter@ToString
@EqualsAndHashCode
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Memo {
    private String memoNum;                 //index
    private String memoText;                // memo content
    private LocalDateTime regDate;      //register Date

}

컨트롤러

package com.test.mvc.controller;

import com.test.mvc.dto.MemoModifyDto;
import com.test.mvc.dto.MemoPostDto;
import com.test.mvc.entity.Memo;
import com.test.mvc.service.MemoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Controller
@RequestMapping("/")
@RequiredArgsConstructor
@Slf4j
public class MemoController {
    //서비스 통해 위임하여 조회나 기타등등
    private final MemoService memoService;

...

컨트롤러 수정 부분

 // ▽ put patch 동시 사용 방법.~!⭐️
    @RequestMapping(method = {RequestMethod.PUT, RequestMethod.PATCH})
    public ResponseEntity<?> modify(
           @Validated @RequestBody MemoModifyDto dto
            , BindingResult result      //검증 객체
    ) {

        log.info("/api/v1/replies : PUT, PATCH");       //PUT 타입으로 넘겨주면 받는다~!
        log.debug("parameter: {}", dto);

        //@Validated 건 곳에서 dto 들어가면   @NotNull @NotBlink 인지 검사
        if (result.hasErrors()) {
            Map<String, String> errors = makeValidationMessageMap(result);

            return ResponseEntity
                    .badRequest()
                    .body(errors);
        }



        List<Memo> mList = memoService.modify(dto);
        return ResponseEntity.ok().body(mList);
    }

MemoModifyDto

package com.test.mvc.dto;


import lombok.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

@Getter
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode
@Builder
public class MemoModifyDto {
    @NotNull
    private long mno;
    @NotNull
    private String newText;
}

프론트 부분 Jsp/ <script> 부분

else if (
              e.target.classList.contains(`edit-btn`) ||
              e.target.classList.contains(`fa-pencil-alt`) ||
              e.target.classList.contains(`fa-check`)
            ) {
              //# 수정
              // console.log("수정 클릭!!");

              if (
                e.target.classList.contains(`edit-btn`) ||
                e.target.classList.contains(`fas`)
              ) {
                const $card = e.target.closest(`.card`);

                const $cardFirstChild = $card.firstElementChild;
                console.log("card=>", $card);
                const $cardButtons = $card.children[2];
                console.log("cb=>", $cardButtons);
                const $editButton = $cardButtons.children[0];
                console.log($editButton);

                const $icon = $editButton.children[0];

                if ($icon.classList.contains("fa-pencil-alt")) {
                  //아이콘 변경
                  $icon.classList.remove("fa-pencil-alt");
                  $icon.classList.add("fa-check");
                  // 태그 변경
                  console.log($cardFirstChild);
                  var newSpan = document.createElement("textarea");
                  newSpan.classList.add("card-content");
                  newSpan.textContent = $cardFirstChild.textContent;
                  $cardFirstChild.parentNode.replaceChild(
                    newSpan,
                    $cardFirstChild
                  );
                } else if ($icon.classList.contains("fa-check")) {
                  console.log("저장 ㄱ");
                  $icon.classList.remove("fa-check");
                  $icon.classList.add("fa-pencil-alt");

                  //UI 업데이트
                  const $cardFirstChild2 = $card.firstElementChild;
                  var newSpan = document.createElement("div");
                  newSpan.classList.add("card-content");
                  newSpan.textContent = $cardFirstChild2.value;
                  console.log("바꿀내용:", $cardFirstChild2.value);
                  $cardFirstChild2.parentNode.replaceChild(
                    newSpan,
                    $cardFirstChild2
                  );

                  //db 처리를 위한 넘버 소환!
                  const mno = $card.dataset.mno;
                  console.log(mno);
                  const newText = $cardFirstChild2.value;
                  fetchModifyMemo(mno, newText);
                }

                // console.log('editList=>', $icon.classList);
                // const $editBtn = $cardButtons.closest(`.edit-btn`);
                // console.log('sss=>', $editBtn);
                // const content = $mno.firstElementChild.content;
                // console.log(e.target.classList);
                // console.log($card);
              }
            }
          });
        // });

frontEnd 부분 렌더링 부분 발췌 <body> 내용

</div>
      <div class="memo-total-List">
        <c:if test="${mList.size() > 0}">
          <c:forEach var="memo" items="${mList}">
            <div class="memo-wrapper">
              <section class="card" data-mno="${memo.memoNum}">
                <div class="card-content">${memo.memoText}</div>
                <div class="card-time">등록시간: ${memo.regDate}</div>

                <div class="card-buttons">
                  <button class="edit-btn">
                    <i class="fas fa-pencil-alt"></i>
                  </button>
                  <button class="delete-btn">
                    <i class="fas fa-trash-alt"></i>
                  </button>
                </div>
              </section>
            </div>
          </c:forEach>
        </c:if>
      </div>
      
```java

 //db 처리를 위한 넘버 소환!
                  const mno = $card.dataset.mno;
                  console.log(mno);
                  const newText = $cardFirstChild2.value;
                  fetchModifyMemo(mno, newText);
                  
// # 수정
        const fetchModifyMemo = async (mno, newText) => {
          const payload = {
            mno: mno,
            newText: newText,
          };
          console.log("payload", payload);
          console.log("url", url);
          const res = await fetch(url, {
            method: "PUT",
            headers: {
              "content-type": "application/json",
            },
            body: JSON.stringify(payload),
          });

          if (res.status === 403) {
            alert("로그인이 필요한 서비스입니다.");
            // window.location.href = '/members/sign-in';
            return;
          }
        };

찍힌 로그

저장 ㄱ
바꿀내용: 111222
82
payload {mno: '82', newText: '111222'}

MemoMapper.xml

<update id="modify">
        UPDATE tbl_memo
        SET memoText = #{newText}
        WHERE memonum = #{mno}
    </update>

실제 컬럼은 memoText 이기 때문에
#{}을 사용해서 값을 컬럼에 맞게 넣어줌

Columns:
memonum int(8) AI PK
memoText varchar(150)
reg_date datetime


profile
내 커리어 끝은 없다

0개의 댓글