public interface MemberRepository extends JpaSpecificationExecutor<Member> {
}
public interface JpaSpecificationExecutor<T> {
Optional<T> findOne(@Nullable Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);
}
class MemberRepositoryTest {
@Test
public void specBasic() throws Exception {
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);
}
}
public class MemberSpec {
public static Specification<Member> teamName(final String teamName) {
// predicate를 만든다.
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);
}
}