JPAのCriteriaBuilderのconjunctionとdisjunctionについて
SpringのSpecificationなどで、動的なJPQLをCriteriaBuilderで、Predicateを組み立てるときに使う conjunction と disjunction 、毎回どっちがどっちか忘れるのでメモ。
conjunction
AND条件の起点。SQLに解釈されると 1 = 1 になる。
(root, query, cb) -> {
var predicate = cb.conjunction();
predicate = cb.and(
predicate,
cb.equal(root.get(EntityClass_.id), entityId)
);
}
disjunction
OR条件の起点。SQLに解釈されると 0 = 1 になる。
(root, query, cb) -> {
var predicate = cb.disjunction();
predicate = cb.or(
predicate,
cb.like(root.get(EntityClass_.name), "%" + entityName + "%")
);
}
振り返り
入力された値に応じて検索条件を組み立てる場合、CriteriaBuilderのメソッドに渡すPredicateが null だと、実行時にNullPointerExceptionが発生するので、未入力なら conjunction や disjunction を使うようにすると安全。
また、PredicateのListやStreamを用意して、Stream#reduceを使うと、 cb.and や cb.or の呼び出しを減らせる。
// AND条件の場合 (root, query, cb) -> { var predicates = new ArrayList<Predicate>(); predicates.add(...); return predicates.stream().reduce(cb.conjunction(), cb::and); } // OR条件の場合 (root, query, cb) -> { return Stream.of( ... ) .reduce(cb.disjunction(), cb::or); }