BackEnd/spring

BeanValidation-Form 전송 객체 분리

연향동큰손 2024. 8. 5. 21:02

검증시 등록할때의 객체와 수정할때의 객체가 다르면 groups를 이용하여 데이터를 검증하기가 어려워진다.

 

간단한 프로젝트를 통해 이해할 수 있었다.

 

프로젝트 요구사항

Item 등록시 

1) 상품이름 = NULL(X)

2) 가격 = 1000이상, 1000000이하, NULL(X)

3) 상품 수량 = 최대 9999

 

Item 수정시

1) 상품id = NULL(X)

2) 상품이름 = NULL(X)

3) 가격 = 1000이상, 1000000이하, NULL(X)

4) 상품수량 = 수정할때는 수량의 제한이 없음

 

 

이러한 제한사항을 구현하기 위해 Form 전송 객체를 분리 하였다.

 

<ItemSaveForm> - 상품 등록 시 사용

package hello.itemservice.web.validation.form;

import lombok.Data;
import org.hibernate.validator.constraints.Range;

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

@Data
public class ItemSaveForm {

    @NotBlank
    private String itemName;

    @NotNull
    @Range(min=1000,max=1000000)
    private Integer price;

    @NotNull
    @Max(value=9999)
    private Integer quantity;
}

 

<ItemUpdateForm> - 상품 수정 시 사용

package hello.itemservice.web.validation.form;

import lombok.Data;
import org.hibernate.validator.constraints.Range;

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

@Data
public class ItemUpdateForm {

    @NotNull
    private Long id;

    @NotBlank
    private String itemName;

    @NotNull
    @Range(min=1000,max=1000000)
    private Integer price;

    //수정에서는 수량을 자유롭게 변경할 수 있다.
    private Integer quantity;
}

 

 

컨트롤러 수정

@PostMapping("/add")
public String addItem(@Validated @ModelAttribute("item") ItemSaveForm form, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
    //특정 필드 예외가 아닌 전체 예외
    if (form.getPrice() != null && form.getQuantity() != null) {
        int resultPrice = form.getPrice() * form.getQuantity();
        if (resultPrice < 10000) {
            bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
        }
    }

    if (bindingResult.hasErrors()) {
        log.info("errors={}", bindingResult);
        return "validation/v4/addForm";
    }

    //성공 로직
    Item item = new Item();
    item.setItemName(form.getItemName());
    item.setPrice(form.getPrice());
    item.setQuantity(form.getQuantity());

    Item savedItem = itemRepository.save(item);
    redirectAttributes.addAttribute("itemId", savedItem.getId());
    redirectAttributes.addAttribute("status", true);
    return "redirect:/validation/v4/items/{itemId}";
}

 

Item 대신 ItemSaveForm을 전달 받았고, @Validated로 검증도 수행하고, BindingResult로 검증 결과도 받았다.

 

★ 주의 : @ModelAttribute("item")으로 바꿔줘야한다. 이유는 이름을 수정해주지 않으면 @ModelAttribute의 규칙에 따라 "itemSaveForm"로 이름이 설정되어서 기존에 진행하고 있는 프로젝트와 일치하지 않게 된다.

 

@PostMapping("/{itemId}/edit")
 public String edit(@PathVariable Long itemId, @Validated @ModelAttribute("item") ItemUpdateForm form, BindingResult bindingResult) {
     //특정 필드 예외가 아닌 전체 예외
     if (form.getPrice() != null && form.getQuantity() != null) {
         int resultPrice = form.getPrice() * form.getQuantity();
         if (resultPrice < 10000) {
             bindingResult.reject("totalPriceMin", new Object[]{10000, resultPrice}, null);
         }
     }
     if (bindingResult.hasErrors()) {
         log.info("errors={}", bindingResult);
         return "validation/v4/editForm";
     }

     Item itemParam = new Item();
     itemParam.setItemName(form.getItemName());
     itemParam.setPrice(form.getPrice());
     itemParam.setQuantity(form.getQuantity());

     itemRepository.update(itemId, itemParam);
     return "redirect:/validation/v4/items/{itemId}";
 }

 

 

 

이러한 방식을 사용할 경우 Form객체를 Item객체로 꼭 변환시켜 줘야 한다.

'BackEnd > spring' 카테고리의 다른 글

SpringBean  (1) 2025.02.11
회원가입 로그인 구현  (0) 2024.08.19
Bean Validation  (0) 2024.08.01
Validator 분리  (1) 2024.07.31
검증 - 개선  (1) 2024.07.26