(Spring) 취향 기반 향수 추천 서비스 - 2. 향수 패키지 개발

김준석·2023년 3월 17일
0

향수 추천 서비스

목록 보기
3/21

목표

저번 목차에서는 데이터를 크롤링해와 향수 DB에 저장을 했다. 이번 목차에서는 향수 데이터를 어떻게 다룰건지에 대한 설명이다.

도메인

Perfume.java

@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Entity(name = "perfume")
public class Perfume {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @NotNull
    @Column(nullable = false, length = 40)
    private String perfumeName;

    @NotNull
    @Column(nullable = false, length = 20)
    private String brandName;

    @NotNull
    @Column(nullable = false, length = 100)
    private String perfumeFeature;

    @NotNull
    @Column(nullable = false)
    private String perfumeImageUrl;

    @Builder
    public Perfume(Long id, String perfumeName, String brandName, String perfumeFeature, String perfumeImageUrl) {
        this.id = id;
        this.perfumeName = perfumeName;
        this.brandName = brandName;
        this.perfumeFeature = perfumeFeature;
        this.perfumeImageUrl = perfumeImageUrl;
    }
}
  • 앞에서 크롤링한 perfumeName,brandName,perfumeFeature,perfumeImageUrl을 저장하기 위해 이를 필드로 설정해줬다.
    이미 매개변수를 받는 생성자가 존재하기 때문에 @NoargsConstructor을 사용하였다.
    추후에 서비스가 커져 Perfume의 자식 객체가 생긴다면 접근을 가능하게 하기 위해서, 또는 외부에서 접근할 수 없도록 AccessLevel을 Protected로 설정하였다.

Repository

PerfumeRepository.java


@Repository
public interface PerfumeRepository extends JpaRepository<Perfume, Long> {

    Optional<Perfume> findById(Long id);

    List<Perfume> findByPerfumeNameContaining(String perfumeName);

    List<Perfume> findByBrandNameContaining(String perfumeBrand);


}

향수 도메인의 역할은 두가지 밖에 없다.
1. 이름으로 향수를 찾아서 List로 반환
2. 브랜드로 향수를 찾아서 List로 반환

이 두가지 모두 세가지의 기능 중 두번째 기능에서 사용할 예정이다.

exception


public class BrandNotFoundException extends BadRequestException {
    private static final String message = "해당 브랜드의 향수 데이터가 없습니다.";

    public BrandNotFoundException() {
        super(message);
    }
}

public class PerfumeNotFoundException extends BadRequestException {

    private static final String message = "해당 향수를 찾을 수 없습니다.";

    public PerfumeNotFoundException() {
        super(message);
    }
}

exception은 모두 최상위로 RuntimeException을 상속하여 커스텀 Exception을 만들었다.

Service


    public List<Perfume> findPerfumeByName(PerfumeRequestDto perfumeRequestDto) {

        List<Perfume> perfume = perfumeRepository.findByPerfumeNameContaining(perfumeRequestDto.getPerfumeName());
        isPerfumeListEmpty(perfume);
        return perfume;
    }

    public List<Perfume> findPerfumeByBrand(PerfumeRequestDto perfumeRequestDto) {
        List<Perfume> perfume = perfumeRepository.findByBrandNameContaining(perfumeRequestDto.getBrandName());
        isBrandListEmpty(perfume);
        return perfume;
    }

    public Perfume findPerfumeById(Long id) {
        return perfumeRepository.findById(id).orElseThrow(PerfumeNotFoundException::new);
    }

    public void deleteAllData() {
        perfumeRepository.deleteAll();
    }

    public List<Perfume> showAllPerfumeData() {
        List<Perfume> perfumeList = perfumeRepository.findAll().stream().collect(Collectors.toList());

        isPerfumeListEmpty(perfumeList);
        return perfumeList;
    }

    private boolean isPerfumeListEmpty(List<Perfume> perfumeList) {
        if (perfumeList.isEmpty()) {
            throw new PerfumeNotFoundException();
        }
        return true;
    }

    private boolean isBrandListEmpty(List<Perfume> brandList) {
        if (brandList.isEmpty()) {
            throw new BrandNotFoundException();
        }
        return true;
    }
  • isPerfumeListEmpty , isBrandListEmpty를 통해 객체가 비어있는지 확인을 하였고,
    클라이언트에서 Body로 보낸 id , 이름 , 브랜드 로 각각 향수를 찾을 수 있게 설계하였다.

  • 이름과 브랜드같은 경우에는 findBy~~Contating을 사용하여 검색한 이름이 포함되면 찾아질 수 있도록 하였다.

showAllperfumeData()같은 경우에는 실제 서비스에 사용하지는 않으나, 테스트코드로 향수 데이터가 잘 들어왔는지 검증하기 위해 넣었다. 또한, 이후 추가 기능이 생기면 사용할 수 있기에 냅뒀다.

DTO

PerfumeRequestDto, PerfumeResponseDto
두 Dto 모두 Request와 Response로만 사용하기 위해 @Getter외에 다른 어노테이션은 넣지 않았다.

@Getter
public class PerfumeResponseDto {

    private Long id;
    private String perfumeName;
    private String brandName;
    private String perfumeFeature;
    private String perfumeImageUrl;

    public PerfumeResponseDto() {

    }
    @Builder
    public PerfumeResponseDto(Long id, String perfumeName, String brandName, String perfumeFeature, String perfumeImageUrl) {
        this.id = id;
        this.perfumeName = perfumeName;
        this.brandName = brandName;
        this.perfumeFeature = perfumeFeature;
        this.perfumeImageUrl = perfumeImageUrl;
    }

코드를 전부 다 넣지 않았습니다. 전체 코드는 Github에 있습니다!

향수 추천 서비스 깃허브

profile
기록하면서 성장하기!

0개의 댓글