Last active
August 29, 2015 14:02
-
-
Save luowei/562a272e7c95a988efa4 to your computer and use it in GitHub Desktop.
Jpa动态条件查询,动态构建Specification构建工具类
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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()]))); | |
} | |
}; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//使用 | |
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