-
JPA 다중 검색, criteriaBuilder카테고리 없음 2022. 10. 24. 17:42반응형
jpa사용해서 멀티 검색 하기 까다롭다.
그럴때 사용하면 좋을 Criteriabuilder
public Page<T> exampleCriteria(JpaSpecificationExecutor<T> executor, final List<Triple<String, String, Object>>criteriaList, Pageable pageable) { Page<T> findResult = executor.findAll(new Specification<T>() { @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) { List<Predicate> stringPredicateList = new ArrayList<Predicate>(); List<Predicate> numPredicateList = new ArrayList<Predicate>(); List<Predicate> pairPredicates = new ArrayList<Predicate>(); for (Triple<String, String, Object> criteriaItem : criteriaList) { if(criteriaItem.getRight() instanceof String) { String fieldName = criteriaItem.getLeft(); String operation = criteriaItem.getMiddle(); String keywordEq = (String) criteriaItem.getRight(); String keyword = ((String) criteriaItem.getRight()).replace("%","\\%").replace("_","\\_"); if ("eq".equals(operation)) { stringPredicateList.add(criteriaBuilder.and(criteriaBuilder.equal(root.get(fieldName), keywordEq))); }else if("like".equals(operation)){ stringPredicateList.add(criteriaBuilder.and(criteriaBuilder.like(root.get(fieldName).as(String.class), "%"+keyword +"%"))); }else if("forward_match".equals(operation)){ stringPredicateList.add(criteriaBuilder.and(criteriaBuilder.like(root.get(fieldName).as(String.class), keyword +"%"))); }else if("backward_match".equals(operation)){ stringPredicateList.add(criteriaBuilder.and(criteriaBuilder.like(root.get(fieldName).as(String.class), "%"+keyword))); } }else if(criteriaItem.getRight() instanceof List) { String fieldName = criteriaItem.getLeft(); String operation = criteriaItem.getMiddle(); @SuppressWarnings("unchecked") List<Double> keyword = (List<Double>) criteriaItem.getRight(); if ("greater".equals(operation)) { numPredicateList.add(criteriaBuilder.and(criteriaBuilder.greaterThanOrEqualTo(root.get(fieldName),keyword.get(0)))); }else if("less".equals(operation)){ numPredicateList.add(criteriaBuilder.and(criteriaBuilder.lessThanOrEqualTo(root.get(fieldName),keyword.get(0)))); }else if("between".equals(operation)){ numPredicateList.add(criteriaBuilder.and(criteriaBuilder.between(root.get(fieldName),keyword.get(0),keyword.get(1)))); } }else if(criteriaItem.getRight() == null) { pairPredicates.add(criteriaBuilder.equal(root.get(criteriaItem.getLeft()), criteriaItem.getMiddle())); } } Predicate pairPredicate = criteriaBuilder.and(pairPredicates.toArray(new Predicate[pairPredicates.size()])); if (stringPredicateList.size() > 0 && numPredicateList.size() == 0) { Predicate triplePredicateString = criteriaBuilder.or(stringPredicateList.toArray(new Predicate[stringPredicateList.size()])); return criteriaBuilder.and(criteriaBuilder.and(pairPredicate), triplePredicateString); }else if(stringPredicateList.size() > 0 && numPredicateList.size() > 0) { Predicate triplePredicateString = criteriaBuilder.or(stringPredicateList.toArray(new Predicate[stringPredicateList.size()])); Predicate triplePredicateNum = criteriaBuilder.or(numPredicateList.toArray(new Predicate[numPredicateList.size()])); return criteriaBuilder.and(criteriaBuilder.and(pairPredicate), triplePredicateString,triplePredicateNum); }else if(stringPredicateList.size() == 0 && numPredicateList.size() > 0) { Predicate triplePredicateNum = criteriaBuilder.or(numPredicateList.toArray(new Predicate[numPredicateList.size()])); return criteriaBuilder.and(criteriaBuilder.and(pairPredicate), triplePredicateNum); }else { return criteriaBuilder.and(pairPredicate); } } },pageable); return findResult; }
or 조건과 and 조건을 조작하려면 criteriaBuilder.or 이부분을 and 로 변경해준다.
Predicate triplePredicateString = criteriaBuilder.or(stringPredicateList.toArray(new Predicate[stringPredicateList.size()]));
combining JPA and/or criteria predicates
참고하면 좋을 사이트 : https://www.baeldung.com/jpa-and-or-criteria-predicates
반응형