[BAEL-9557] - Migrated the spring-rest-query-language to Java 8 idioms
This commit is contained in:
parent
e31557b2dc
commit
14db73cf02
|
@ -1,10 +1,13 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import org.baeldung.web.util.SearchCriteria;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.baeldung.web.util.SearchCriteria;
|
||||
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
|
||||
public final class MyUserPredicatesBuilder {
|
||||
private final List<SearchCriteria> params;
|
||||
|
@ -23,20 +26,33 @@ public final class MyUserPredicatesBuilder {
|
|||
return null;
|
||||
}
|
||||
|
||||
final List<BooleanExpression> predicates = new ArrayList<>();
|
||||
MyUserPredicate predicate;
|
||||
for (final SearchCriteria param : params) {
|
||||
predicate = new MyUserPredicate(param);
|
||||
final BooleanExpression exp = predicate.getPredicate();
|
||||
if (exp != null) {
|
||||
predicates.add(exp);
|
||||
}
|
||||
final List<BooleanExpression> predicates = params.stream().map(param -> {
|
||||
MyUserPredicate predicate = new MyUserPredicate(param);
|
||||
return predicate.getPredicate();
|
||||
}).filter(predicate -> predicate != null).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
BooleanExpression result = Expressions.asBoolean(true).isTrue();
|
||||
for (BooleanExpression predicate : predicates) {
|
||||
result = result.and(predicate);
|
||||
}
|
||||
|
||||
BooleanExpression result = predicates.get(0);
|
||||
for (int i = 1; i < predicates.size(); i++) {
|
||||
result = result.and(predicates.get(i));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static class BooleanExpressionWrapper {
|
||||
|
||||
private BooleanExpression result;
|
||||
|
||||
public BooleanExpressionWrapper(final BooleanExpression result) {
|
||||
super();
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
public BooleanExpression getResult() {
|
||||
return result;
|
||||
}
|
||||
public void setResult(BooleanExpression result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.baeldung.web.util.SearchCriteria;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
|
@ -10,7 +8,10 @@ import javax.persistence.criteria.CriteriaBuilder;
|
|||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.List;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.baeldung.web.util.SearchCriteria;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public class UserDAO implements IUserDAO {
|
||||
|
@ -25,20 +26,9 @@ public class UserDAO implements IUserDAO {
|
|||
final Root r = query.from(User.class);
|
||||
|
||||
Predicate predicate = builder.conjunction();
|
||||
|
||||
for (final SearchCriteria param : params) {
|
||||
if (param.getOperation().equalsIgnoreCase(">")) {
|
||||
predicate = builder.and(predicate, builder.greaterThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
|
||||
} else if (param.getOperation().equalsIgnoreCase("<")) {
|
||||
predicate = builder.and(predicate, builder.lessThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
|
||||
} else if (param.getOperation().equalsIgnoreCase(":")) {
|
||||
if (r.get(param.getKey()).getJavaType() == String.class) {
|
||||
predicate = builder.and(predicate, builder.like(r.get(param.getKey()), "%" + param.getValue() + "%"));
|
||||
} else {
|
||||
predicate = builder.and(predicate, builder.equal(r.get(param.getKey()), param.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
UserSearchQueryCriteriaConsumer searchConsumer = new UserSearchQueryCriteriaConsumer(predicate, builder, r);
|
||||
params.stream().forEach(searchConsumer);
|
||||
predicate = searchConsumer.getPredicate();
|
||||
query.where(predicate);
|
||||
|
||||
return entityManager.createQuery(query).getResultList();
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
|
||||
import org.baeldung.web.util.SearchCriteria;
|
||||
|
||||
public class UserSearchQueryCriteriaConsumer implements Consumer<SearchCriteria>{
|
||||
|
||||
private Predicate predicate;
|
||||
private CriteriaBuilder builder;
|
||||
private Root r;
|
||||
|
||||
public UserSearchQueryCriteriaConsumer(Predicate predicate, CriteriaBuilder builder, Root r) {
|
||||
super();
|
||||
this.predicate = predicate;
|
||||
this.builder = builder;
|
||||
this.r= r;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(SearchCriteria param) {
|
||||
|
||||
if (param.getOperation().equalsIgnoreCase(">")) {
|
||||
predicate = builder.and(predicate, builder.greaterThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
|
||||
} else if (param.getOperation().equalsIgnoreCase("<")) {
|
||||
predicate = builder.and(predicate, builder.lessThanOrEqualTo(r.get(param.getKey()), param.getValue().toString()));
|
||||
} else if (param.getOperation().equalsIgnoreCase(":")) {
|
||||
if (r.get(param.getKey()).getJavaType() == String.class) {
|
||||
predicate = builder.and(predicate, builder.like(r.get(param.getKey()), "%" + param.getValue() + "%"));
|
||||
} else {
|
||||
predicate = builder.and(predicate, builder.equal(r.get(param.getKey()), param.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Predicate getPredicate() {
|
||||
return predicate;
|
||||
}
|
||||
}
|
|
@ -1,14 +1,15 @@
|
|||
package org.baeldung.persistence.dao;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.baeldung.persistence.model.User;
|
||||
import org.baeldung.web.util.SearchOperation;
|
||||
import org.baeldung.web.util.SpecSearchCriteria;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import org.springframework.data.jpa.domain.Specifications;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class UserSpecificationsBuilder {
|
||||
|
||||
private final List<SpecSearchCriteria> params;
|
||||
|
@ -48,15 +49,19 @@ public final class UserSpecificationsBuilder {
|
|||
if (params.size() == 0)
|
||||
return null;
|
||||
|
||||
Specification<User> result = new UserSpecification(params.get(0));
|
||||
final List<Specification<User>> specs = params.stream()
|
||||
.map(UserSpecification::new)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
Specification<User> result = specs.get(0);
|
||||
|
||||
for (int i = 1; i < params.size(); i++) {
|
||||
result = params.get(i)
|
||||
.isOrPredicate()
|
||||
? Specifications.where(result)
|
||||
.or(new UserSpecification(params.get(i)))
|
||||
.or(specs.get(i))
|
||||
: Specifications.where(result)
|
||||
.and(new UserSpecification(params.get(i)));
|
||||
.and(specs.get(i));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
package org.baeldung.persistence.dao.rsql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specifications;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.ComparisonNode;
|
||||
import cz.jirutka.rsql.parser.ast.LogicalNode;
|
||||
import cz.jirutka.rsql.parser.ast.LogicalOperator;
|
||||
import cz.jirutka.rsql.parser.ast.Node;
|
||||
import org.springframework.data.jpa.domain.Specifications;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class GenericRsqlSpecBuilder<T> {
|
||||
|
||||
|
@ -22,28 +24,23 @@ public class GenericRsqlSpecBuilder<T> {
|
|||
}
|
||||
|
||||
public Specifications<T> createSpecification(final LogicalNode logicalNode) {
|
||||
final List<Specifications<T>> specs = new ArrayList<Specifications<T>>();
|
||||
Specifications<T> temp;
|
||||
for (final Node node : logicalNode.getChildren()) {
|
||||
temp = createSpecification(node);
|
||||
if (temp != null) {
|
||||
specs.add(temp);
|
||||
}
|
||||
}
|
||||
|
||||
Specifications<T> result = specs.get(0);
|
||||
List<Specifications<T>> specs = logicalNode.getChildren()
|
||||
.stream()
|
||||
.map(node -> createSpecification(node))
|
||||
.filter(specifications -> specifications != null)
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
if (logicalNode.getOperator() == LogicalOperator.AND) {
|
||||
for (int i = 1; i < specs.size(); i++) {
|
||||
result = Specifications.where(result).and(specs.get(i));
|
||||
}
|
||||
}
|
||||
Specifications<T> initialSpec = specs.stream().findFirst().get();
|
||||
|
||||
else if (logicalNode.getOperator() == LogicalOperator.OR) {
|
||||
for (int i = 1; i < specs.size(); i++) {
|
||||
result = Specifications.where(result).or(specs.get(i));
|
||||
Specifications<T> result = specs.stream().skip(1).reduce(initialSpec, (firstSpec, secondSpec) -> {
|
||||
if (logicalNode.getOperator() == LogicalOperator.AND) {
|
||||
return Specifications.where(firstSpec).and(secondSpec);
|
||||
} else if (logicalNode.getOperator() == LogicalOperator.OR) {
|
||||
return Specifications.where(firstSpec).or(secondSpec);
|
||||
}
|
||||
}
|
||||
return firstSpec;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package org.baeldung.persistence.dao.rsql;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
import cz.jirutka.rsql.parser.ast.ComparisonOperator;
|
||||
|
||||
public class GenericRsqlSpecification<T> implements Specification<T> {
|
||||
|
||||
|
@ -71,18 +74,22 @@ public class GenericRsqlSpecification<T> implements Specification<T> {
|
|||
// === private
|
||||
|
||||
private List<Object> castArguments(final Root<T> root) {
|
||||
final List<Object> args = new ArrayList<Object>();
|
||||
|
||||
final Class<? extends Object> type = root.get(property).getJavaType();
|
||||
|
||||
for (final String argument : arguments) {
|
||||
final List<Object> args = arguments.stream().map(arg -> {
|
||||
|
||||
Object obj;
|
||||
if (type.equals(Integer.class)) {
|
||||
args.add(Integer.parseInt(argument));
|
||||
obj = Integer.parseInt(arg);
|
||||
} else if (type.equals(Long.class)) {
|
||||
args.add(Long.parseLong(argument));
|
||||
obj = Long.parseLong(arg);
|
||||
} else {
|
||||
args.add(argument);
|
||||
obj = arg;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
|
||||
}).collect(Collectors.toCollection(ArrayList::new));
|
||||
|
||||
return args;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package org.baeldung.web.controller;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -63,7 +64,7 @@ public class UserController {
|
|||
@ResponseBody
|
||||
public List<User> findAll(@RequestParam(value = "search", required = false) String search) {
|
||||
List<SearchCriteria> params = new ArrayList<SearchCriteria>();
|
||||
if (search != null) {
|
||||
if (Optional.ofNullable(search).isPresent()) {
|
||||
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
|
||||
Matcher matcher = pattern.matcher(search + ",");
|
||||
while (matcher.find()) {
|
||||
|
@ -126,7 +127,7 @@ public class UserController {
|
|||
@ResponseBody
|
||||
public Iterable<MyUser> findAllByQuerydsl(@RequestParam(value = "search") String search) {
|
||||
MyUserPredicatesBuilder builder = new MyUserPredicatesBuilder();
|
||||
if (search != null) {
|
||||
if (Optional.ofNullable(search).isPresent()) {
|
||||
Pattern pattern = Pattern.compile("(\\w+?)(:|<|>)(\\w+?),");
|
||||
Matcher matcher = pattern.matcher(search + ",");
|
||||
while (matcher.find()) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.baeldung.web.util;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
|
@ -45,7 +46,7 @@ public class CriteriaParser {
|
|||
Deque<Object> output = new LinkedList<>();
|
||||
Deque<String> stack = new LinkedList<>();
|
||||
|
||||
for (String token : searchParam.split("\\s+")) {
|
||||
Arrays.stream(searchParam.split("\\s+")).forEach(token -> {
|
||||
if (ops.containsKey(token)) {
|
||||
while (!stack.isEmpty() && isHigerPrecedenceOperator(token, stack.peek()))
|
||||
output.push(stack.pop()
|
||||
|
@ -65,7 +66,7 @@ public class CriteriaParser {
|
|||
output.push(new SpecSearchCriteria(matcher.group(1), matcher.group(2), matcher.group(3), matcher.group(4), matcher.group(5)));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
while (!stack.isEmpty())
|
||||
output.push(stack.pop());
|
||||
|
|
Loading…
Reference in New Issue