simDev1234
심플하고 차분하게
simDev1234
전체 방문자
오늘
어제
  • 분류 전체보기
    • Computer Science
      • Basic Math
      • Data Structure
      • Algorithm
      • Database
      • OS
    • Language
      • Java
      • Kotlin
      • SQL
    • Framework
      • Spring
      • Orm&Mapper
      • 프로젝트로 스프링 이해하기
      • 스프링 라이브러리
    • Infra
      • Cloud
      • Docker
      • Redis
      • AWS, Azure
      • Device
    • Etc
      • CleanCoding
    • Git,Github

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 스프링
  • 참조변수
  • 참조타입
  • controllerTest
  • 컨트롤러
  • 404
  • 자바
  • 자바프로그램
  • JVM메모리구조
  • null
  • 자바프로그래밍
  • scanner #next() #nextLine()
  • 자바메모리구조

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
simDev1234

심플하고 차분하게

[이커머스 프로젝트] QueryDSL를 통해 상품 검색하기
Framework/프로젝트로 스프링 이해하기

[이커머스 프로젝트] QueryDSL를 통해 상품 검색하기

2022. 12. 13. 21:28

|  개요

1. Build.Gradle에 QueryDSL과 Jakarta를 함께 주입한다.

2. Config 클래스를 만들어 EntityManager를 생성하고 이를 JpaQueryFactory에 넣어준다.

3. ProductRepositoryCustom과 ProductRepositoryImpl을 만들고, ProductRepostory에서 Custom 인터페이스를 상속한다.

 

|  상세 

 

1. Build.Gradle에 QueryDSL를 추가한다.

* Jakarta를 추가하는 이유는, NoClassDefFoundError를 방지하기 위해서이다.

* NoClassDefFoundError는 컴파일 시에는 있었는데 실행 시에는 클래스를 찾을 수 없을 때 발생한다고 한다..

  QueryDSL를 사용할 때 자주 나타나는 오류인 것 같다.

// queryDSL
implementation 'com.querydsl:querydsl-jpa'
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jpa"
// Jakarta
// java.lang.NoClassDefFoundError(javax.annotation.Entity) 발생 대응
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
// java.lang.NoClassDefFoundError(javax.annotation.Generated) 발생 대응
annotationProcessor "jakarta.annotation:jakarta.annotation-api"

 

2. Config 클래스

- EntityManager를 생성하고, 이를 JPAQueryFactory에 넣어준다.

@Configuration
public class QueryDslConfig {

  @PersistenceContext
  private EntityManager entityManager;

  @Bean
  public JPAQueryFactory jpaQueryFactory(){
    return new JPAQueryFactory(entityManager);
  }

}

 

3. 서비스 클래스

- 상품명을 통해 조회하는 메소드를 작성한다.

@Service
class XXXService{

	/**
     * 상품명을 통해 유사 상품 목록 조회
     */
    public List<Product> searchByName(String name) {
        return productRepository.searchByName(name);
    }
}

 

4. JPQL를 적용할 커스텀 Repository 만들기

   (1) Custom interface와 (2) Impl 구현체 클래스

  * 이때, 이름은 ProductRepository에 Custom, Impl을 붙여 만들어 주어야 JPA가 인식할 수 있다.

출처:https://elsboo.tistory.com/35

(1) ProductRepositoryCustom

public interface ProductRepositoryCustom {

    List<Product> searchByName(String name);

}

 

(2) ProductRepositoryImpl

1) JPAQueryFactory를 주입한다.

2) QProduct를 생성한다.

   (또는 이것을 private final로 뺄 수도 있다. --> 양식은 QMember, QProduct와 같이 이름을 맞추어야 한다.)

3) 1)의 JpaQueryFactory를 통해 커스텀 쿼리를 작성한다.

@Repository
@RequiredArgsConstructor
public class ProductRepositoryImpl implements ProductRepositoryCustom{

    private final JPAQueryFactory queryFactory;

    @Override
    public List<Product> searchByName(String name){

        String search = "%" + name + "%";

        QProduct product = QProduct.product;

        return queryFactory.selectFrom(product)
                .where(product.name.like(search))
                .fetch();

    }

}

 

(3) ProductRepository에서 (1)에서 만든 interfacte를 extends한다.

* 참고로에 아래에 적은 @EntityGraph는 지연로딩 때문에 Proxy로 가져올 데이터들을 전부 로딩하기 위해 작업했던 것이었다. 따로 정리할 시간이 없을 것 같아 일단 노트해둔다..

public interface ProductRepository extends JpaRepository<Product, Long>, ProductRepositoryCustom {

    @EntityGraph(attributePaths = {"productItems"}, type = EntityGraph.EntityGraphType.LOAD)
    Optional<Product> findBySellerIdAndId(Long sellerId, Long id);

    @EntityGraph(attributePaths = {"productItems"}, type = EntityGraph.EntityGraphType.LOAD)
    Optional<Product> findWithProductItemsById(Long id);

}

 

5. 컨트롤러를 작성하고 테스트를 해본다.

@RestController
@RequestMapping("/search/product")
@RequiredArgsConstructor
public class SearchController {

    private final ProductSearchService productSearchService;

    @GetMapping
    public ResponseEntity<List<ProductDto>> searchByName(@RequestParam String name) {

        return ResponseEntity.ok(productSearchService.searchByName(name).stream()
            .map(ProductDto::withoutItemsFrom).collect(Collectors.toList()));

    }

}

 

 

[참고]

부트캠프 수업 내용 정리

https://elsboo.tistory.com/35

@EntityGraph https://itmoon.tistory.com/77

'Framework > 프로젝트로 스프링 이해하기' 카테고리의 다른 글

[이커머스 프로젝트] 장바구니 구현하기 (RedisTemplate)  (0) 2022.12.15
[이커머스 프로젝트] 이메일 전송 기능 구현 (Mailgun, Feign)  (0) 2022.11.25
[이커머스 프로젝트] Swagger2 적용  (0) 2022.11.25
[이커머스 프로젝트] 멀티 모듈 생성하기  (0) 2022.11.25
[이커머스 프로젝트] API Gateway를 활용한 MSA (Micro Service Architecture)  (0) 2022.11.25
    'Framework/프로젝트로 스프링 이해하기' 카테고리의 다른 글
    • [이커머스 프로젝트] 장바구니 구현하기 (RedisTemplate)
    • [이커머스 프로젝트] 이메일 전송 기능 구현 (Mailgun, Feign)
    • [이커머스 프로젝트] Swagger2 적용
    • [이커머스 프로젝트] 멀티 모듈 생성하기
    simDev1234
    simDev1234
    TIL용 블로그. * 저작권 이슈가 있는 부분이 있다면 댓글 부탁드립니다.

    티스토리툴바