본문 바로가기
web/맛슐랭 Project

맛슐랭 - 맛집 리뷰 service 구현 (CRUD)

by su0a 2024. 3. 27.

1. ReviewService

리뷰를 생성, 수정, 조회, 삭제 하기 위한 로직을 구현한 서비스이다.

리뷰와 이미지는 일대다 조인이기 때문에 dto로 정보를 받아오거나 반환할 경우 for문을 사용하여 처리하였다.

리뷰 등록 시 검증 메서드에서 BindingResult 객체를 통해 오류를 담아 html로 넘겨주었다.

코드 내 주석에 설명을 적어놓았기 때문에 자세한 설명은 생략한다.

@Service
@RequiredArgsConstructor
public class ReviewService {
    private final ReviewRepository reviewRepository;
    private final UploadImageService uploadImageService;
    private final PlaceService placeService;
    private final PlaceRepository placeRepository;

    // 리뷰 등록 시 검증하기 위한 메서드
    public BindingResult validReview(Member member, ReviewCreateRequest req, BindingResult bindingResult){
        // 음식점 상호명이 비어있을 경우
        if(req.getPlace_name().isEmpty()){
            bindingResult.addError(new FieldError("req","place_name","음식점을 선택해주세요."));
        }
        // 특정 회원이 해당 음식점의 리뷰를 이미 작성했는지 확인하기 위해
        else if(reviewRepository.existsByMemberAndPlace_PosXAndPlace_PosY(member, req.getPosX(), req.getPosY())) {
            bindingResult.addError(new FieldError("req","place_name","리뷰를 이미 작성한 장소입니다."));
        }
        // 먹음 음식을 입력하지 않은 경우
        if(req.getEatFoods().isEmpty()||req.getEatFoods().size()==0){
            bindingResult.addError(new FieldError("req","eatFoods","먹은 음식을 작성해 주세요."));
        }
        // 제목이 비어있을 경우
        if(req.getTitle().isEmpty()){
            bindingResult.addError(new FieldError("req","title","제목이 비어있습니다."));
        }
        return bindingResult;
    }

    // 리뷰를 저장하기 위한 메서드
    @Transactional
    public Review saveReview(ReviewCreateRequest req, Member member) throws IOException {

        Place place = placeService.findPlace(req.getPlace_name(), req.getAddress(), req.getPosX(), req.getPosY());
        Review review = Review.toEntity(req, place, member);

        // 리뷰 저장
        Review saveReview = reviewRepository.save(review);

        // 업로드된 이미지들을 저장
        for (MultipartFile file : req.getMultipartFiles()) {
            UploadImage uploadImage = this.uploadImageService.saveReviewImage(file, saveReview);
            saveReview.getUploadImages().add(uploadImage);
        }
        // member 에도 review 추가
        member.getReviews().add(saveReview);
        // place 에도 review 추가
        place.getReviews().add(saveReview);

        return saveReview;
    }

    // 리뷰를 삭제하기 위한 메서드
    @Transactional
    public void deleteReview(Long reviewId) {
        // 리뷰 id로 리뷰를 찾아서 반환
        Review review = reviewRepository.findById(reviewId).get();
        Place place = review.getPlace();
        reviewRepository.delete(review);
        place.getReviews().remove(review);
        // 해당 음식점의 리뷰가 없으면 음식점의 정보도 함께 사라짐
        if(place.getReviews().size()==0){
            placeRepository.delete(place);
        }
    }

    // 특정 멤버가 쓴 리뷰를 반환하는 메서드
    public List<ReviewDto> getMyReviews(String memberEmail){
        List<Review> myReviews = reviewRepository.findByMemberEmail(memberEmail);
        // 리뷰를 dto로 반환하기 위해 만든 객체
        List<ReviewDto> myReviewDtos = new ArrayList<>();
        for(Review myReview:myReviews){
            List<UploadImage> uploadImages = myReview.getUploadImages();
            // 이미지의 파일 경로만 저장하기 위해 만든 리스트
            List<String> imagePath=new ArrayList<>();
            for(UploadImage uploadImage:uploadImages){
                String filePath = uploadImage.getSavedFilename();
                imagePath.add(filePath);
            }
            // 리뷰 객체와 이미지 경로를 저장한 리스트를 파라미터 값으로 전달
            ReviewDto reviewDto = ReviewDto.of(myReview,imagePath);

            myReviewDtos.add(reviewDto);
        }
        return myReviewDtos;
    }

    // 리뷰를 수정하기 위한 메서드
    @Transactional
    public void modifyReview(ReviewDto reviewDto) throws IOException{
        Review review = reviewRepository.findById(reviewDto.getId()).get();
        Review modifyReview = review.modify(reviewDto.getEatFoods(), reviewDto.getTitle(),reviewDto.getContent());
        // 업로드한 이미지가 존재할 경우
        if(reviewDto.getMultipartFiles().size()>0){
            // 해당 리뷰에 저장되어 있는 이미지들을 삭제 후 업로드한 이미지 저장
            List<UploadImage> uploadImages = modifyReview.getUploadImages();
            modifyReview.uploadImageListClear();
            for(UploadImage uploadImage:uploadImages){
                uploadImageService.deleteImage(uploadImage);
            }
            // 업로드된 이미지들을 저장
            for (MultipartFile file : reviewDto.getMultipartFiles()) {
                UploadImage uploadImage = this.uploadImageService.saveReviewImage(file, modifyReview);
                modifyReview.getUploadImages().add(uploadImage);
            }
        }
    }

}

 

2. PlaceService

Place 객체를 경도, 위도를 사용하여 찾은 후 없으면 새로운 Place 객체를 생성한다.

@Service
@RequiredArgsConstructor
public class PlaceService {
    private final PlaceRepository placeRepository;

    // 해당 음식점의 정보를 찾고 없으면 새로운 Place 객체 생성 후 저장
    public Place findPlace(String place_name,String address, String posX, String posY){
        Place place;
        // 해당 음식점이 존재할 경우
        if(placeRepository.existsByPosXAndPosY(posX,posY)){
            place = placeRepository.findByPosXAndPosY(posX, posY).get();
        }
        // 해당 음식점이 존재하지 않을 경우
        else{
            place=savePlace(place_name,address, posX,posY);
        }
        return place;
    }

    // 음식점을 저장하기 위한 메서드
    @Transactional
    public Place savePlace(String place_name, String address,String pos_x,String pos_y){
        // 해당 음식점에 관한 정보로 엔티티 생성 후 저장
        Place place = placeRepository.save(Place.toEntity(place_name, address, pos_x, pos_y));
        return place;
    }
}