μ€λλ μ€μ μλ ννλ‘μ νΈλ₯Ό μ§ννμκ³ , λ¦μ μ€ν λΆν°λ ν λ°νλ₯Ό μ§ννμλ€. λ§‘μ λΆλΆμ λν μ½λλ₯Ό μ§λ©° κΈ°λ‘νμ¬ λ¨κΈ°λ©΄ μ’μ κ² κ°μ λΆλΆμ μμ±ν΄λ³Όλ €κ³ νλ€.
κΈ°μ‘΄μ @Valid μ΄λ
Έν
μ΄μ
κ³Ό BindingResult κ°μ²΄λ₯Ό μ¬μ©νμ¬ μμ²μ λν μμΈμ²λ¦¬λ₯Ό νμμ΅λλ€.
@Valid μ΄λ
Έν
μ΄μ
κ³Ό BindingResult μ¬μ©β‘ μμ² DTO ν΄λμ€
@Getter
@Setter
public class CreateRequest {
@NotBlank(message = "μν μ΄λ¦μ νμ μ
λλ€.")
private String productName;
@NotBlank(message = "μν κ°κ²©μ νμ μ
λλ€.")
private String price;
@NotBlank(message = "μν μ€λͺ
μ νμ μ
λλ€.")
private String content;
@NotNull(message = "μν κ°―μλ νμ μ
λλ€.")
private Integer count;
@NotNull(message = "μν μΉ΄ν
κ³ λ¦¬λ νμ μ
λλ€.")
private Category category;
}
①컨νΈλ‘€λ¬ λ¨
μλμ μ½λμ λν΄μ μ€λͺ
μ νμλ©΄ μμ±ν CreateRequest κ°μ²΄μ @Valid μ΄λ
Έν
μ΄μ
μ μμ±νμ¬, κ²μ¦μ ν μ μμ΅λλ€.
μμ±ν κ²μ¦ 쑰건μ λν΄ BindingResult λ©μλμ hasErrors() λ©μλλ₯Ό μ¬μ©νμ¬ μμΈ κ²μ¦μ ν μ μμΌλ©°, 400 μλ¬κ° λ°μν©λλ€.
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public RsData createProduct(@ModelAttribute @Valid CreateRequest createRequest,
@ModelAttribute(name = "images") MultipartFile images,
BindingResult bindingResult) throws IOException {
if (hasErrors(bindingResult)) {
return RsData.failOf(INVALID_PRODUCT_REQUEST);
}
productService.createProductWithImage(createRequest, images);
return RsData.of("S-1", POST_SUCCESS_PRODUCT, "create");
}
private boolean hasErrors(BindingResult bindingResult) {
return bindingResult.hasErrors();
}
μ μ²λΌ BindingResult κ°μ²΄λ₯Ό μ¬μ©νμ¬ μμΈ κ²μ¦μ ν μ μμ§λ§, μ λ λ§€κ°λ³μμ κ°―μκ° 3κ° μ΄μμΌλ‘ λμ΄ λ¦¬ν©ν λ§ ν νμμ±μ λλΌκ² λμμ΅λλ€.
β‘ μμΈμ²λ¦¬λ₯Ό 컀μ€ν
νμ¬ μ μμΌλ‘ κ΄λ¦¬νκΈ° μν @RestControllerAdvice μ μμΈλ₯Ό νΈλ€λ§ ν μ μλ @ExceptionHandler μ΄λ
Έν
μ΄μ
μ μ¬μ©νμ΅λλ€.
μΆκ°λ‘ @Valid μ΄λ
Έν
μ΄μ
μ μ¬μ©νμ¬ μμΈλ₯Ό ν°νΈλ¦¬λ©΄, MethodArgumentNotValidExceptionμ΄ λ°μνκ² λ©λλ€.
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final String INVALID_PRODUCT_REQUEST
= "μ ν¨νμ§ μμ μμ² μ
λλ€.";
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<String> handleInvalidRequest
(MethodArgumentNotValidException exception) {
String message = Optional
.ofNullable(
exception.getBindingResult().getFieldError())
.map(FieldError::getDefaultMessage)
.orElseThrow(()
-> new RuntimeException(INVALID_PRODUCT_REQUEST));
return new ResponseEntity<>(message, HttpStatus.BAD_REQUEST);
}
}
μ μ½λμ κ°μ΄ μ μμΌλ‘ μμΈλ₯Ό μ²λ¦¬ νκ² λλ©΄, 컨νΈλ‘€λ¬ λ¨μμ BindingResult κ°μ²΄λ₯Ό νλΌλ―Έν°λ‘ λκΈ°μ§ μμλ λκ² λ©λλ€.
β‘ BindingResult κ°μ²΄λ₯Ό λ§€κ°λ³μλ‘ μ¬μ©νμ§ μμ 컨νΈλ‘€λ¬ λ¨
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public RsData createProduct(@ModelAttribute @Valid CreateRequest createRequest,
@ModelAttribute(name = "images") MultipartFile images) throws IOException {
productService.createProductWithImage(createRequest, images);
return RsData.of("S-1", POST_SUCCESS_PRODUCT, "create");
}
ERD μ€κ³λ μμ κ°μ΄ νμκ³ , λ§λ‘ νμ΄μ μ€λͺ
νλ©΄OneToOne κ΄κ³OneToMany κ΄κ³OneToMany κ΄κ³λ‘ νμ μ‘μμ΅λλ€.