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); }