Skip to content

Commit

Permalink
feat:filtering
Browse files Browse the repository at this point in the history
  • Loading branch information
youcastle03 committed Nov 15, 2024
1 parent 8a56797 commit 845d8c6
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 27 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ dependencies {
runtimeOnly("com.mysql:mysql-connector-j")
annotationProcessor("org.projectlombok:lombok")
testImplementation("org.springframework.boot:spring-boot-starter-test")
developmentOnly("org.springframework.boot:spring-boot-docker-compose")
// developmentOnly("org.springframework.boot:spring-boot-docker-compose")
testRuntimeOnly("org.junit.platform:junit-platform-launcher")

//jwt
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/jeje/work/aeatbe/controller/ProductController.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,17 @@ public ResponseEntity<?> deleteProducts(@PathVariable Long id
productService.deleteProduct(id);
return ResponseEntity.noContent().build();
}


@PostMapping("/initialize-allergies")
public ResponseEntity<String> initializeAllergiesMapping() {
productService.initializeProductAllergiesMapping();
return ResponseEntity.ok("Product-Allergy 연관 관계가 초기화되었습니다.");
}

@PostMapping("/initialize-freeFrom")
public ResponseEntity<String> initializeFreeFromMapping() {
productService.initializeProductFreeFromMapping();
return ResponseEntity.ok("Product-Allergy 연관 관계가 초기화되었습니다.");
}
}
7 changes: 7 additions & 0 deletions src/main/java/jeje/work/aeatbe/entity/Product.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,11 @@ public void updateTag(String tag) {
this.tag = tag;
}

public void addProductAllergy(ProductAllergy productAllergy) {
productAllergies.add(productAllergy);
}

public void addProductFreeFrom(ProductFreeFrom productFreeFrom) {
productFreeFroms.add(productFreeFrom);
}
}
170 changes: 161 additions & 9 deletions src/main/java/jeje/work/aeatbe/repository/ProductRepository.java
Original file line number Diff line number Diff line change
@@ -1,28 +1,180 @@
package jeje.work.aeatbe.repository;


import java.util.Map;
import jeje.work.aeatbe.entity.Product;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface ProductRepository extends JpaRepository<Product, Long> {
Page<Product> findByProductNameContaining(String q, Pageable pageable);

@Query("SELECT p FROM Product p WHERE NOT EXISTS (SELECT a FROM p.productAllergies a WHERE a.allergy IN :allergies)")
Page<Product> findByAllergyNotIn(List<String> allergies, Pageable pageable);
// Page<Product> findByProductNameContaining(String q, Pageable pageable);
//
// @Query("SELECT p FROM Product p WHERE NOT EXISTS (SELECT a FROM p.productAllergies a WHERE a.allergy IN :allergies)")
// Page<Product> findByAllergyNotIn(List<String> allergies, Pageable pageable);
//
// @Query("SELECT p FROM Product p JOIN p.productFreeFroms f WHERE f.freeFromCategory IN :freeFroms")
// Page<Product> findByFreeFrom(List<String> freeFroms, Pageable pageable);
//
// Page<Product> findByPriceBetween(int priceMin, int priceMax, Pageable pageable);
//
@Query("SELECT new map(p.id as id, p.productName as product_name) FROM Product p")
List<Map<String, Object>> findByProductIdAndName();
//
//
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax")
// Page<Product> findByPriceBetween(@Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);
//
//
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax AND p.productName LIKE %:q%")
// Page<Product> findByProductName(@Param("q") String q, @Param("priceMin") int priceMin,
// @Param("priceMax") int priceMax, Pageable pageable);

@Query("SELECT p FROM Product p JOIN p.productFreeFroms f WHERE f.freeFromCategory IN :freeFroms")
Page<Product> findByFreeFrom(List<String> freeFroms, Pageable pageable);

Page<Product> findByPriceBetween(int priceMin, int priceMax, Pageable pageable);
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax " +
// "AND NOT EXISTS (SELECT a FROM p.productAllergies a WHERE a.allergy IN :allergies)")
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax " +
// "AND NOT EXISTS (SELECT pa FROM ProductAllergy pa WHERE pa.product = p AND pa.allergy.allergyType IN :allergies)")
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax " +
// "AND p.id NOT IN (SELECT pa.product.id FROM ProductAllergy pa WHERE pa.allergy.allergyType IN :allergies)")
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax AND NOT EXISTS (SELECT pa FROM ProductAllergy pa " +
// "WHERE pa.product = p AND pa.allergy.allergyType IN :allergies)")
// Page<Product> findByAllergy(@Param("allergies") List<String> allergies, @Param("priceMin") int priceMin,
// @Param("priceMax") int priceMax, Pageable pageable);
//
//
// @Query("SELECT p FROM Product p JOIN ProductFreeFrom pf ON p = pf.product " +
// "JOIN FreeFromCategory ff ON pf.freeFromCategory = ff WHERE p.price BETWEEN :priceMin AND :priceMax AND ff.freeFromType IN :freeFroms")
// Page<Product> findByFreeFrom(@Param("freeFroms") List<String> freeFroms, @Param("priceMin") int priceMin,
// @Param("priceMax") int priceMax, Pageable pageable);

// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax AND p.productName LIKE %:q% " +
// "AND NOT EXISTS (SELECT a FROM p.productAllergies a WHERE a.allergy IN :allergies)")
// @Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax AND p.productName LIKE %:q% " +
// "AND NOT EXISTS (SELECT pa FROM ProductAllergy pa WHERE pa.product = p AND pa.allergy.allergyType IN :allergies)")
// Page<Product> findByProductNameAndAllergy(@Param("q") String q, @Param("allergies") List<String> allergies,
// @Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);


// @Query("SELECT p FROM Product p JOIN p.productFreeFroms f WHERE p.price BETWEEN :priceMin AND :priceMax " +
// "AND p.productName LIKE %:q% AND f.freeFromCategory IN :freeFroms")
// @Query("SELECT DISTINCT p FROM Product p JOIN ProductFreeFrom pf ON p = pf.product JOIN FreeFromCategory ff ON pf.freeFromCategory = ff " +
// "WHERE p.price BETWEEN :priceMin AND :priceMax AND ff.freeFromType IN :freeFroms")
// @Query("SELECT DISTINCT p FROM Product p JOIN ProductFreeFrom pf ON p = pf.product " +
// "JOIN FreeFromCategory ff ON pf.freeFromCategory = ff WHERE p.price BETWEEN :priceMin AND :priceMax " +
// "AND p.productName LIKE %:q% AND ff.freeFromType IN :freeFroms")
// Page<Product> findByProductNameAndFreeFrom(@Param("q") String q, @Param("freeFroms") List<String> freeFroms,
// @Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);

// @Query("SELECT p FROM Product p JOIN p.productFreeFroms f WHERE p.price BETWEEN :priceMin AND :priceMax " +
// "AND NOT EXISTS (SELECT a FROM p.productAllergies a WHERE a.allergy IN :allergies) AND f.freeFromCategory IN :freeFroms")
// @Query("SELECT DISTINCT p FROM Product p JOIN ProductFreeFrom pf ON p = pf.product JOIN FreeFromCategory ff ON pf.freeFromCategory = ff " +
// "WHERE p.price BETWEEN :priceMin AND :priceMax AND NOT EXISTS (SELECT pa FROM ProductAllergy pa " +
// "WHERE pa.product = p AND pa.allergy.allergyType IN :allergies) AND ff.freeFromType IN :freeFroms")
// Page<Product> findByAllergyAndFreeFrom(@Param("allergies") List<String> allergies, @Param("freeFroms") List<String> freeFroms,
// @Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);



// @Query("SELECT p FROM Product p JOIN p.productFreeFroms f WHERE p.price BETWEEN :priceMin AND :priceMax AND p.productName LIKE %:q% " +
// "AND NOT EXISTS (SELECT a FROM p.productAllergies a WHERE a.allergy IN :allergies) AND f.freeFromCategory IN :freeFroms")
// @Query("SELECT p FROM Product p JOIN ProductFreeFrom pf ON p = pf.product JOIN FreeFromCategory ff ON pf.freeFromCategory = ff " +
// "WHERE p.price BETWEEN :priceMin AND :priceMax AND p.productName LIKE %:q% " +
// "AND NOT EXISTS (SELECT pa FROM ProductAllergy pa WHERE pa.product = p AND pa.allergy.allergyType IN :allergies) " +
// "AND ff.freeFromType IN :freeFroms")
// Page<Product> findByAll(
// @Param("q") String q, @Param("allergies") List<String> allergies, @Param("freeFroms") List<String> freeFroms,
// @Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);

// 기본 가격 범위 검색
@Query("SELECT p FROM Product p WHERE p.price BETWEEN :priceMin AND :priceMax")
Page<Product> findByPriceBetween(@Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);

// 상품명 검색
@Query("SELECT DISTINCT p FROM Product p " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND p.productName LIKE %:q%")
Page<Product> findByProductName(@Param("q") String q, @Param("priceMin") int priceMin,
@Param("priceMax") int priceMax, Pageable pageable);

// 알레르기 제외 검색
@Query("SELECT DISTINCT p FROM Product p " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND NOT EXISTS (SELECT pa FROM ProductAllergy pa " +
"WHERE pa.product = p AND pa.allergy.allergyType IN :allergies)")
Page<Product> findByAllergy(@Param("allergies") List<String> allergies, @Param("priceMin") int priceMin,
@Param("priceMax") int priceMax, Pageable pageable);

// FreeFrom 포함 검색 (OR 조건)
@Query("SELECT DISTINCT p FROM Product p " +
"JOIN p.productFreeFroms pf " +
"JOIN pf.freeFromCategory ff " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND ff.freeFromType IN :freeFroms")
Page<Product> findByFreeFrom(@Param("freeFroms") List<String> freeFroms,
@Param("priceMin") int priceMin,
@Param("priceMax") int priceMax,
Pageable pageable);

// 상품명 + 알레르기 제외 검색
@Query("SELECT DISTINCT p FROM Product p " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND p.productName LIKE %:q% " +
"AND NOT EXISTS (SELECT pa FROM ProductAllergy pa " +
"WHERE pa.product = p AND pa.allergy.allergyType IN :allergies)")
Page<Product> findByProductNameAndAllergy(@Param("q") String q, @Param("allergies") List<String> allergies,
@Param("priceMin") int priceMin, @Param("priceMax") int priceMax, Pageable pageable);

// 상품명 + FreeFrom 검색 (OR 조건)
@Query("SELECT DISTINCT p FROM Product p " +
"JOIN p.productFreeFroms pf " +
"JOIN pf.freeFromCategory ff " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND p.productName LIKE %:q% " +
"AND ff.freeFromType IN :freeFroms")
Page<Product> findByProductNameAndFreeFrom(@Param("q") String q,
@Param("freeFroms") List<String> freeFroms,
@Param("priceMin") int priceMin,
@Param("priceMax") int priceMax,
Pageable pageable);

// 알레르기 제외 + FreeFrom 검색 (OR 조건)
@Query("SELECT DISTINCT p FROM Product p " +
"JOIN p.productFreeFroms pf " +
"JOIN pf.freeFromCategory ff " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND NOT EXISTS (SELECT pa FROM ProductAllergy pa " +
"WHERE pa.product = p AND pa.allergy.allergyType IN :allergies) " +
"AND ff.freeFromType IN :freeFroms")
Page<Product> findByAllergyAndFreeFrom(
@Param("allergies") List<String> allergies,
@Param("freeFroms") List<String> freeFroms,
@Param("priceMin") int priceMin,
@Param("priceMax") int priceMax,
Pageable pageable);

// 전체 조건 검색 (FreeFrom은 OR 조건)
@Query("SELECT DISTINCT p FROM Product p " +
"JOIN p.productFreeFroms pf " +
"JOIN pf.freeFromCategory ff " +
"WHERE p.price BETWEEN :priceMin AND :priceMax " +
"AND p.productName LIKE %:q% " +
"AND NOT EXISTS (SELECT pa FROM ProductAllergy pa " +
"WHERE pa.product = p AND pa.allergy.allergyType IN :allergies) " +
"AND ff.freeFromType IN :freeFroms")
Page<Product> findByAll(
@Param("q") String q,
@Param("allergies") List<String> allergies,
@Param("freeFroms") List<String> freeFroms,
@Param("priceMin") int priceMin,
@Param("priceMax") int priceMax,
Pageable pageable);

@Query("SELECT new map(p.id as id, p.productName as product_name) FROM Product p")
List<Map<String, Object>> findByProductIdAndName();

}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ private void saveProductDTO(ProductDTO productDTO) {
.allergy(allergyCategory)
.build();

product.getProductAllergies().add(productAllergy);

productAllergyRepository.save(productAllergy);
}
}
Expand Down
68 changes: 58 additions & 10 deletions src/main/java/jeje/work/aeatbe/service/ProductService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
import jeje.work.aeatbe.dto.product.ProductDTO;
import jeje.work.aeatbe.dto.product.ProductResponseDTO;
import jeje.work.aeatbe.entity.Product;
import jeje.work.aeatbe.entity.ProductAllergy;
import jeje.work.aeatbe.entity.ProductFreeFrom;
import jeje.work.aeatbe.exception.ProductNotFoundException;
import jeje.work.aeatbe.mapper.product.ProductMapper;
import jeje.work.aeatbe.mapper.product.ProductResponseMapper;
import jeje.work.aeatbe.repository.ProductAllergyRepository;
import jeje.work.aeatbe.repository.ProductFreeFromRepository;
import jeje.work.aeatbe.repository.ProductRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.*;
Expand Down Expand Up @@ -41,6 +45,8 @@ public class ProductService {
private final ReviewRatingService reviewRatingService;
private final AllergyCategoryService allergyCategoryService;
private final FreeFromCategoryService freeFromCategoryService;
private final ProductAllergyRepository productAllergyRepository;
private final ProductFreeFromRepository productFreeFromRepository;


public ProductResponseDTO getProductResponseDTO(ProductDTO productDTO) {
Expand Down Expand Up @@ -71,7 +77,7 @@ public Page<ProductResponseDTO> getAllProducts(String q, List<String> allergies,
List<String> freeFroms, int priceMin, int priceMax, String sortBy, Pageable pageable) {
Pageable sortedPageable = createSortedPageable(pageable, sortBy);

Page<Product> productsPage = findProductsByCriteria(q, allergies, freeFroms, priceMin, priceMax, sortedPageable);
Page<Product> productsPage = findProductsByFiltering(q, allergies, freeFroms, priceMin, priceMax, sortedPageable);

List<ProductResponseDTO> productDTOs = mapToResponseDTO(productsPage.getContent());

Expand Down Expand Up @@ -369,24 +375,38 @@ private Pageable createSortedPageable(Pageable pageable, String sortBy) {
return PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), sort);
}

private Page<Product> findProductsByCriteria(String q, List<String> allergies,
private Page<Product> findProductsByFiltering(String q, List<String> allergies,
List<String> freeFroms, int priceMin, int priceMax, Pageable pageable) {

if ((allergies == null || allergies.isEmpty()) && (freeFroms == null || freeFroms.isEmpty())) {
Pageable sortedByProductName = PageRequest.of(pageable.getPageNumber(),
pageable.getPageSize(), Sort.by("productName").ascending());
return productRepository.findByPriceBetween(priceMin, priceMax, sortedByProductName);

if (q != null && !q.isEmpty() && allergies != null && !allergies.isEmpty() && freeFroms != null && !freeFroms.isEmpty()) {
return productRepository.findByAll(q, allergies, freeFroms, priceMin, priceMax, pageable);
}

if (q != null && !q.isEmpty() && allergies != null && !allergies.isEmpty()) {
return productRepository.findByProductNameAndAllergy(q, allergies, priceMin, priceMax, pageable);
}

if (q != null && !q.isEmpty() && freeFroms != null && !freeFroms.isEmpty()) {
return productRepository.findByProductNameAndFreeFrom(q, freeFroms, priceMin, priceMax, pageable);
}

if (q != null && !q.isEmpty()) {
return productRepository.findByProductName(q, priceMin, priceMax, pageable);
}

if (q != null) {
return productRepository.findByProductNameContaining(q, pageable);
if (allergies != null && !allergies.isEmpty() && freeFroms != null && !freeFroms.isEmpty()) {
return productRepository.findByAllergyAndFreeFrom(allergies, freeFroms, priceMin, priceMax, pageable);
}

if (allergies != null && !allergies.isEmpty()) {
return productRepository.findByAllergyNotIn(allergies, pageable);
return productRepository.findByAllergy(allergies, priceMin, priceMax, pageable);
}

if (freeFroms != null && !freeFroms.isEmpty()) {
return productRepository.findByFreeFrom(freeFroms, pageable);
return productRepository.findByFreeFrom(freeFroms, priceMin, priceMax, pageable);
}

return productRepository.findByPriceBetween(priceMin, priceMax, pageable);
}

Expand All @@ -401,4 +421,32 @@ private List<ProductResponseDTO> mapToResponseDTO(List<Product> products) {
))
.collect(Collectors.toList());
}

@Transactional
public void initializeProductAllergiesMapping() {
List<Product> allProducts = productRepository.findAll();

for (Product product : allProducts) {
List<ProductAllergy> allergies = productAllergyRepository.findByProductId(product.getId());

for (ProductAllergy allergy : allergies) {
product.addProductAllergy(allergy);
}
}
}

@Transactional
public void initializeProductFreeFromMapping() {
List<Product> allProducts = productRepository.findAll();

for (Product product : allProducts) {

List<ProductFreeFrom> freeFroms = productFreeFromRepository.findByProductId(product.getId());

for (ProductFreeFrom freeFrom : freeFroms) {
product.addProductFreeFrom(freeFrom);
}
}
}

}
14 changes: 7 additions & 7 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,24 @@ spring:

datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
# url: jdbc:mysql://localhost:3306/${DB_NAME}${DB_PARAMS}
# username: ${DB_USERNAME}
# password: ${DB_PASSWORD}
url: jdbc:mysql://ls-38256e2c709eb673a54cb785292b2b146d8c8bd6.ch2008eu6uht.ap-northeast-2.rds.amazonaws.com:3306/785292b2b
username: dbaeatbedb
password: s5gpw{67h}aL|+Z<gC~7rw)5iz9J]HGV

jpa:
hibernate:
# ddl-auto: ${SPRING_JPA_HIBERNATE_DDL_AUTO:create-drop}
ddl-auto: ${SPRING_JPA_HIBERNATE_DDL_AUTO:update}
# ddl-auto: ${SPRING_JPA_HIBERNATE_DDL_AUTO:create-drop}
ddl-auto: none
show-sql: ${SPRING_JPA_SHOW_SQL:true}
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
format_sql: true
format_sql: false
defer-datasource-initialization: true

sql:
init:
# mode: always
# mode: always

docker:
compose:
Expand Down

0 comments on commit 845d8c6

Please sign in to comment.