1 분 소요

나머지 기능

거의 안쓰는 기능 (알고만 있자.)

Specifications (명세)

책 도메인 주도 설계 (Domain Driven Design)는 Specifications(명세) 라는 개념을 소개 스프링 데이터 JPA는 JPA Criteria를 활용해서 이 개념을 사용할 수 있도록 지원

술어(predicate)

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

명세 기능 사용 방법 JpaSepcificationExecutor인터페이스 상속

1
2
3
4
5
public interface MemberRepository extends JpaRepository<Member, Long>, MemberRepositoryCustom  
        , JpaSpecificationExecutor<Member> { 
        
        ...
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test  
public void specBasic() throws Exception {  
    //given  
    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();  
    //when  
    Specification<Member> spec = MemberSpec.username("m1").and(MemberSpec.teamName("teamA"));  
    List<Member> members = memberRepository.findAll(spec);  
    //then  
    Assertions.assertThat(members.size()).isEqualTo(1);  
}

다음과 같은 테스트 코드를 작성 할 때 Specification을 이용해서 다음과 같이 조건문을 사용하도록 해보자. 그러면 Specification을 구현해 보러 가자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MemberSpec {  
    public static Specification<Member> teamName(final String teamName) {  
        return new Specification<Member>() {  
            @Override  
            public Predicate toPredicate(Root<Member> root, CriteriaQuery<?> query, CriteriaBuilder 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, builder) -> {  
            return builder.equal(root.get("username"), username);  
        };  
    }  
}

진짜 너무 어렵다.. criteria를 이용하여 만들었다.

결과는 잘 나왔다.

  • Specification을 구현하면 명세들을 조립할 수 있음. where(), and(), or(), not()제공
  • findAll()을 보면 회원 이름 명세 (username)와 팀 이름 명세 (teamName)를 and()로 조합해서 검색 조건 으로 사용.

  • 명세를 정의하려면 Specification인터페이스를 구현
  • 명세를 정의할 땐 toPredicate(...)메서드만 구현하면 되는데 JPA Criteria의 Root, CriteriaQuery, CriteriaBuilder클래스를 파라미터 제공
  • 예제에선 편의상 람다 사용

참고 : 실무에서 JPA Critreria 안쓴다! QueryDSL 사용하자.

태그: ,

카테고리:

업데이트:

댓글남기기