이전 실습을 통해 JPA에서 Join을 사용하여 관계형 DB를 구현하는 법을 배웠었다. 그럼 이를 통해 구현할 수 있는 대표적인 기능인 댓글 기능을 구현해보도록 하겠다.
DB 구조
파일 구조
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Builder
public class Hospital {
@Id
private Integer id;
private String roadNameAddress;
private String hospitalName;
/*
JPA에서는 데이터를 조회할 때 즉시 로딩(EAGER)과 지연 로딩(LAZY) 두 가지 방식이 있다.
이 두 가지 방식을 간단하게 설명하면 즉시 로딩은 데이터를 조회할 때 연관된 데이터까지 한 번에 불러오는 것이고,
지연 로딩은 필요한 시점에 연관된 데이터를 불러오는 것이라고 할 수 있다.
가급적이면 기본적으로 지연 로딩을 사용하는 것이 좋다.
*/
@OneToMany(mappedBy = "hospital", fetch = FetchType.LAZY)
// 병원은 1개이고 리뷰는 여러개 달리므로 One = 병원, Many = 리뷰들
private List<Review> reviews;
}
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Getter
@Builder
public class Review {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
private String userName;
@ManyToOne // 리뷰입장에서는 리뷰가 여러개고 병원은 한개이므로
@JoinColumn(name = "hospital_id") // hospital_id의 행을 Hospital DB와 연결함
private Hospital hospital; // 즉, hospital_id가 FK가 됨
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Builder
// 리뷰를 생성할때 요청받는 데이터
public class ReviewRequest {
// private Integer hospitalId;
private String title;
private String content;
private String userName;
}
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Getter
// 리뷰를 생성할때 반환하는 데이터
public class ReviewResponse {
private Long id;
private String title;
private String content;
private String userName;
private String message;
}
@Repository
public interface HospitalRepository extends JpaRepository<Hospital,Integer> {
}
@Repository
public interface ReviewRepository extends JpaRepository<Review,Long> {
}
@Service
public class ReviewService {
private final ReviewRepository reviewRepository;
private final HospitalRepository hospitalRepository;
public ReviewService(ReviewRepository reviewRepository, HospitalRepository hospitalRepository) {
this.reviewRepository = reviewRepository;
this.hospitalRepository = hospitalRepository;
}
public ReviewResponse ReviewAdd(int id,ReviewRequest reviewRequest){
Optional<Hospital> hospital = hospitalRepository.findById(id); // 유저가 리뷰를 작성하고자 하는 게시물 번호를 가져와 해당 데이터를 호출함
Review review = Review.builder()
.title(reviewRequest.getTitle()) // 유저가 작성한 리뷰 데이터의 값(ReviewRequest)을 Review Entity에 저장함
.content(reviewRequest.getContent())
.userName(reviewRequest.getUserName())
.hospital(hospital.get()) //
.build();
Review savedReview = reviewRepository.save(review);
ReviewResponse reviewResponse = ReviewResponse.builder()
.id(savedReview.getId())
.title(savedReview.getTitle())
.content(savedReview.getContent())
.userName(savedReview.getUserName())
.message("리뷰가 추가되었습니다.")
.build();
return reviewResponse;
}
}
사용자가 작성한 리뷰를 저장하기 위해서는 해당 게시물의 번호(ID)와 내용(ReviewRequest)를 받아 Hospital DB에 ID에 대한 데이터를 가져와 Review Entity에 작성한 내용(ReviewRequest)과 Hospital 데이터를 저장해준다.
그 후 Review DB에 JPA의 save를 통해 저장한다.
해당 내용이 잘 저장되었는지 확인하기 위해 JSON형식으로 해당 데이터를 출력하기 위해 Response DTO에 데이터를 넘겨준다.
@RestController
@RequestMapping("/api/v1/hospital")
public class HospitalController {
private final ReviewService reviewService;
public HospitalController(ReviewService reviewService) {
this.reviewService = reviewService;
}
@PostMapping("/{id}/review")
public ResponseEntity<ReviewResponse> ReviewAdd(@PathVariable Integer id, @RequestBody ReviewRequest reviewRequest){
return ResponseEntity.ok().body(reviewService.ReviewAdd(id,reviewRequest));
}
}