Spring Data JPA - Specifications(명세)

2022. 8. 2. 21:45·공부/JPA
반응형

출처 : 인프런 실전! 스프링 데이터 JPA

Spring Data JPA 게시글은 대부분 인프런의 김영한님의 강의인 '실전! 스프링 데이터 JPA' 기반으로 내용을 정리했습니다.

 

나머지 기능들

  • Specifications(명세)
  • Query By Example
  • Projections
  • 네이티브 쿼리

나머지 기능들은 복잡도가 높지만 실무에서 그닥 필요하지는 않은 기능들이다. 그래도 개 똥도 약에 쓰려면 없다고, 알고 있으면 좋을 기능들이므로 이런 게 있구나 정도만 파악하면 될 것 같다.

 

Specifications(명세)

스프링 데이터 JPA는 JPA Criteria를 활용해서 이 개념을 사용할 수 있도록 지원한다. Criteria 앞에서 자주 좀 본 기능 같다. 하지만 기억에 잘 안 남는 거 보니 그다지 중요한 애는 아닌 거 같다. 강의에서도 말하길 이 기능은 JPA 설계가 가장 잘못된 기능 중 하나라고 한다(개인 의견이겠지만). 그만큼 실무에서는 잘 사용하지 않는 기능이라고 한다. 이유는 코드를 해독하는데 있어서 어려움이 많아 쿼리가 조금이라도 복잡해지면 사용하기가 어렵다 한다.

 

술어(predicate)

  • 참 또는 거짓으로 평가
  • AND OR 같은 연산자로 조합해서 다양한 검색 조건을 쉽게 생성(컴포지트 패턴)
    • ex) 검색 조건 하나하나
  • 스프링 데이터 JPA는 org.springframework.data.jpa.domain.Specification 클래스로 정의한다.

 

명세 기능 사용 방법

JpaSpecificationExecutor 인터페이스 상속

// MemberRepository.interface
public interface MemberRepository extends JpaRepository<Member, Long>,
        MemberRepositoryCustom, JpaSpecificationExecutor<Member>{

전에 만들어 두었던 MemberRepository.interface에 extends 구문 맨 뒤에 JpaSpecificationExecutor<타입>을 추가해주면 된다. JpaSpecificationExeutor<T> 안을 들여다보면 뭔가 익숙한 메서드에 매개변수로 Specification<T>을 받는 걸 볼 수 있다.

List<T> findAll(@Nullable Specification<T> spec);
  • MemberSpec.class
public class MemberSpec {

    public static Specification<Member> teamName(final String teamName) {
        return (Specification<Member>) (root, query, criteriaBuilder) -> {

            if(StringUtils.isEmpty(teamName)) {
                return null;
            }

            Join<Member, Team> t = root.join("team", JoinType.INNER);// 회원과 조인
            return criteriaBuilder.equal(t.get("name"), teamName);
        };
    }

    public static Specification<Member> username(final String username) {
        return (Specification<Member>) (root, query, criteriaBuilder) ->
            criteriaBuilder.equal(root.get("username"), username);
    }
}
  • MemberRepositoryTest.class
@Test
public void specBasic() {
    Team teamA = new Team("teamA");
    em.persist(teamA);

    Member m1 = new Member("m1", 0, teamA);
    Member m2 = new Member("m2", 0, teamA);
    em.persist(m1);
    em.persist(m2);

    em.flush();
    em.clear();

    Specification<Member> spec = MemberSpec.username("m1").and(MemberSpec.teamName("teamA"));

    List<Member> result = memberRepository.findAll(spec);

    Assertions.assertThat(result.size()).isEqualTo(1);
}
select
    member0_.member_id as member_i1_1_,
    member0_.create_by as create_b2_1_,
    member0_.create_date as create_d3_1_,
    member0_.last_modified_by as last_mod4_1_,
    member0_.last_modified_date as last_mod5_1_,
    member0_.age as age6_1_,
    member0_.team_id as team_id8_1_,
    member0_.username as username7_1_ 
from
    member member0_ 
inner join
    team team1_ 
        on member0_.team_id=team1_.team_id 
where
    member0_.username=? 
    and team1_.name=?
  • Specification을 구현하면 명세들을 조립할 수 있다. where(), and(), or(), not()을 제공한다.
  • findAll()을 보면 회원 이름 명세(username)와 팀 이름 명세(teamName)를 and로 조합해서 검색 조건으로 사용한다.

Specification의 장점 중 하나는 동적 쿼리를 편리하게 자바로 이용할 수 있다는 점이다. Specification 기능 자체는 괜찮은데 한 가지 아쉬운 점이 JPA Criteria를 사용한다는 것이다. 그러니 코드 자체가 너무 복잡하다. 그래서 예제 코드를 보면 한 눈에 들어오지 않는 단점이 있다.

! 그래서 결론은! 실무에서는 사용하지 말자.
반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Spring Data JPA - Projections
  • Spring Data JPA - Query By Example
  • Spring Data JPA - 새로운 엔티티를 구별하는 방법
  • Spring Data JPA - 스프링 데이터 JPA 구현체 분석
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    RESTful
    IT
    프론트엔드
    스프링부트
    방통대
    운영체제
    SQL
    JPA
    react
    자바스크립트
    기출문제
    에러해결
    알고리즘
    QueryDSL
    Java
    oracle
    MSA
    SpringBoot를 이용한 RESTful Web Service 개발
    토이프로젝트
    코딩테스트
    백준
    springboot
    Spring
    전자정부프레임워크
    개발자
    egov
    프로그래머스
    토비의스프링부트
    인프런
    넥사크로
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
Spring Data JPA - Specifications(명세)
상단으로

티스토리툴바