Post

JPA_findByCategory/keyword

✅ 조건(카테고리, 키워드)이 있도록 JPA에서 찾아올 떄

코딩공책-32

1. 먼저, 내가 가져오려는 값이 1개의 테이블에서 가져오는지, 여러개의 테이블에서 필요한지 파악하기

  1. 1개의 테이블에서만 정보 가져오기 필요하다면: findBy하고 끝
  2. 여러개의 테이블에서 정보 조금씩 필요:
    1. JPQL에서 JOIN TABLE하거나
    2. service에서 각 테이블에서 각 JPA로 받아온 다음 합친다. 💡 4번 예시 참고

2. 조건이 있는가? 특정 카테고리를 찾고 싶다거나, 특정 키워드를 찾고 싶다거나

  1. JPQL에서 WHERE문으로 조건 처리
  2. 일단 JPA에서 findAll로 모든 아이템들을 받아온 후, stream().filter()로 조건을 찾는다.

3. JPA에서 받아온 response와 내가 return하고 싶은 response가 DTO가 같은가?

  1. 같다면 바로 위에서 조건 찾은 다음 toList() 하고 return
  2. 다르면map(()-> new 내가 만들고 싶은 DTO)

💡 결론

  • 여러개의 테이블에서 조인해야하는데, 찾고 싶은 조건들도 있다면 그냥 편하게 JPA로 처리한다.
  • 이미 findAll이 있고, 조건 하나만 간단히 추가하고 return하는 형식이 같다면 그냥 findAll쓰고 service에서 조건만 처리한다.

✔️ 1. Post Board 예시

코딩공책-29

  1. post 테이블에서 findAll해서 모든 post를 찾아온다. 별도의 테이블 join은 필요가 없다.
    우리가 원하는 정보가 모두 post 테이블에 있기 떄문이다.
  2. 조건: 키워드를 포함하는
    이를 위해서 postService에서: JPA에서 찾아온 모든 post중에, stream().filter()을 활용하여 키워드를 포함하는 post만 찾는다.
  3. 내가 JPA에서 받아온건 post인데, 내보내고 싶은 DTO는 postResponse이다. 따라서 map(()-> new postResponse)

✔️ 2. ShoppingMall-verSoh 예시

코딩공책-30

  1. 원하는 정보가 여러게 테이블에 흩어져 있다. 여러게 테이블을 join해서 정보 모아모아
  2. 조건: 키워드를 포함하는
    이를 위해서 productService에서: JPA에서 찾아온 모든 products 중에, stream().filter()을 활용하여 키워드를 포함하는 products만 찾는다.
  3. 내가 JPA에서 받아온건 productMainResponse이고, 내보내고 싶은 DTO도 productMainResponse이다. 두 DTO가 일치하므로 별 문제없이 바로 내보낸다.

✔️ 3. ShoppingMall-Mar2024 예시 ⭐️ 제일 깥끔

코딩공책-31

  1. 원하는 정보가 여러게 테이블에 흩어져 있다. 키워드를 포함하는 조건도 있다.
  2. JPA에서 JPQL로 모든 로직(테이블 합치기 + 키워드 찾기)을 다 처리해버린다!
  3. JPA에서 받아온 응답과 내보내고 싶은 응답 또한 같으므로 바로 내보낸다.

✔️ 4. service에서 각 테이블에서 각 JPA로 받아온 다음 합치기 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
 public ResponseDTO findProductDetail(Integer productId) {
        Product product = productJpa.findById(productId)
                .orElseThrow(() -> new NotFoundException("해당 아이디" + productId + "상품을 찾을 수 없습니다."));

        if(product.getProductStatus().equals("soldOut")) throw new SoldOutException("판매 종료된 상품입니다.");

        List<Review> reviews = reviewJpa.findByProduct(product);
        Double reviewAvg = reviews.stream().collect(Collectors.averagingDouble(Review::getScore));

        List<ProductPhoto> productPhotos = productPhotoJpa.findByProduct(product);
        List<PhotoRequestDto> photoRequestDtoList = productPhotos
                .stream()
                .map((p) -> new PhotoRequestDto(p.getPhotoUrl(), p.getPhotoType()))
                .collect(Collectors.toList());

        List<ProductOption> productOption = productOptionJpa.findByProduct(product);
        List<ProductOptionRequestDto> productOptionRequestDtoList = productOption
                .stream()
                .map((p) -> new ProductOptionRequestDto(p.getProductOptionId(), p.getColor(), p.getProductSize(), p.getStock()))
                .collect(Collectors.toList());

        List<ReviewUserDto> reviewUserDtoList = reviews
                .stream()
                .map((r) -> new ReviewUserDto(r.getUser().getUserId(), r.getReviewId(), r.getReviewContents(), r.getScore(), r.getCreatedAt()))
                .collect(Collectors.toList());


        ProductDetailResponse productDetailResponse = ProductDetailResponse.builder()
                .productId(product.getProductId())
                .productName(product.getProductName())
                .productPrice(product.getProductPrice())
                .category(product.getCategory())
                .productStatus(product.getProductStatus())
                .createAt(product.getCreatedAt())
                .finishAt(product.getFinishedAt())
                .scoreAvg(reviewAvg)
                .photoRequestDtoList(photoRequestDtoList)
                .productOptionRequestList(productOptionRequestDtoList)
                .reviewUserDtoList(reviewUserDtoList)
                .build();

        return new ResponseDTO(200, "제품 상세 조회 성공", productDetailResponse);

    }
This post is licensed under CC BY 4.0 by the author.