Spring Data JPA - Query By Example

2022. 8. 2. 23:43·공부/JPA
반응형

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

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

 

Query By Example

Query By Example은 쿼리를 Example에 의해서 하겠다는 기능이다. 코드로 살펴보자.

@Test
public void queryByExample() {
    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();

    //Probe
    Member member = new Member("m1"); // 엔티티 자체가 검색 조건이 된다.
    Example<Member> ex = Example.of(member);
    List<Member> result = memberRepository.findAll(ex);

    assertThat(result.get(0).getUsername()).isEqualTo("m1");

}
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_ 
where
    member0_.username=? 
    and member0_.age=0 //**

Member 도메인 객체(Probe)에 m1(username)을 넣어주고 그 자체를 검색 조건으로 사용한다. 엔티티를 검색 조건으로 사용해서 쿼리를 날려보니 뭔가 이상한 점이 있다. age가 조건에 0으로 추가되어서 select 쿼리가 발생했다..! 이유는 Member 클래스 필드에 id, username, age가 있기 때문이다. id는 Long이라 null이 들어가 무시를 해버리지만 age는 primitive type인 int이기 때문에 null이 못 들어가 0이 들어가버려 무시를 하지 못한다. 그래서 따로 처리를 해줘야 한다.

Member member = new Member("m1");
ExampleMatcher matcher = ExampleMatcher.matching()
        .withIgnorePaths("age"); //** 추가
Example<Member> ex = Example.of(member,matcher);
List<Member> result = memberRepository.findAll(ex);

assertThat(result.get(0).getUsername()).isEqualTo("m1");

ExampleMatcher로 matching().withIgnorePaths()에 age를 추가해주면 age를 무시한다.

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_ 
where
    member0_.username=?

이렇게 보면 좋은 기능일 수 있는데 이 기능의 최대 단점은 inner join만 되고 outer join이 불가능하다는 점이다. inner join은 다음과 같이 검색 조건이 될 Team의 엔티티를 만들고  setTeam()으로 member와 team을 연관 관계가 맺어질 수 있게 해주면 된다.

Member member = new Member("m1"); // 엔티티 자체가 검색 조건이 된다.
Team team = new Team("teamA");
member.setTeam(team);
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=?

 

장점

  • 동적 쿼리를 편리하게 처리한다.
  • 도메인 객체를 그대로 사용한다.
  • 데이터 저장소를 RDB에서 NOSQL로 변경해도 코드 변경이 없게 추상화 되어 있다.
  • 스프링 데이터 JPA JpaRepository 인터페이스에 이미 포함되어 있다.
@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>
                                    , QueryByExampleExecutor<T> {

 

단점

  • 조인은 가능하지만 내부 조인(INNER JOIN)만 가능하다. 외부 조인(LEFT JOIN)을 지원하지 않는다.
  • 다음과 같은 중첩 제약조건이 안 된다.
    • firstname = ?0 or (firstname =?1 and lastname = ?2)
  • 매칭 조건이 매우 단순하다.
    • 문자는 starts, contains, ends, regex
    • 다른 속성은 정확한 매칭 = 만 지원한다.

 

정리

  • 실무에서 사용하기에는 매칭 조건이 너무 단순하고, LEFT 조인을 지원하지 않는다.
  • 실무에서는 QueryDSL을 사용하자!
반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Spring Data JPA - 네이티브 쿼리
  • Spring Data JPA - Projections
  • Spring Data JPA - Specifications(명세)
  • Spring Data 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
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

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

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
Spring Data JPA - Query By Example
상단으로

티스토리툴바