스프링 부트와 JPA 활용1 - 웹 계층 개발 4

JOY·2022년 5월 12일
0
post-thumbnail

📌 스프링 부트와 JPA 활용1 - 웹 계층 개발 4

인프런 - 스프링 부트와 JPA 활용1 by 김영한 을 기반으로 작성된 글입니다.
실전! 스프링 부트와 JPA 활용1 - 웹 애플리케이션 개발


웹 계층 개발 목차

1. 홈 화면과 레이아웃

2. 회원 등록

3. 회원 목록 조회

4. 상품 등록

5. 상품 목록

6. 상품 수정

7. 변경 감지와 병합(merge)

8. 상품 주문

9. 주문 목록 검색, 취소


구현 기능

  • 홈 화면
  • 회원 기능
    • 회원 등록
    • 회원 조회
  • 상품 기능
    • 상품 등록
    • 상품 수정
    • 상품 조회
  • 주문 기능
    • 상품 주문
    • 주문내역 조회
    • 주문 취소

상품 기능

상품은 책으로 한정

상품 등록 폼 (BookForm.java)

package jpabook.jpashop.controller;

import lombok.Getter;
import lombok.Setter;

@Getter @Setter
public class BookForm {
    private Long id;

    //상품 공통 속성
    private String name;
    private int price;
    private int stockQuantity;

    //책 관련 속성
    private String author;
    private String isbn;
}

상품 등록 컨트롤러(ItemController.java)

package jpabook.jpashop.controller;

import jpabook.jpashop.domain.item.Book;
import jpabook.jpashop.service.ItemService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
@RequiredArgsConstructor
public class ItemController {

    private final ItemService itemService;

    @GetMapping("/items/new")
    public String createForm(Model model){
        model.addAttribute("form", new BookForm());

        return "items/createItemForm";
    }

    @PostMapping("/items/new")
    public String create(BookForm form){
        Book book = new Book();
        book.setName(form.getName());
        book.setPrice(form.getPrice());
        book.setStockQuantity(form.getStockQuantity());
        book.setAuthor(form.getAuthor());
        book.setIsbn(form.getIsbn());

        itemService.saveItem(book);
        return "redirect:/";
    }
}

상품 등록 뷰 (createItemForm.html)

코드는 일부만 나타내도록 하겠다

(생략)
 <form th:action="@{/items/new}" th:object="${form}" method="post">
        <div class="form-group">
            <label th:for="name">상품명</label>
            <input type="text" th:field="*{name}" class="form-control"
                   placeholder="이름을 입력하세요">
        </div>
(생략)

📍 실행 결과

submit insert 확인

👉단일 테이블 전략 사용
테이블 하나만 사용, 데이터가 저장 되었는지 구분하기 위해 간단한 데이터만 저장하였다




🔎 개인적으로 데이터 검증을 하기 위해
@Vaild, BindingResult 코드를 추가 해보았다

ItemController.java

public String create(@Valid BookForm form, BindingResult result){
        
        if(result.hasErrors()){
            return "items/createItemForm";
        }

createItemForm.html

<input type="text" th:field="*{name}" class="form-control"
                   placeholder="이름을 입력하세요"
                   th:class="${#fields.hasErrors('name')}? 'form-control
                                            fieldError' : 'form-control'">

에러 발생시 나타낼 스타일을 추가하고 (fieldError) 상품명, 가격, 수량에만 th:class 를 사용하였다

BookForm.java

//상품 공통 속성
    @NotEmpty(message = "책 이름을 입력해주세요")
    private String name;

    @NotEmpty(message = "책 가격을 입력해주세요")
    private int price;

    @NotEmpty(message = "책 수량을 등록해주세요")
    private int stockQuantity;

📍 설명
상품명, 가격, 수량에 @NotEmpty 을 적용하였다


모든 코드를 작성하고 실행해보니 에러가 발생하였다

❗ 에러 1

javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint 'javax.validation.constraints.NotEmpty' validating type 'java.lang.Integer'. Check configuration for 'stockQuantity'

💡 원인
@NotEmptyString 타입에서 사용하는 어노테이션이기 때문에
오류가 난 것이었다. size와 length를 검사할 수 있는 타입이 들어간다고 한다.

가격과 수량은 Integer 타입이므로 @NotNull을 사용해준다.
추가적으로 @NotBlank 도 String 타입만 사용할 수 있다.

💡 해결
BookForm.java 코드 수정

	//상품 공통 속성
    @NotEmpty(message = "상품명을 입력해주세요")
    private String name;

    @NotNull(message = "책 가격을 1원 이상 입력해주세요")
    @Min(value = 1, message = "책 가격을 1원 이상 입력해주세요")
    private int price;

    @NotNull(message = "책 수량을 1권 이상 입력해주세요")
    @Min(value = 1, message = "책 수량을 1권 이상 입력해주세요")
    private int stockQuantity;

❗ 에러 2

java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'form' available as request attribute

💡 원인

내가 전체적으로 코드를 추가하기 전까지는
에러가 나지 않던 코드가 에러가 나서 애를 먹었다.
form 키 값이 오타가 났나 찾아보았더니 정상적으로 써있어서 머리를 싸맸다
내가 무엇을 잘못 입력했고 해결방법은 무엇일까..?

💡 해결
ItemController.java 코드 수정

아래처럼 @ModelAttribute("form") 코드를 추가해 수정해주었다

public String create(@ModelAttribute("form") @Valid BookForm form, BindingResult result){}
제대로 데이터를 입력해서 submit 해보자

insert 성공

상품 목록 페이지는 다음 시간에 만들어보자.
일단 급한 불을 꺼두고 더 자세히 공부해 봐야겠다😅

profile
Just Do IT ------- 🏃‍♀️

0개의 댓글