Specifications (명세)

박찬우·2024년 1월 11일

스프링 데이터 JPA

목록 보기
15/18

술어(predicate)

  • 실무 사용 X
  • 참 또는 거짓으로 평가
  • AND OR 같은 연산자로 조합해서 다양한 검색조건을 쉽게 생성(컴포지트 패턴)
  • 예) 검색 조건 하나하나
  • 스프링 데이터 JPA는 org.springframework.data.jpa.domain.Specification 클래스로 정의
  • Specification 을 구현하면 명세들을 조립할 수 있음. where() , and() , or() , not() 제공
  • findAll 을 보면 회원 이름 명세( username )와 팀 이름 명세( teamName )를 and 로 조합해서 검색 조건으로 사용
public interface MemberRepository extends JpaRepository<Member, Long>,  JpaSpecificationExecutor<Member> {
}
public class MemberSpec {
    public static Specification<Member> teamName(final String teamName) {
        return (Specification<Member>) (root, query, builder) -> {
            if (StringUtils.isEmpty(teamName)) {
                return null;
            }

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

    public static Specification<Member> username(final String username) {
        return (Specification<Member>) (root, query, builder) ->
                builder.equal(root.get("username"), username);
    }

}
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);
  • 명세를 정의하려면 Specification 인터페이스를 구현
  • 명세를 정의할 때는 toPredicate(...) 메서드만 구현하면 되는데 JPA Criteria의 Root , CriteriaQuery , CriteriaBuilder 클래스를 파라미터 제공
profile
진짜 개발자가 되어보자

0개의 댓글