Spring Data JPA で遊んでみる 〜その9〜

昨日のSpecificationの続きでSpecificationを複数組み合わせて使う際に便利な、Specificationsというヘルパークラスが用意されている。

public class Specifications<T> implements Specification<T> {
  private final Specification<T> spec;
  private Specifications(Specification<T> spec) {...}
  public static <T> Specifications<T> where(Specification<T> spec) {...}
  public Specifications<T> and(final Specification<T> other) {...}
  public Specifications<T> or(final Specification<T> other) {...}
  public static <T> Specifications<T> not(final Specification<T> spec) {...}
  public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {...}
}

幾つかメソッドが定義されていますがwhereを基点としてandとかorとかでつなげていく感じ。

例えば2つSpecがあるとして

public class EmpSpecifications {
    public static Specification<Emp> idLessThanOrEqualTo(final Long id) {
        return new Specification<Emp>() {
            @Override
            public Predicate toPredicate(Root<Emp> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.lessThanOrEqualTo(root.get(Emp_.id), id);
            }
        };
    }

    public static Specification<Emp> hasDept(final Dept dept) {
        return new Specification<Emp>() {
            @Override
            public Predicate toPredicate(Root<Emp> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.equal(root.get(Emp_.dept), dept);
            }
        };
    }
}

これを組み合わせて使う場合は

List<Emp> emps = repository.findAll(where(idLessThanOrEqualTo(9L)).and(hasDept(Dept.of(1L))));

とかいうふうに使えます。

サンプルこのへん。
https://github.com/yamkazu/springdata-jpa-example/tree/complexspec