private Specification<VO> createSpecification(final Map<String, String> filterData) throws Exception {
final Map<String, String> filterOperators = new HashMap<>();
final Map<String, Object> filterParams = new HashMap();
extractFilterOperatorsAndParams(filterData, filterOperators, filterParams);
Specification<VO> spec = new Specification<VO>() {
@Override
public Predicate toPredicate(Root<VO> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
List<Predicate> predicates = new ArrayList<>();
for (Map.Entry<String, Object> entry : filterParams.entrySet()) {
//get path to leaf node
Path<?> path = root;
if(ATTR_JSON_TYPE.equals(entry.getKey())) {
predicates.add(root.type().in(entry.getValue()));
}
else {
for (String pk : entry.getKey().split("\\.")) {
path = path.get(pk);
}
// create predicate
predicates.add(getFieldPredicate(cb, path, filterOperators.get(entry.getKey()), entry.getValue()));
}
}
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}
private Predicate getFieldPredicate(CriteriaBuilder cb, Path<?> path, String operator, Object value) {
if (OP_EQUAL.equals(operator)) {
if (value instanceof Collection) {
return path.in((Collection) value);
}
return cb.equal(path, value);
}
else if (OP_NOT.equals(operator)) {
if (value instanceof Collection) {
List<Predicate> predicates = new ArrayList<>();
for (Object val : (Collection) value) {
predicates.add(cb.notEqual(path, val));
}
return cb.and(predicates.toArray(new Predicate[predicates.size()]));
}
else {
return cb.notEqual(path, value);
}
}
else if (OP_LIKE.equals(operator)) {
return cb.like(path.as(String.class), value.toString());
}
else if (OP_NOTLIKE.equals(operator)) {
return cb.notLike(path.as(String.class), value.toString());
}
else if (OP_BETWEEN.equals(operator)) {
Iterator<?> iter = ((Collection<?>) value).iterator();
Object val1 = iter.next(), val2 = iter.next();
if (val1 instanceof Byte) {
return cb.between(path.as(Byte.class), (Byte) val1, (Byte) val2);
}
else if (val1 instanceof Short) {
return cb.between(path.as(Short.class), (Short) val1, (Short) val2);
}
else if (val1 instanceof Integer) {
return cb.between(path.as(Integer.class), (Integer) val1, (Integer) val2);
}
else if (val1 instanceof Long) {
return cb.between(path.as(Long.class), (Long) val1, (Long) val2);
}
else if (val1 instanceof Float) {
return cb.between(path.as(Float.class), (Float) val1, (Float) val2);
}
else if (val1 instanceof Double) {
return cb.between(path.as(Double.class), (Double) val1, (Double) val2);
}
else {
return null;
}
} else {
try {
Method m = null;
if (OP_GT.equals(operator)) {
m = cb.getClass().getMethod("greaterThan", Expression.class, Comparable.class);
}
else if (OP_GE.equals(operator)) {
m = cb.getClass().getMethod("greaterThanOrEqualTo", Expression.class, Comparable.class);
}
else if (OP_LT.equals(operator)) {
m = cb.getClass().getMethod("lessThan", Expression.class, Comparable.class);
}
else if (OP_LE.equals(operator)) {
m = cb.getClass().getMethod("lessThanOrEqualTo", Expression.class, Comparable.class);
}
if (m != null) {
if (value instanceof Byte) {
return (Predicate) m.invoke(cb, path.as(Byte.class), (Byte) value);
}
else if (value instanceof Short) {
return (Predicate) m.invoke(cb, path.as(Short.class), (Short) value);
}
else if (value instanceof Integer) {
return (Predicate) m.invoke(cb, path.as(Integer.class), (Integer) value);
}
else if (value instanceof Long) {
return (Predicate) m.invoke(cb, path.as(Long.class), (Long) value);
}
else if (value instanceof Float) {
return (Predicate) m.invoke(cb, path.as(Float.class), (Float) value);
}
else if (value instanceof Double) {
return (Predicate) m.invoke(cb, path.as(Double.class), (Double) value);
}
}
}
catch (Exception e) {
throw new RuntimeException(e);
}
return null;
}
}
};
return spec;
}
Reference:
http://docs.spring.io/spring-data/data-jpa/docs/1.0.x/api/org/springframework/data/jpa/domain/Specification.html
http://docs.oracle.com/javaee/5/api/javax/persistence/package-summary.html
http://wenku.baidu.com/view/190e385c3b3567ec102d8a40.html?re=view