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>
리뷰작성칸은 로그인된 사용자에게만 보이도록했다.

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>
리뷰작성칸은 로그인된 사용자에게만 보이도록했다.
