본문 바로가기
카테고리 없음

스프링 부트 핵심 가이드 4주차

by 이두덩이 2023. 8. 13.

 

▶ 제08장.  Spring Data JPA 활용

  1. JPQL(JPA Query Language)
    • JPA에서 사용할 수 있는 쿼리를 의미
    • 예시 -> select p from Product p where p.number =?1;
      • Product : 엔티티 이름
      • p.nuber : 엔티티 속성
  2. 쿼리 메서드
    • JpaRepository에서 상속받은 기본 메서드 이외의 별도 메서드를 정의해서 사용할 경우 간단하게 쿼리문을 작성하기 위해 사용
    • 쿼리 메서드의 생성법 (동작을 결정하는 주제와 서술어로 구분)  
      • find... By, exist... By, get... By,,, 등과 같은 키워드로 쿼리 주제를 정함
      • By : 서술어의 시작을 나타내는 구분자 역할
      • 서술어 부분은 검색 및 청렬 조건을 지정
      • 엔티티 속성으로 정의할 수 있으며  AND나 OR를 사용해 조건 확장 가능
      • 엔티티에서 관리하고 있는 속성(필드)만 참조 가능
      • 예시  -> List <Person> findByLastnameAndEmail(String lastName, String email);
    • 주제 키워드
    • 조건자 키워드
      1. Is: 값의 일치를 조건으로 사용
        • 생량 되는 경우도 많으며, Equals와 동일한 기능을 수행
        • 예시 ->
          • Product findByNumberIs(Long number);
          • Product findByNumberEquals(Long number);
      2. (Is) Not: 값의 불일치를 조건으로 사용
      3. (Is) Null, (Is) NotNull: 값이 null인지 검사
      4. (Is) True, (Is) NotTrue: boolean타입으로 지정된 칼럼값을 확인
      5. Or, And: 여러 조건을 묶을 때 사용
      6. (Is) GreaterThan, (Is) LessThan, (Is) Between:숫자나 datetime 칼럼을 대상으로 한 비교 연산에 사용
      7. (Is) StartingWith(==StartsWith), (Is) EndingWith(==EndsWith), (Is) Containing(==Contains), (Is) Like: 칼럼값에서 일부 일치 여부를 확인
  3. 정렬과 페이징 처리
    • 정렬 처리
      1. 쿼리 메서드 정렬 처리
        • 예시 -> List <Product> findByNameorderByPriceAscStockDesc(String name);
        • Price를 기중으로 오름차순 정렬 후 후순위로 재고수량을 기준으로 내림차순 정렬
      2. 매개변수를 활용한 쿼리 정렬
        • 예시 -> List findByNameorder(String name, Sort sort);
        • 쿼리 메서드 정렬과 거의 같은 기능을 수행
        • 차이점은 Sort로 받은 정렬 기준을 가지고 쿼리문에 적용
        • 호출에서 예시 -> productRepository.findByName("펜", Sort.by(Order.asc("price"), Order.desc("stock")));
    • 페이징 처리
      • DB의 레코드를 개수로 나눠 페이지를 구분하는 것
      • 리턴 타입으로 Page를 설정하고 매개변수에는 Pageable 타입을 정의해서 사용
        • 예시 -> Page <Product> findByName(String name, Pageable, pageable);
      • 호출할 때 리턴 타임으로 Page객체를 받고, Pageable 파라미터 전달을 위해 PageRequest클래스 사용
        • 호출에서 예시 -> Page <Product> productPage = productRepository.findByName("펜", PageRequest.of(0, 2));
        • PageRequest의 매개변수
          1. of(int page, int size): 페이지 번호(0부터 시작), 페이지당 데이터 개수
          2. of(int page, int size, Sort): 페이지 번호, 페이지당 데이터 개수, 정렬
          3. of(int page, int size, Derection, String properties): 페이지 번호, 페이지당 데이터 개수, 정렬 방향, 속성(칼럼)
  4. @Query 어노테이션 사용하기
    • 직접 JPQL을 작성할 수 있는 방식
    • JPA 구현체에서 자동으로 쿼리 문장을 해석하고 실행
    • 예시 -> @Query("select p From Product As p where p.name = ?1"
                   List<Product> findBy Name(String name);
    • @Param 어노테이션과 함께 사용하면 ?의 순서 신경 없어 오류 발생 적어짐
      • 예시 -> @Query("select p From Product As p where p.name = :name"
                    List findBy Name(@Param("name") String name);
  5. QueryDSL 적용하기
    • @Query는 메서드 이름 기반 JPQL의 한계는 대부분 해소 가능하지만, 직접 문자열을 입력하기 때문에 오타와 같은 에러가 발생해 런타임 에러가 발생한다.(컴파일 시점에는 에러가 잡히지 않는다) 이를 방지하기 위해 QueryDSL을 사용
    • QueryDSL 장점
      1. IDE에서 자동 완성을 사용 가능
      2. 문법적으로 잘못된 쿼리를 허용하지 않음
      3. 고정된 SQL 쿼리를 작성하지 않기 때문에 동적으로 쿼리를 생성할 수 있음
      4. 코드로 작성하므로 가독성 및 생산성 향상
      5. 도메인 타입과 프로퍼티를 안전하게 참조 가능
    • 사용을 위해서 의존성 주입, plugins에 추가가 필요
    • Maven(complie), Gradle(other -> complieQuertdsl) 눌러 빌드해주면 작성했던 모든 엔티티 클래스의 Qdomain이라는 쿼리 타입의 클래스를 자체적으로 생성해서 메타데이터로 사용해서 SQL을 작성
    • 리턴 타입
      • List<T> fetch(): 조회 결과를 리스트로 반환
      • T fetchOne(): 단 건의 조회 결과를 반환
      • T fetchFirst(): 여러 건의 조회 결과 중 1건을 반환(내부 로직: .limit(1).fetchOne())
      • Long fetchCount(): 조회 결과의 개수를 반환
      • QueryResult<T> fetchResults(): 조회 결과 리스트와 개수를 포함한 QueryResults를 반환
    • 사용법
      1. JPAQuery<Product> query = new JPAQuery(entityManager);
        • from 절부터 작성
      2. JPAQueryFactory query = new JPAQueryFactory(entityManager);
        • select절부터 작성 가능
  6. [한걸음 더]JPA Auditin 적용
    • Spring Data JPA에서 엔티티 클래스에는 공통적으로 들어가는 필드들을 자동으로 넣어주는 기능
    • 생성 주체, 생성 일자, 변경 주체, 병경 일자
    • @SpringBootApplication있는 곳, 아니면 별도의 @Configuration클래스에 @EnableJpaAuditing 어노테이션추가해서 사용(후자의 방법을 권장)