Skip to content

Instantly share code, notes, and snippets.

@luowei
Last active August 29, 2015 14:02
Show Gist options
  • Save luowei/562a272e7c95a988efa4 to your computer and use it in GitHub Desktop.
Save luowei/562a272e7c95a988efa4 to your computer and use it in GitHub Desktop.
Jpa动态条件查询,动态构建Specification构建工具类
package com.xxxxx.trade.util;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.GenericConversionService;
import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static com.xxxxx.trade.util.QueryUtils.*;
/**
* Created with IntelliJ IDEA.
* User: luowei
* Date: 12-11-18
* Time: 下午5:41
* To change this template use File | Settings | File Templates.
*/
public abstract class DynamicSpecifications {
private static final ConversionService conversionService = new GenericConversionService();
public static <T> Specification<T> byPropertyFilter(final Collection<PropertyFilter> filterList, final Class<T> clazz) {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> tRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<Predicate>();
// query = cb.createQuery(clazz);
// tRoot = query.from(clazz);
for (PropertyFilter filter : filterList) {
Path expression = tRoot.get(filter.getName());
Class attributeClass = expression.getJavaType();
if (!attributeClass.equals(String.class) && filter.getValue() instanceof String
&& conversionService.canConvert(String.class, attributeClass)) {
filter.setValue(conversionService.convert(filter.getValue(), attributeClass));
}
switch (filter.getType()) {
case EQ:
predicates.add(cb.equal(expression, filter.getValue()));
break;
case LIKE:
predicates.add(cb.like(expression, "%" + filter.getValue() + "%"));
break;
case GT:
predicates.add(cb.greaterThan(expression, (Comparable) filter.getValue()));
break;
case GE:
predicates.add(cb.greaterThanOrEqualTo(expression, (Comparable) filter.getValue()));
break;
case LT:
predicates.add(cb.lessThan(expression, (Comparable) filter.getValue()));
break;
case LE:
predicates.add(cb.lessThanOrEqualTo(expression, (Comparable) filter.getValue()));
break;
}
}
if (predicates.size() > 0) {
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}
return cb.conjunction();
// return cb.createQuery(clazz).where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}
};
}
public static <T> Specification<T> byPropertyFilter2(final Collection<PropertyFilter> filterList, final Class<T> clazz) {
return new Specification<T>() {
@Override
public Predicate toPredicate(Root<T> tRoot, CriteriaQuery<?> query, CriteriaBuilder cb) {
Predicate where = cb.conjunction();
query = cb.createQuery(clazz);
tRoot = query.from(clazz);
for (PropertyFilter filter : filterList) {
Path expression = tRoot.get(filter.getName());
Class attributeClass = expression.getJavaType();
if (!attributeClass.equals(String.class) && filter.getValue() instanceof String
&& conversionService.canConvert(String.class, attributeClass)) {
filter.setValue(conversionService.convert(filter.getValue(), attributeClass));
}
switch (filter.getType()) {
case EQ:
where = cb.and(where, cb.equal(expression, filter.getValue()));
break;
case LIKE:
where = cb.and(where, (cb.like(expression, "%" + filter.getValue() + "%")));
break;
case GT:
where = cb.and(where, cb.greaterThan(expression, (Comparable) filter.getValue()));
break;
case GE:
where = cb.and(where, cb.greaterThanOrEqualTo(expression, (Comparable) filter.getValue()));
break;
case LT:
where = cb.and(where, cb.lessThan(expression, (Comparable) filter.getValue()));
break;
case LE:
where = cb.and(where, cb.lessThanOrEqualTo(expression, (Comparable) filter.getValue()));
break;
}
}
// query.where(where);
return where;
// return cb.createQuery(clazz).where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
}
};
}
}
package com.xxxxx.trade.util;
import org.springframework.data.domain.Sort;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @className:QueryUtils
* @classDescription:
* @author:luowei
* @createTime:12-11-12
*/
public abstract class QueryUtils {
public static String DEFAULT_ORDER = "id: asc";
public static Integer DEFAULT_PAGESIZE = 20;
/**
* 获得排序条件
*
* @param orderMap 排序字段map
* @return
*/
public static Sort sortByOrderFiled(Map<String, Sort.Direction> orderMap) {
if (orderMap == null) return null;
List<Sort.Order> orderList = new ArrayList<Sort.Order>();
for (Map.Entry<String, Sort.Direction> entry : orderMap.entrySet()) {
orderList.add(new Sort.Order(entry.getValue(), entry.getKey()));
}
return new Sort(orderList);
}
/**
* 根据条件查询,多条件只支持and,返回分页对象
*
* @param pfList
* @return
*/
public static String getWheres(List<PropertyFilter> pfList) {
String where = null;
Map<String, Object> params = new HashMap<String, Object>();
// count用来计数条件个数
int count = 0;
StringBuilder sb = new StringBuilder();
if (pfList != null && !pfList.isEmpty()) {
// sb.append(" where ");
for (PropertyFilter pf : pfList) {
if (pf.isNotBlankOfThisPropertyValue()) {
count++;
// count大于1表示至少有两个条件
if (count > 1) {
sb.append(" and ");
}
// sb.append(pf.getName());
sb.append("o.").append(pf.getName());
switch (pf.getType()) {
case EQ:
sb.append(" = ");
break;
case GT:
sb.append(" > ");
break;
case GE:
sb.append(" >= ");
break;
case LT:
sb.append(" < ");
break;
case LE:
sb.append(" <= ");
break;
case LIKE:
sb.append(" like ");
break;
}
if (pf.getType().equals(Type.LIKE)) {
sb.append(" %" + pf.getValue() + "% ");
} else {
sb.append(pf.getValue());
}
}
}
where = sb.toString();
}
return where;
}
/**
* @className:PropertyFilter
* @classDescription:
* @author:luowei
* @createTime:12-10-12
*/
public static class PropertyFilter {
private String name; // 条件名称
private Object value; // 条件值
private Type type; // 查询类型
public PropertyFilter() {
}
public PropertyFilter(String name, Object value) {
this.name = name;
this.value = value;
this.type = Type.EQ;
}
public PropertyFilter(String name, Object value, Type type) {
this.name = name;
this.value = value;
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
/**
* 返回当前条件参数是否有效,字符串不为空,非字符串的不为null
*
* @return
*/
public boolean isNotBlankOfThisPropertyValue() {
if (value instanceof String) {
String str = (String) value;
return (null != str && !str.trim().isEmpty());
} else {
return (null != value);
}
}
/**
* 添加属性
*
* @param name
* @param value
* @return
*/
public PropertyFilter add(String name, String value, Type type) {
if (name != null && name != "") {
if (type == null) {
type = Type.EQ;
}
return new PropertyFilter(name, value, type);
} else return this;
}
}
/**
* @className:Type
* @classDescription:
* @author:luowei
* @createTime:12-1--12
*/
public static enum Type {
EQ, GT, GE, LT, LE, LIKE
}
}
//使用
public List<ExpDetailCount> findExpWithCriteria(
ExpDetailCount expDetailCount, CommonDto commonDto,
YearMonthDto yearMonthDto) {
//获得查询条件
final List<QueryUtils.PropertyFilter> filterList = getdetailQueryProps(expDetailCount, commonDto);
//把起始年、结束年,起始月,结束月条件也加进来
filterList.addAll(commonService.getYearMonthQueryProps(yearMonthDto));
//构造查询规范
Specification<ExpDetailCount> spec = DynamicSpecifications.<ExpDetailCount>byPropertyFilter(filterList, ExpDetailCount.class);
//查询获得列表结果
List<ExpDetailCount> detailCountList = expDetailCountDao.findAll(spec);
return detailCountList;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment