2022.11.24 (목요일)

yeonicerely·2022년 11월 24일
0

SpringBoot DataJpa를 이용해서 병원 리뷰 조회 및 작성

1. 프로젝트 구조

  • ERD

  • Add

Entity

  • Hospital
import com.fasterxml.jackson.annotation.JsonBackReference;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.List;

@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Hospital {

    @Id
    private Long id;
    @Column(name = "hospital_name")
    private String name;
    private String roadNameAddress;

    @OneToMany(mappedBy = "hospital", fetch = FetchType.LAZY)
    @JsonBackReference // 직렬화 -> 상호 참조 제거
    private List<Review> review;

}
  • Review
@Entity
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class Review {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String content;
    private String patientName;

    @ManyToOne
    @JoinColumn(name = "hospital_id")
    @JsonManagedReference // 직렬화 -> 상호 참조 제거
    private Hospital hospital;

    public Review(String title, String content, String patientName, Hospital hospital){
        this.title = title;
        this.content = content;
        this.patientName = patientName;
        this.hospital = hospital;

    }

}

DTO

  • ResponseDto
import lombok.*;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class HospitalAddRequestDto {

// 병원의 아이디는 pathvariable에서 넘겨주고
// 리뷰의 제목, 내용, 작성자 이름만 작성할 수 있도록 함

    private String title;
    private String content;
    private String patientName;

}
  • ResponseDto
import com.likelion.springjpaexcercise.entity.Hospital;
import com.likelion.springjpaexcercise.entity.Review;
import com.likelion.springjpaexcercise.repository.HospitalRepository;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Optional;

@Getter
@NoArgsConstructor
@AllArgsConstructor
public class HospitalAddResponseDto {

// 리뷰 제목, 내용, 작성자 이름, 병원의 id를 view에서 볼 수 있도록 함
    private String title;
    private String content;
    private String patientName;
    private Long hospitalId;

		// request dto를 Review로 바꾸어주는 메소드
		// 이것을 DB에 저장하여 review 테이블을 업데이트
    public Review toEntity(Hospital hospital, HospitalAddRequestDto hospitalAddRequestDto){
        return new Review(hospitalAddRequestDto.getTitle(), hospitalAddRequestDto.getContent(), hospitalAddRequestDto.getPatientName(), hospital);
    }

}

Controller

import com.likelion.springjpaexcercise.entity.Hospital;
import com.likelion.springjpaexcercise.entity.Review;
import com.likelion.springjpaexcercise.entity.dto.HospitalAddRequestDto;
import com.likelion.springjpaexcercise.entity.dto.HospitalAddResponseDto;
import com.likelion.springjpaexcercise.repository.HospitalRepository;
import com.likelion.springjpaexcercise.repository.ReviewRepository;
import com.likelion.springjpaexcercise.service.HospitalService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/v1/hospitals")
public class HospitalController {

    private final HospitalService hospitalService;
    private final ReviewRepository reviewRepository;

    private final HospitalRepository hospitalRepository;

    public HospitalController(HospitalService hospitalService, ReviewRepository reviewRepository, HospitalRepository hospitalRepository) {
        this.hospitalService = hospitalService;
        this.reviewRepository = reviewRepository;
        this.hospitalRepository = hospitalRepository;
    }

		// 병원 아이디로 병원의 리뷰 조회
    @GetMapping("/{id}")
    public ResponseEntity<List<Review>> HospitalsReviewList(@PathVariable Long id){

        return ResponseEntity.ok().body(hospitalService.findHospitalReview(id));
    }

		// 리뷰의 아이디로 개별 리뷰 조회
		
    @GetMapping("/reviews/{id}")
    public ResponseEntity<Review> reviewListWithId(@PathVariable Long id){

        return ResponseEntity.ok().body(hospitalService.findReview(id));
    }

		// 전체 병원 리스트 조회
    @GetMapping("")
    public ResponseEntity<Page<Hospital>> list(Pageable pageable){

        return ResponseEntity.ok().body(hospitalService.hospitalList(pageable));
    }

		// id에 해당하는 병원의 리뷰 작성
    @PostMapping("/{id}/reviews")
    public ResponseEntity<HospitalAddResponseDto> addReview(@PathVariable Long id, @RequestBody HospitalAddRequestDto hospitalAddRequestDto){

        HospitalAddResponseDto hospitalAddResponseDto = hospitalService.addReview(hospitalAddRequestDto, id);

        return ResponseEntity.ok().body(hospitalAddResponseDto);

    }

}

Service

import com.likelion.springjpaexcercise.entity.Hospital;
import com.likelion.springjpaexcercise.entity.Review;
import com.likelion.springjpaexcercise.entity.dto.HospitalAddRequestDto;
import com.likelion.springjpaexcercise.entity.dto.HospitalAddResponseDto;
import com.likelion.springjpaexcercise.repository.HospitalRepository;
import com.likelion.springjpaexcercise.repository.ReviewRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class HospitalService {

    private final HospitalRepository hospitalRepository;
    private final ReviewRepository reviewRepository;

    public HospitalService(HospitalRepository hospitalRepository, ReviewRepository reviewRepository) {
        this.hospitalRepository = hospitalRepository;
        this.reviewRepository = reviewRepository;
    }

    public List<Review> findHospitalReview(Long id){

        Review review = new Review();

        Hospital findHospital = hospitalRepository.findById(id).get();

        List<Review> reviewList = findHospital.getReview();

        return reviewList;
    }

    public Review findReview(Long reviewId){
        Optional<Review> findedReview = reviewRepository.findById(reviewId);
        Review review = findedReview.get();

        return review;
    }

    public Page<Hospital> hospitalList(@PageableDefault(size=10, sort="id", direction = Sort.Direction.DESC)
    Pageable pageable){
        Page<Hospital> hospitalPage = hospitalRepository.findAll(pageable);

        return hospitalPage;
    }

    public HospitalAddResponseDto addReview(HospitalAddRequestDto requestDto, Long hospitalId){

		// pathVariable을 통해 넘겨받은 id ->병원을 조회해서 Review의 필드에 넘겨줌

        Optional<Hospital> hospitalOptional= hospitalRepository.findById(hospitalId);
        Hospital hospital = hospitalOptional.get();

        HospitalAddResponseDto hospitalAddResponseDto = new HospitalAddResponseDto(requestDto.getTitle(), requestDto.getContent(), requestDto.getPatientName(), hospitalId);

        Review review = hospitalAddResponseDto.toEntity(hospital, requestDto);
        reviewRepository.save(review);

        return hospitalAddResponseDto;
    }

}

3. 에러 해결

1. swagger ui를 붙일 때 발생하는 Failed to start bean 'documentationPluginsBootstrapper'

: https://velog.io/@quarara01/Swagger-ui%EB%A5%BC-%EB%B6%99%EC%9D%BC-%EB%95%8C-%EB%B0%9C%EC%83%9D%ED%95%98%EB%8A%94-Failed-to-start-bean-documentationPluginsBootstrapper

2. docker: Error response from daemon: pull access denied for 8080, repository does not exist or may require 'docker login'

: https://velog.io/@quarara01/docker-Error-response-from-daemon-pull-access-denied-for-8080-repository-does-not-exist-or-may-require-docker-login

3. @OneToMany, @ManyToOne 양방향 참조로 인한 stackover flow 에러

: https://velog.io/@quarara01/OneToMany-ManyToOne-%EC%96%91%EB%B0%A9%ED%96%A5-%EC%B0%B8%EC%A1%B0%EB%A1%9C-%EC%9D%B8%ED%95%9C-stackover-flow-%EC%97%90%EB%9F%AC

0개의 댓글