top.springdatajpa.zujijpa.Specifications Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of zuji-jpa Show documentation
Show all versions of zuji-jpa Show documentation
To solve complex dynamic SQL
package top.springdatajpa.zujijpa;
import lombok.experimental.UtilityClass;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.util.StringUtils;
import top.springdatajpa.zujijpa.annotation.QueryIgnore;
import top.springdatajpa.zujijpa.annotation.QueryOperator;
import top.springdatajpa.zujijpa.enums.Operator;
import top.springdatajpa.zujijpa.utils.EntityUtils;
import top.springdatajpa.zujijpa.wrapper.OperatorWrapper;
import top.springdatajpa.zujijpa.wrapper.SpecificationWrapper;
import javax.persistence.JoinColumn;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
/**
* Specifications query the core tool class
* @author azheng
* @since 2019/5/7
*/
@UtilityClass
public class Specifications {
public static Specification where(Consumer> action) {
return where(true, action);
}
/**
* Specification generate the most core method
* @param isConjunction True is `and` connection, false is `or` connection
* @param action Query code
* @param Main table entity class of query
* @return Specification
*/
public static Specification where(boolean isConjunction, Consumer> action) {
return (Root root, CriteriaQuery> query, CriteriaBuilder builder) -> {
SpecificationWrapper specification = new SpecificationWrapper<>(root, query, builder);
action.accept(specification);
List predicates = specification.getPredicates();
Predicate[] arr = predicates.toArray(new Predicate[predicates.size()]);
return isConjunction?builder.and(arr):builder.or(arr);
};
}
public static Specification conditionOf(Object object) {
return conditionOf(object, e -> {});
}
public static Specification conditionOf(Object object, Consumer> action) {
Map map = EntityUtils.notNullCastToMap(object);
Specification s = where(e -> {
map.forEach((k, v) -> {
OperatorWrapper wrapper = new OperatorWrapper();
wrapper.setSpecWrapper(e);
wrapper.setValue(v);
QueryIgnore ignore = k.getAnnotation(QueryIgnore.class);
QueryOperator query = k.getAnnotation(QueryOperator.class);
JoinColumn joinCol = k.getAnnotation(JoinColumn.class);
if(ignore != null) return;
Operator operator = query != null?query.value(): Operator.EQ;
if(v instanceof Collection){
operator = Operator.IN;
}
if(query != null && StringUtils.hasText(query.fieldName())){
wrapper.setName(getPathName(query.fieldName(), joinCol));
}else{
wrapper.setName(getPathName(k.getName(), joinCol));
}
operator.consumer().accept(wrapper);
});
action.accept(e);
});
return s;
}
private String getPathName(String name, JoinColumn joinCol){
if(joinCol != null && !name.contains(".")){
name = joinCol.name() + "." + name;
}
return name;
}
}