PUT 메소드 실습

서지우·2023년 8월 1일
0

Spring Boot

목록 보기
8/18

PUT 메소드 실습

1. html(타임리프)

글번호와 input 수정버튼을 만들어준다.


update.html

html을 하나 만들어준다.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>지역 수정</h1>
    <div>
        <span>글번호 : </span>
        <span>2</span>
    </div>
    <div>
        <input type="text" value="원래지역이름">
        <button>수정</button>
    </div>
</body>
</html>

live서버를 켜서 확인해본다.

잘나오는군...


2. 수정페이지

@Controller에 view를 해서 화면이 연결되도록 하고, model 예를 들어 7번 region dto 만들어서 전달을 해서 쿼리스트링에 넣을 수 있도록 한다.
또한 service에서 controller에 넘길 수 있도록 만들어준다.

/main/update-page/7

(repository는 앞선 실습에서 쓴 것 그대로 쓴다.)

MainControllerApiV1.java

화면을 뿌릴 수 있게 만들어준다.

    @GetMapping("/main/update-page/{regionsId}")
    public ModelAndView updatePage(){
        ModelAndView modelAndView = new ModelAndView();
        // List<ResMainDTO> resMainDTOList =  mainService.updateMainData(regionsId);
        modelAndView.setViewName("main/update");
        return modelAndView;
    }

실행해서 localhost에 들어가서 쿼리스트링에 임시로 넣어주고 실행하면 되는 것을 볼 수 있다.


main.html

수정버튼을 클릭하면 수정페이지로 넘어갈 수 있게 버튼을 만들어준다.

          <span class="regionBtn" th:onclick="deleteRegion([[${dto.regionsId}]])">X</span>
          <span class="regionBtn">수정</span>

script를 통해 페이지이동 할 수 있도록 함수를 만들어준다.
(필요한 부분만 가져옴)

          <span class="regionBtn" th:onclick="goUpdatePage([[${dto.regionsId}]])">수정</span>
    <script>
      const goUpdatePage = (regionsId) => {
        location.href = "/main/update-page/" + regionsId;
      }

수정버튼을 클릭하면 값과 함께 수정페이지로 넘어가는 것을 볼 수 있다.


ReqUpdateMainDTO.java

페이지마다 각각 dto 만드는게 좋다!
요청하는 값들을 DTO로 만들어준다.

package com.example.hr1.domain.main.dto;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
public class ReqUpdateMainDTO {
    private Integer regionId;
    private String regionName;
}

ResUpdateMainDTO

요청받는 값들을 DTO로 만들어준다.

package com.example.hr1.domain.main.dto;

import com.example.hr1.model.regions.entity.RegionsEntity;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@NoArgsConstructor
@AllArgsConstructor
@Builder
@Getter
public class ResUpdateMainDTO {
    private Integer regionsId;
    private String regionName;

    public static ResUpdateMainDTO fromEntity(RegionsEntity regionsEntity){
        return ResUpdateMainDTO.builder()
        .regionsId(regionsEntity.getRegionId())
        .regionName(regionsEntity.getRegionName())
        .build();
    }
}

MainService.java

ResUpdateMainDTO의 formEntity해서 반환한다.

    public ResUpdateMainDTO getUpdateMainPageData(Integer regionsId){
        RegionsEntity regionsEntity = regionsReposiotory.findByRegionId(regionsId);

        return ResUpdateMainDTO.fromEntity(regionsEntity);
    }

MainController.java

화면을 뿌려주기 위해 Controller에 작성한다.

    @GetMapping("/main/update-page/{regionsId}")
    public ModelAndView updatePage(@PathVariable Integer regionsId){
        ModelAndView modelAndView = new ModelAndView();
        ResUpdateMainDTO resUpdateMainDTO =  mainService.getUpdateMainPageData(regionsId);
        modelAndView.addObject("resUpdateMainDTO", resUpdateMainDTO);
        modelAndView.setViewName("main/update");
        return modelAndView;
    }

실행해서 localhost로 들어가 수정버튼을 눌리면

해당 리스트 번호가 들어가고 지역이름이 텍스트 필드에에 입력되어 있는 것을 볼 수 있다.


2. 수정요청

@RestController를 사용한다.
(앞서 게시물에 정리해놓았다.)

첫번째 방식(추천)은 @PathVariable로 id, @RequestBody로 변경할 데이터를 받는 방법이다.

두번째 방식은 @RequestBody로 id하고 변경할 데이터 다받는 방법이다.

첫번째 방식으로 한다.

ReqUpdateMainDTO.java

ReqUpdateMainDTO를 변경해준다.

package com.example.hr1.domain.main.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@NoArgsConstructor
@AllArgsConstructor
@Getter
@ToString
public class ReqInsertMainDTO {
    private String regionsName;
}

MainControllerApiV1.java

데이터를 뿌려주기 위해 MainControllerApiV1에 만들어준다.

    @PutMapping("/api/v1/main/{regionsId}")
    public ResponseDTO<Object> updateMainData(@PathVariable Integer regionsId, @RequestBody ReqUpdateMainDTO reqUpdateMainDTO) {
        mainService.updateMainData(regionsId, reqUpdateMainDTO);
        return ResponseDTO.builder()
                .code(0)
                .message("region 수정에 성공했습니다.")
                .build();
    }

@PathVariable 어노테이션

http://127.0.0.1/users?userId={$userId}
http://127.0.0.1/users/{userId}

위에는 일반적인 GET 방식의 파라미터 전달이라 흔히 볼수 있었다.
아래는 케이스는 Rest Api호출시 주로 많이 사용하게 된다.
URI를 이용해 파라미터 처리를 할수있다는 뜻이다.

사용법

  1. @GetMapping path의 {변수} 괄호안에 괄호 그레이스를 열어 URI에 사용될 변수 명을 입력한다.
    GetMapping 뿐만 아니라 당연히 다른 Method도 가능하다. ( PostMapping, DeleteMapping, PutMapping......)
  2. @PathVariable 어노테이션을 이용해서 {템플릿 변수} 와 동일한 이름을 갖는 파라미터를 추가하면 된다.

MainService.java

@Transactional을 사용하여 만들어준다.
(@Transactional은 아래에 설명하겠음)

    @Transactional // 붙여주면 이 친구는 false가 되니까 
    public void updateMainData(Integer regionsId, ReqUpdateMainDTO reqUpdateMainDTO){
        // regionsId 받아서 넣어주기
        RegionsEntity regionsEntity = regionsReposiotory.findByRegionId(regionsId);

        // spring data jpa는 더티체킹을 사용한다
        // 데이터베이스에서 가져온 데이터(엔티티)가 변경이 되면
        // 자동으로 update쿼리를 날려줌

        // dto에서 바뀐 역 이름 받아서 넣어주기
        regionsEntity.setRegionName(reqUpdateMainDTO.getRegionName());
    }

@Transactional

스프링은 @Transactional 어노테이션을 이용한 선언적 트랜잭션 처리를 지원한다.

트랜잭션이란?

트랜잭션은 우리말로 ‘거래’라는 뜻을 갖고 있으므로, 먼저 거래와 관련된 간단한 예시를 들어보겠다.

예시
친구에게 500보냄

  • 트랜잭션 시작
  • 내 계좌에서 500원 감소

  • 정전 서버가 꺼짐
  • 트랜잭션 시작하기 전으로 되돌아감
    이걸 롤백이라 함

  • 친구 계좌에서 500원추가
  • 트랜잭션 완료

    완료 되면 커밋

DB와 관련된, 트랜잭션이 필요한 서비스 클래스 혹은 메서드에 @Transactional 어노테이션을 달아주면된다.

참고자료
꼭 읽어보길
트랜잭션 어노테이션에 대해
트랜잭션을 사용하면서 알아야 하는 점


3.포스트맨으로 테스트

실행해 POSTMAN에서 PUT방식으로 해서 5번을 목성으로 바꾸기 위해 send를 해준다.그랬더니 오류가 난다.

그래서 DB에 들어가서 봤더니 5번이 없어서 그랬다.

그래서 있는 번호중에 7번은 수정해보기로 했다send를 했더니 수정에 성공했다.


4. 자바스크립트로 제작 및 연결

스크립트를 만들어 연결한다.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <h1>지역 수정</h1>
    <div>
        <span>글번호 : </span>
        <span id="regionId" th:text="${resUpdateMainDTO.regionsId}"></span>
    </div>
    <div>
        <input id="regionName" type="text" th:value="${resUpdateMainDTO.regionName}">
        <!-- 방법2 -->
        <button th:onclick="updateRegion([[${resUpdateMainDTO.regionsId}]])">수정</button>
        <!-- 방법1 -->
        <!-- <button>수정</button> -->
    </div>
    <script>
        // 방법2
        const updateRegion = (regionsId) => {

            //방법1 (input에 있는 데이터 이 방식으로)
            // document.querySelector("#regionId").innerText;

            const regionName = document.querySelector("#regionName").value;

            const dto = {
                regionName: regionName
            }

            fetch("/api/v1/main/" + regionsId, {
                method: "PUT",
                body: JSON.stringify(dto),
                headers: {
                    "Content-Type" : "application/json"
                }
            })
            .then((response) => response.json())
            .then((result) => {
                alert(result.message);
                if (result.code == 0) {
                    location.href = "/";
                }
            });

        };

    </script>
</body>
</html>

실행해서 local로 들어가 수정을 해본다.


기본키를 자동으로 생성

자동증가
자동증가가 설정되어 있지 않아 해준다.(그림 따라 하면됨)


RegionsEntity.java

기본키를 자동으로 생성하도록 @Id와 @GeneratedValue를 붙여준다.

    // 기본키 (PK)에 @Id를 붙인다
    @Id
    // 데이터베이스에 있는 컬럼명을 연결
    // 컬럼의 속성을 맞춰주는 것이 좋다.
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "region_id", nullable = false, unique = true)
    private Integer regionId;

참고자료
@GeneratedValue 전략 -기본키를 자동으로 생성하는 방법 4가지


MainService.java

자동증가로 변경했기 때문에 count를 지워준다.

    @Transactional
    public void postMainData(ReqInsertMainDTO reqInsertMainDTO){

        // long count = regionsReposiotory.count();

        RegionsEntity regionsEntity = RegionsEntity.builder()
        // .regionId((int)count + 1)
        .regionName(reqInsertMainDTO.getRegionsName())
        .build();

        regionsReposiotory.save(regionsEntity);
    }

실행해서 입력하면 순서대로 잘 들어간다.


profile
미래가 기대되는 풀스택개발자 공부 이야기~~

0개의 댓글