|  | @ -0,0 +1,304 @@
 | 
												
													
														
															|  | 
 |  | package com.yihu.jw.mysql.query;
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | import javafx.util.Pair;
 | 
												
													
														
															|  | 
 |  | import org.hibernate.Criteria;
 | 
												
													
														
															|  | 
 |  | import org.hibernate.Session;
 | 
												
													
														
															|  | 
 |  | import org.hibernate.criterion.*;
 | 
												
													
														
															|  | 
 |  | import org.hibernate.metadata.ClassMetadata;
 | 
												
													
														
															|  | 
 |  | import org.springframework.util.StringUtils;
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | import java.lang.reflect.Field;
 | 
												
													
														
															|  | 
 |  | import java.util.ArrayList;
 | 
												
													
														
															|  | 
 |  | import java.util.HashMap;
 | 
												
													
														
															|  | 
 |  | import java.util.List;
 | 
												
													
														
															|  | 
 |  | import java.util.Map;
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | /**
 | 
												
													
														
															|  | 
 |  |  * URL 查询串解析器。
 | 
												
													
														
															|  | 
 |  |  *
 | 
												
													
														
															|  | 
 |  |  * @author lincl
 | 
												
													
														
															|  | 
 |  |  * @author Sand
 | 
												
													
														
															|  | 
 |  |  * @version 1.0
 | 
												
													
														
															|  | 
 |  |  * @created 2016.02.05 10:17
 | 
												
													
														
															|  | 
 |  |  */
 | 
												
													
														
															|  | 
 |  | public class URLHqlQueryParser<T> {
 | 
												
													
														
															|  | 
 |  |     private String fields;
 | 
												
													
														
															|  | 
 |  |     private String filters;
 | 
												
													
														
															|  | 
 |  |     private String orders;
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     Session session;
 | 
												
													
														
															|  | 
 |  |     Class<T> entityCls;
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     public URLHqlQueryParser(String fields, String filters, String orders) {
 | 
												
													
														
															|  | 
 |  |         this.fields = fields;
 | 
												
													
														
															|  | 
 |  |         this.filters = filters;
 | 
												
													
														
															|  | 
 |  |         this.orders = orders;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     public URLHqlQueryParser(String filters){
 | 
												
													
														
															|  | 
 |  |         this.filters = filters;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     public URLHqlQueryParser setSession(Session session) {
 | 
												
													
														
															|  | 
 |  |         this.session = session;
 | 
												
													
														
															|  | 
 |  |         return this;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     public URLHqlQueryParser setEntityClass(Class<T> cls) {
 | 
												
													
														
															|  | 
 |  |         this.entityCls = cls;
 | 
												
													
														
															|  | 
 |  |         return this;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     /**
 | 
												
													
														
															|  | 
 |  |      * 生成搜索语句.
 | 
												
													
														
															|  | 
 |  |      *
 | 
												
													
														
															|  | 
 |  |      * @return
 | 
												
													
														
															|  | 
 |  |      */
 | 
												
													
														
															|  | 
 |  |     public Criteria makeCriteriaQuery() {
 | 
												
													
														
															|  | 
 |  |         Criteria criteria = session.createCriteria(entityCls);
 | 
												
													
														
															|  | 
 |  |         ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(entityCls);
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | //        makeSelection(criteria, classMetadata);
 | 
												
													
														
															|  | 
 |  |         makeOrderBy(criteria, classMetadata);
 | 
												
													
														
															|  | 
 |  |         makeWhere(criteria, classMetadata);
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |         return criteria;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     /**
 | 
												
													
														
															|  | 
 |  |      * 生成count语句。
 | 
												
													
														
															|  | 
 |  |      *
 | 
												
													
														
															|  | 
 |  |      * @return
 | 
												
													
														
															|  | 
 |  |      */
 | 
												
													
														
															|  | 
 |  |     public Criteria makeCriteriaCountQuery() {
 | 
												
													
														
															|  | 
 |  |         Criteria criteria = session.createCriteria(entityCls);
 | 
												
													
														
															|  | 
 |  |         ClassMetadata classMetadata = session.getSessionFactory().getClassMetadata(entityCls);
 | 
												
													
														
															|  | 
 |  |         criteria.setProjection(Projections.rowCount());
 | 
												
													
														
															|  | 
 |  |         makeWhere(criteria, classMetadata);
 | 
												
													
														
															|  | 
 |  |         return criteria;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     /**
 | 
												
													
														
															|  | 
 |  |      * 生成返回值字段。
 | 
												
													
														
															|  | 
 |  |      *
 | 
												
													
														
															|  | 
 |  |      * @param criteria
 | 
												
													
														
															|  | 
 |  |      * @param classMetadata
 | 
												
													
														
															|  | 
 |  |      */
 | 
												
													
														
															|  | 
 |  |     private void makeSelection(Criteria criteria, ClassMetadata classMetadata) {
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     /**
 | 
												
													
														
															|  | 
 |  |      * +code 以code字段进行升序排序
 | 
												
													
														
															|  | 
 |  |      * -code 以code字段进行降序排序
 | 
												
													
														
															|  | 
 |  |      * 生成排序字段。
 | 
												
													
														
															|  | 
 |  |      *
 | 
												
													
														
															|  | 
 |  |      * @param criteria
 | 
												
													
														
															|  | 
 |  |      * @param classMetadata
 | 
												
													
														
															|  | 
 |  |      */
 | 
												
													
														
															|  | 
 |  |     private void makeOrderBy(Criteria criteria, ClassMetadata classMetadata) {
 | 
												
													
														
															|  | 
 |  |         if (!StringUtils.isEmpty(orders)) {
 | 
												
													
														
															|  | 
 |  |             String[] orderArray = orders.split(",");
 | 
												
													
														
															|  | 
 |  |             for(String elem : orderArray){
 | 
												
													
														
															|  | 
 |  | //                try {
 | 
												
													
														
															|  | 
 |  | //                    classMetadata.getPropertyType(elem);
 | 
												
													
														
															|  | 
 |  | //                }catch (Exception e){
 | 
												
													
														
															|  | 
 |  | //                    throw new IllegalArgumentException("the property not found!");
 | 
												
													
														
															|  | 
 |  | //                }
 | 
												
													
														
															|  | 
 |  |                 criteria = elem.startsWith("+") ?
 | 
												
													
														
															|  | 
 |  |                         criteria.addOrder(Order.asc(elem.substring(1)))
 | 
												
													
														
															|  | 
 |  |                         : criteria.addOrder(Order.desc(elem.substring(1)));
 | 
												
													
														
															|  | 
 |  |             }
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     /**
 | 
												
													
														
															|  | 
 |  |      * like:使用"?"来表示,如:name?'%医'
 | 
												
													
														
															|  | 
 |  |      * not in:使用"<>"来表示并用","逗号对值进行分隔,如:status=2,3,4,5
 | 
												
													
														
															|  | 
 |  |      * in:使用"="来表示并用","逗号对值进行分隔,如:status=2,3,4,5
 | 
												
													
														
															|  | 
 |  |      * =:使用"="来表示,如:status=2
 | 
												
													
														
															|  | 
 |  |      * >=:使用大于号和大于等于语法,如:createDate>2012
 | 
												
													
														
															|  | 
 |  |      * <=:使用小于号和小于等于语法,如:createDate<=2015
 | 
												
													
														
															|  | 
 |  |      * 分组:在条件后面加上空格,并设置分组号,如:createDate>2012 g1,具有相同组名的条件将使用or连接
 | 
												
													
														
															|  | 
 |  |      * 多条件组合:使用";"来分隔
 | 
												
													
														
															|  | 
 |  |      * <p>
 | 
												
													
														
															|  | 
 |  |      * 生成 where 条件。
 | 
												
													
														
															|  | 
 |  |      *
 | 
												
													
														
															|  | 
 |  |      * @param criteria
 | 
												
													
														
															|  | 
 |  |      * @param classMetadata
 | 
												
													
														
															|  | 
 |  |      */
 | 
												
													
														
															|  | 
 |  |     private void makeWhere(Criteria criteria, ClassMetadata classMetadata) {
 | 
												
													
														
															|  | 
 |  |         if (StringUtils.isEmpty(filters)) return;
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |         Map<String, List<Criterion>> criterionMap = new HashMap<>();
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |         String[] filterArray = filters.split(";");
 | 
												
													
														
															|  | 
 |  |         List<Criterion> groupCriterion = new ArrayList<>();
 | 
												
													
														
															|  | 
 |  |         for (int i = 0; i < filterArray.length; ++i) {
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |             String[] tokens = filterArray[i].split(" ");
 | 
												
													
														
															|  | 
 |  |             if (tokens.length > 2){
 | 
												
													
														
															|  | 
 |  |                 for(int j=1; j<tokens.length; j++){
 | 
												
													
														
															|  | 
 |  |                     if(j==tokens.length-1)
 | 
												
													
														
															|  | 
 |  |                         tokens[1] = tokens[j];
 | 
												
													
														
															|  | 
 |  |                     else
 | 
												
													
														
															|  | 
 |  |                         tokens[0] += " " + tokens[j] ;
 | 
												
													
														
															|  | 
 |  |                 }
 | 
												
													
														
															|  | 
 |  |             }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | //            if (tokens.length > 2) throw new IllegalArgumentException("无效过滤参数");
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |             String group = null;
 | 
												
													
														
															|  | 
 |  |             if (tokens.length >= 2) group = tokens[1];
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |             Criterion criterion = splitFilter(tokens[0], classMetadata);
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |             if (group == null)
 | 
												
													
														
															|  | 
 |  |                 group = Integer.toString(i);
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |             criterionMap.put(group,
 | 
												
													
														
															|  | 
 |  |                     makeGroupCriterion(criterionMap.get(group), criterion));
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         addWhere(criteria, criterionMap);
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private void addWhere(Criteria criteria, Map<String, List<Criterion>> criterionMap) {
 | 
												
													
														
															|  | 
 |  |         List<Criterion> ls;
 | 
												
													
														
															|  | 
 |  |         for (String group : criterionMap.keySet()){
 | 
												
													
														
															|  | 
 |  |             ls = criterionMap.get(group);
 | 
												
													
														
															|  | 
 |  |             if(ls.size()>1)
 | 
												
													
														
															|  | 
 |  |                 criteria.add(
 | 
												
													
														
															|  | 
 |  |                         Restrictions.or(ls.toArray(new Criterion[ls.size()]))
 | 
												
													
														
															|  | 
 |  |                 );
 | 
												
													
														
															|  | 
 |  |             else
 | 
												
													
														
															|  | 
 |  |                 criteria.add(
 | 
												
													
														
															|  | 
 |  |                         Restrictions.and(ls.toArray(new Criterion[ls.size()]))
 | 
												
													
														
															|  | 
 |  |                 );
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     protected List<Criterion> makeGroupCriterion(List<Criterion> ls, Criterion criterion){
 | 
												
													
														
															|  | 
 |  |         (ls = ls == null ? new ArrayList<>() : ls)
 | 
												
													
														
															|  | 
 |  |                 .add(criterion);
 | 
												
													
														
															|  | 
 |  |         return ls;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     protected Criterion splitFilter(String filter, ClassMetadata classMetadata) {
 | 
												
													
														
															|  | 
 |  |         Criterion criterion = null;
 | 
												
													
														
															|  | 
 |  |         if (filter.contains("?")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, "[?]", classMetadata);
 | 
												
													
														
															|  | 
 |  |             criterion = pair.getKey().like("%"+pair.getValue()+"%");
 | 
												
													
														
															|  | 
 |  |         } else if (filter.contains("<>")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, "<>", classMetadata);
 | 
												
													
														
															|  | 
 |  |             if (pair.getValue().getClass().isArray()) {
 | 
												
													
														
															|  | 
 |  |                 criterion = pair.getKey().in((Object[])pair.getValue());
 | 
												
													
														
															|  | 
 |  |             } else {
 | 
												
													
														
															|  | 
 |  |                 criterion = pair.getKey().eq(pair.getValue());
 | 
												
													
														
															|  | 
 |  |             }
 | 
												
													
														
															|  | 
 |  |             criterion = Restrictions.not(criterion);
 | 
												
													
														
															|  | 
 |  |         }  else if (filter.contains(">=")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, ">=", classMetadata);
 | 
												
													
														
															|  | 
 |  |             criterion = pair.getKey().ge(pair.getValue());
 | 
												
													
														
															|  | 
 |  |         } else if (filter.contains(">")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, ">", classMetadata);
 | 
												
													
														
															|  | 
 |  |             //todo:  转成对应类型
 | 
												
													
														
															|  | 
 |  |             criterion = pair.getKey().gt(pair.getValue());
 | 
												
													
														
															|  | 
 |  |         } else if (filter.contains("<=")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, "<=", classMetadata);
 | 
												
													
														
															|  | 
 |  |             criterion = pair.getKey().le(pair.getValue());
 | 
												
													
														
															|  | 
 |  |         } else if (filter.contains("<")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, "<", classMetadata);
 | 
												
													
														
															|  | 
 |  |             criterion = pair.getKey().lt(pair.getValue());
 | 
												
													
														
															|  | 
 |  |         } else if (filter.contains("=")) {
 | 
												
													
														
															|  | 
 |  |             Pair<Property, Object> pair = getPair(filter, "=", classMetadata);
 | 
												
													
														
															|  | 
 |  |             if (pair.getValue().getClass().isArray()) {
 | 
												
													
														
															|  | 
 |  |                 criterion = pair.getKey().in((Object[])pair.getValue());
 | 
												
													
														
															|  | 
 |  |             } else {
 | 
												
													
														
															|  | 
 |  |                 criterion = pair.getKey().eq(pair.getValue());
 | 
												
													
														
															|  | 
 |  |             }
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         return criterion;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     protected Pair<Property, Object> getPair(String filter, String splitter, ClassMetadata classMetadata) throws IllegalArgumentException {
 | 
												
													
														
															|  | 
 |  |         String[] tokens = filter.split(splitter);
 | 
												
													
														
															|  | 
 |  |         String valStr = tokens[1];
 | 
												
													
														
															|  | 
 |  |         Object val = tokens[1];
 | 
												
													
														
															|  | 
 |  |         try {
 | 
												
													
														
															|  | 
 |  |             if((splitter.equals("=") || splitter.equals("<>")) && valStr.contains(",")){
 | 
												
													
														
															|  | 
 |  |                 val = formatVal(tokens[0], valStr, true);
 | 
												
													
														
															|  | 
 |  |             }
 | 
												
													
														
															|  | 
 |  |             else if(!splitter.equals("[?]")){
 | 
												
													
														
															|  | 
 |  |                 val = formatVal(tokens[0], valStr, false);
 | 
												
													
														
															|  | 
 |  |             }
 | 
												
													
														
															|  | 
 |  |         } catch (NoSuchFieldException e) {
 | 
												
													
														
															|  | 
 |  |             e.printStackTrace();
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         return new Pair(Property.forName(tokens[0]), val);
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private Object formatVal(String fileName, String valStr, boolean isArr) throws NoSuchFieldException {
 | 
												
													
														
															|  | 
 |  |         Object val = "";
 | 
												
													
														
															|  | 
 |  |         if(isLong(fileName)){
 | 
												
													
														
															|  | 
 |  |             if(isArr){
 | 
												
													
														
															|  | 
 |  |                 val = strToLongArr(valStr);
 | 
												
													
														
															|  | 
 |  |             }else
 | 
												
													
														
															|  | 
 |  |                 val = Long.parseLong(valStr);
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |         }else if(isInteger(fileName)){
 | 
												
													
														
															|  | 
 |  |             if(isArr){
 | 
												
													
														
															|  | 
 |  |                 val = strToIntArr(valStr);
 | 
												
													
														
															|  | 
 |  |             }else
 | 
												
													
														
															|  | 
 |  |                 val = Integer.parseInt(valStr);
 | 
												
													
														
															|  | 
 |  |         }else {
 | 
												
													
														
															|  | 
 |  |             if(isArr)
 | 
												
													
														
															|  | 
 |  |                 val = valStr.split(",");
 | 
												
													
														
															|  | 
 |  |             else
 | 
												
													
														
															|  | 
 |  |                 val = valStr;
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         return val;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private Long[] strToLongArr(String valStr){
 | 
												
													
														
															|  | 
 |  |         String[] strArr = valStr.split(",");
 | 
												
													
														
															|  | 
 |  |         Long[] longArr = new Long[strArr.length];
 | 
												
													
														
															|  | 
 |  |         for(int i=0; i<strArr.length; i++){
 | 
												
													
														
															|  | 
 |  |             longArr[i] = Long.parseLong(strArr[i]);
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         return longArr;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private Integer[] strToIntArr(String valStr){
 | 
												
													
														
															|  | 
 |  |         String[] strArr = valStr.split(",");
 | 
												
													
														
															|  | 
 |  |         Integer[] intArr = new Integer[strArr.length];
 | 
												
													
														
															|  | 
 |  |         for(int i=0; i<strArr.length; i++){
 | 
												
													
														
															|  | 
 |  |             intArr[i] = Integer.parseInt(strArr[i]);
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         return intArr;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private boolean isInteger(String fieldName) throws NoSuchFieldException {
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |         Field field = getField(fieldName);
 | 
												
													
														
															|  | 
 |  |         return field.getType().equals(Integer.class) || field.getType().equals(Integer.TYPE);
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private boolean isLong(String fieldName) throws NoSuchFieldException {
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |         Field field = getField(fieldName);
 | 
												
													
														
															|  | 
 |  |         return field.getType().equals(Long.class) || field.getType().equals(Long.TYPE);
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | 
 | 
												
													
														
															|  | 
 |  |     private Field getField(String fieldName) throws NoSuchFieldException {
 | 
												
													
														
															|  | 
 |  |         Field f;
 | 
												
													
														
															|  | 
 |  |         try {
 | 
												
													
														
															|  | 
 |  |             f = entityCls.getDeclaredField(fieldName);
 | 
												
													
														
															|  | 
 |  |         } catch (NoSuchFieldException e) {
 | 
												
													
														
															|  | 
 |  |             f = entityCls.getSuperclass().getDeclaredField(fieldName);
 | 
												
													
														
															|  | 
 |  |         }
 | 
												
													
														
															|  | 
 |  |         return f;
 | 
												
													
														
															|  | 
 |  |     }
 | 
												
													
														
															|  | 
 |  | }
 |