저번 목차에서는 데이터를 크롤링해와 향수 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;
}
}
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로 반환
이 두가지 모두 세가지의 기능 중 두번째 기능에서 사용할 예정이다.
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을 만들었다.
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()같은 경우에는 실제 서비스에 사용하지는 않으나, 테스트코드로 향수 데이터가 잘 들어왔는지 검증하기 위해 넣었다. 또한, 이후 추가 기능이 생기면 사용할 수 있기에 냅뒀다.
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;
}