Review Entity

@Entity
@NoArgsConstructor
@Getter
public class Review {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String content;

    @ManyToOne
    @JoinColumn(name = "item_id")
    private Item item;

    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    @Builder
    public Review(Long id, String content, Item item, Member member){
        this.id = id;
        this.content = content;
        this.item = item;
        this.member = member;
    }
}

리뷰엔티티에는 해당 아이템, 리뷰 작성자를 다대일 매핑하였다.

ReviewDto 작성

@Data
public class ReviewDto {

    private String content;
    private Item item;
    private Member member;

    public Review toEntity(){
        return Review.builder()
                .content(content)
                .item(item)
                .member(member)
                .build();
    }
}

ReviewRepository 작성

public interface ReviewRepository extends JpaRepository<Review, Long> {

    List<Review> findByItem_Id(Long id);
}

아이템의 리뷰 리스트를 받아오기위해 findByItem_Id를 작성했다.

ReviewService 작성

ReviewService

public interface ReviewService {
    List<Review> FindItemId(Long id);
    void create(ReviewDto reviewDto, Long id, Principal principal);
}

ReviewServiceImpl

@Service
@RequiredArgsConstructor
public class ReviewServiceImpl implements ReviewService {

    private final ReviewRepository reviewRepository;
    private final MemberRepository memberRepository;
    private final ItemRepository itemRepository;

    @Override
    public List<Review> FindItemId(Long id) {
        return reviewRepository.findByItem_Id(id);
    }

    @Override
    public void create(ReviewDto reviewDto, Long id, Principal principal) {
        Item item = itemRepository.findById(id).get();
        Member member = memberRepository.findByEmail(principal.getName());
        reviewDto.setMember(member);
        reviewDto.setItem(item);

        reviewRepository.save(reviewDto.toEntity());
    }
}

리뷰를 작성할때 create메서드를 이용하는데
각각 item Id와 Principal.getName()으로 member Email을 이용해서 아이템과 멤버 객체를 추가해준뒤 save한다.

ItemController 추가

    @GetMapping("/detail/{id}")
    public String item_detail(Model model, @PathVariable Long id){
        model.addAttribute("item", itemService.itemFindId(id));
        model.addAttribute("reviews", reviewService.FindItemId(id));

        return "item/detail";
    }

    @PostMapping("/review_reg/{id}")
    public String review_reg(@ModelAttribute ReviewDto reviewDto,
                             @PathVariable Long id,
                             Principal principal){

        reviewService.create(reviewDto, id, principal);

        return "redirect:/item/detail/"+id;
    }

detail.html 작성

<!DOCTYPE html>
<html lang="en" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
    <div th:replace="/fragments/header.html :: header"></div>
    <title>Title</title>
</head>
<body>
<div th:replace="/fragments/nav.html :: nav"></div>
<div class="container">
    <h1>상품 상세</h1>
    <div class="card mb-3">
        <div class="card-body">
            <h5 class="card-title" th:text="${item.name}"></h5>
            <h6 class="card-subtitle mb-2 text-muted" th:text="'가격: ' + ${item.price} +'원'"></h6>
            <p class="card-text" th:text="'판매자: '+${item.member.getName()}"></p>
            <pre class="card-footer" th:text="${item.content}"></pre>
        </div>
    </div>
    <form class="mb-2" th:action="@{/review_reg/{id}(id=${item.id})}" method="post" sec:authorize="isAuthenticated()">
        <div class="mb-3">
            <label for="content">리뷰 내용: </label>
            <textarea class="form-control" id="content" name="content" rows="3"></textarea>
        </div>
        <button type="submit" class="btn btn-primary">제출</button>
    </form>
    <div>
        <h3 class="mb-2">리뷰 목록</h3>
        <div class="card">
            <ul class="list-group list-group-flush">
                <li th:each="review : ${reviews}" class="list-group-item">
                    <div class="card-body mb-2">
                        <h5 class="card-title" th:text="${review.content}"></h5>
                        <p class="card-text">작성자: <span th:text="${review.member.getName()}"></span></p>
                    </div>
                </li>
            </ul>
        </div>
    </div>
</div>
</body>
</html>

리뷰작성칸은 로그인된 사용자에게만 보이도록했다.

Junyoung.dev