[북스터디] 스프링 부트 핵심 가이드(ch8)를 공부해 보았다.(5편)ch8

Wang_Seok_Hyeon·2023년 4월 1일
1
post-thumbnail

전편에 ORM에 대해 간략하게 이야기하며
JPA 메서드에 대해서 간략하게 소개했다.

하지만 그때 아쉬움이 컸던 부분이 다름 아닌, 모든 메서드에 대한 상세한 설명과 예시가 없었다는 점이었는데 8장에서 해당 부분의 내용이 상세히 다뤄져서 굉장히 기분이 좋았다.

그럼 JPA 즉, DATABASE를 JAVA SPRING에서 편리하게 사용할 수 있도록 자동화된 수 많은 메서드의 사용과 예시에 대해서 다시 한 번 상세하게 정리해 보자.

수많은 쿼리 메서드들

쿼리 메서드의 주제 부분에 사용할 수 있는 주요 키워드는 다음과 같습니다.

  • find…By
  • exists…By
  • count…By
  • delete…By, remove …By
  • …First..., …top...
  • Is/(Is)Not
  • (Is)Null, (Is)NotNull
  • (Is)True,(Is)False
  • And, Or
  • (Is)Greaterthan,(Is)LessThan,(Is)Between
  • (Is)StatingWith(==StatrsWith), (Is)EndingWith(==EndsWith),
    (Is) containing(Contains),(Is)Like
  • Order by

find…By
특정 데이터가 조회

//find...By
Optional<prodcut> findByNumber(Long number);
List<Product> findAllByName(String name);
Product queryByNumber(Long number);

exists…By
특정 데이터가 존재하는지 확인

//exists...By
boolean existsByNumber(Long number);

count…By
조회 쿼리를 수행한 후 쿼리 결과로 나온 레코드의 개수를 리턴

//count...By
long countByMane(String name);

delete…By, remove …By
삭제 쿼리를 수행 리턴 타입이 없거나 삭제한 횟수를 리턴

//delete...By, remove...By
void deleteByNumber(Long number);
long removeByName(String name);

…First..., …top...
쿼리를 통해 조회된 결과값의 개수를 제한하는 키워드
두 키워드는 동일한 역할을 수행
단 건으로 조회하기 위해서는 를 생략

//...First<number>..., ...top<number>...
List<Product> findFirst5ByName(String name);
List<Product> findTop10ByName(String name);

Is/(Is)Not

  • 값의 일치 조건으로 사용하는 조건자 키워드 생략되는 경우가 많으며 equals와 동일한 기능을 수행
  • 값의 불일치를 조건으로 사용하는 조건자 키워드 Is는 생략하고 not 키워드만 사용
//findByNumber
Product findByNumberId(Long number);
Product findByNumberEquals(Long number);

Product findByNumberNot(Long number);
Product findByNumberNot(Long number);

(Is)Null, (Is)NotNull
값이 null인지 검사하는 조건자 키워드

List<Product> findByUpdatedAtNull();
List<Product> findByUpdatedAtIsNull();
List<Product> findByUpdatedAtNotNull();
List<Product> findByUpdatedAtIsNotNull();

(Is)True,(Is)False
boolean 타입으로 지정된 칼럼값을 확인하는 키워드

Product findByisActiveTrue();
Product findByisActiveIsTrue();
Product findByisActiveFalse();
Product findByisActiveIsFalse();

And, Or
여러 조건을 묶을 때 사용

Prodcut findBynumberAndName(Long number, String name);
Product findByNumberOrName(Long number, String name);

(Is)Greaterthan,(Is)LessThan,(Is)Between
숫자나 datetime 칼럼을 대상으로 한 비교 연산에 사용할 수 있는 조건자 키워드

List<Porduct> findByPriceIsGreaterThan(Long price);
List<Porduct> findByPriceGreaterThan(Long price);
List<Porduct> findByPriceGreaterThanEqual(Long price);
List<Porduct> findByPriceIsLessThan(Long price);
List<Porduct> findByPriceLessThan(Long price);
List<Porduct> findByPriceLessThanEqual(Long price);
List<Porduct> findByPriceIsBetween(Long lowPrice, Long highPrice);
List<Porduct> findByPriceBetween(Long lowPrice, Long highPrice);

(Is)StatingWith(==StatrsWith), (Is)EndingWith(==EndsWith),
(Is) containing(Contains),(Is)Like

칼럼값에서 일부 일치 여부를 확인하는 조건자 키워드

List<Product> findByNameLike(String name);
List<Product> findByNameIsLike(String name);

List<Product> findByNameContains(String name);
List<Product> findByNameContaining(String name);
List<Product> findByNameIsContatining(String name);

List<Product> findByNameStartsWith(String name);
List<Product> findByNameStatringWith(String name);
List<Product> findByNameIsStartingwith(String name);

List<Product> findByNameEndsWith(String name);
List<Product> findByNameEndingWith(String name);
List<Product> findByNameIsEndingWith(String name);

Order by
일반적인 쿼리문에서 정렬을 사용할 때는 ORDER BY 구문을 사용

//ASC : 오름차순, DESC : 내림차순
List<Product> findByNameOrderByNumberAsc(String name);
List<Product> findByNameOrderByNumberDesc(String name);

페이지 처리를 간단하게 이용할 수 있는
JPA의 Page와 Pageable

page를 만드는 것은 자료의 정리에 있어서 굉장히 중요한 요소 중 하나다. 위의 Page와 Pageable이 JPA에는 기본으로 제공하고 있기 때문에 이를 위의 쿼리 메서드와 적절히 함께 사용하면 쉽게 페이지를 구현할 수 있다.

페이징 처리를 위한 쿼리 메서드 예시

Page<Product> findByName(String name, Pageable pageable);

위와 같이 리턴 타입으로 Page를 설정하고 매개변수에는 Pageable을 타입의 객체를 정의
해당 메서드를 사용하기 위해서는 아래와 같이 호출

페이징 쿼리 메서드를 호출하는 방법

page<Product> productPage = productRepository.findByName("펜", PageRequest.of(0,2));
of 메서드매개변수 설명비고
of(int page, int size)페이지 번호(0부터 시작) 페이지 당 데이터 개수데이터를 정렬하지 않음
of(int page, int size, Sort)페이지 번호, 페이지 당 데이터 개수 정렬sort에 의해 정렬
of(int page, int size, Direction, String… properties)페이지 번호, 페이지 당 데이터 개수,정렬 방향,속성(칼럼)Sort.by(direction, properties)에 의해 정렬

위 까지의 내용이 메서드와 관련된 주요 활용 내용이다.

그렇지만 이외에도 쿼리를 쉽게 작성하기 위한 연구가 계속 이루어졌고 몇 가지 방법이 더 소개된다. 그 중 대표적으로 꼽을 수 있는게 QueryDSL이 있다.

QueryDSL이란?

QueryDSL은 정적 타입을 이용해 SQL과 같은 쿼리를 생성할 수 있도록 지원하는 프레임워크를 말하며 다음과 같은 장점이 있다.

  • IDE가 제공하는 코드 자동 완성 기능을 사용 가능.

  • 문법적으로 잘못된 쿼리를 허용X

  • 동적으로 쿼리를 생성

  • 가독성 및 생산성 향상

  • 도메인 타입과 프로퍼티를 안전하게 참조

    몇 가지 설정을 더 해줘야 사용을 할 수 있는데 의존성을 추가하는 부분은 자신의 프로젝트 구조의 버전에 맞춰서 적절히 추가해 주면 된다. :)

    특히나 JPA에서는 QueryDSL을 더 편하게 사용할 수 있게 QuerydslPredicateExecutor와를 제공한다.

QuerydslPredicateExecutor 인터페이스

제공 메서드

Optional<T> findOne(Predicate predicate);
Iterable<T> findAll(Predicate predicate);
Iterable<T> findAll(Predicate predicate, Sort sort);
Iterable<T> findAll(Predicate predicate, OrderSpecifier<?>...orders);
Iterable<T> findAll(OrderSpecifier<?>...orders);
Page<T> findAll(Predicate predicate, Pageable, pageable);
long count(Predicate, predicate);
boolean exists(Predicate predicate);

대부분 Predicate을 활용하는 걸 알 수 있는데 이외에도

QuerydslRepositorySupport 추상 클래스라는 것을 활용해, 더욱 쉽게 사용하는 방법에 대해서 소개하고 있다.

하지만 이 부분에 대한 이해도가 낮아 정리를 현재 하지는 못했고, 추후 관련한 내용을 업데이트 할 수 있도록 하겠다. :)

이외에도 서적에서는 BaseEntity와 같은 기본적으로 앱을 만들 때 쓰이는 생성시간과 업데이트 시간에 관한 클래스에 대해서 소개하고 있다. 이 내용의 경우 정말 많이 사용하는 format이므로 한 번 보고 넘어가는 걸 추천한다.

대표적인 BaseEntity 예제

@Getter
@Setter
@ToString
@MappedSuperclass
@EntityListeners(value = {AuditingEntityListener.class})
public abstract class BaseEntity {
  @CreatedDate
	@Column(updateable = false)
  private LocalDateTime createdAt;

  @LastModifiedDate
  private LocalDateTime modifiedAt;
}

getter는 필수이지만 , setter와 toString의 경우 상황에 맞게 설정하는 것을 추천한다.

각각의 어노테이션에 관한 간략한 설명은 아래와 같다.

  • @MappedSuperclass : JPA의 엔티티 클래스가 상속받을 경우 자식 클래스에게 매핑 정보를 전달

  • @EntitiyListeners : 엔티티를 데이터베이스에 적용하기 전후로 콜백을 요청

  • AuditingEntityListener : 엔티티 Auditing 정보를 주입하는 JPA 엔티티 리스너 클래스

  • @CreateDate : 데이터 생성 날짜를 자동으로 주입하는 어노테이션

  • @LastModifiedDate : 데이터 수정 날짜를 자동으로 주입하는 어노테이션

    이것으로 이번 8장에 대해서 간략하게 알아 보았는데, 책에 프로젝트를 통해 따라가는 학습 역시 좋은 과정이므로 꼭 책을 통해 자세히 보는 것을 추천한다 :)

profile
하루 하루 즐겁게

0개의 댓글