Jfinal用拼接sql用的Conditions工具類

package cn.jiayi.framework.kit.sql;

import cn.jiayi.web.kit.commons.StringKit;
import com.jfinal.log.Logger;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用於生成JFinal的SQL查詢語句<br>
 * 工具說明:
 * 1.setFiledQuery 指定字段查詢的TYPE,經過record或者model對象將查詢須要的值傳入,並生成sql。<br>
 *   例如:<br>
 *   setFiledQuery(FUZZY_LEFT,"name","phone");<br>
 *   modelToCondition(new Model().set("name","admin");<br>
 *   此時生成sql爲:and name like "%admin"  //由於只傳了name的值沒有phone的,故不生成phone<br>
 *
 * 2.當setValueQuery中字段和BizUser對象中的字段重疊時,以setValueQuery爲準.<br>
 *   例如:<br>
 *   conditions.setValueQuery(Conditions.FUZZY_LEFT,BizUser.COL_NAME,"admin");<br>
 *   //傳入name和phone的值<br>
 *   modelToCondition(new Model().set("name","admin").set("phone","13012341234"));<br>
 *   此時生成sql爲:and name like "%admin" //由於setValueQuery中只有name的查詢類型;<br>
 *
 * 3.若是須要以modal中的參數和值爲準,請將modelToCondition方法的isAll設爲false.
 *
 * Created by konbluesky
 * Date : 14-9-16 下午4:58
 * Project : JiaYi_WebServer
 * http://my.oschina.net/helloyangxp/blog/294231
 *
 */
public class Conditions {
    static Logger log = Logger.getLogger(Conditions.class);

    public static final String EQUAL = "EQUAL"; // 相等

    public static final String NOT_EQUAL = "NOT_EQUAL"; // 不相等

    public static final String LESS_THEN = "LESS_THEN"; // 小於

    public static final String LESS_EQUAL = "LESS_EQUAL"; // 小於等於

    public static final String GREATER_EQUAL = "GREATER_EQUAL"; // 大於等於

    public static final String GREATER_THEN = "GREATER_THEN"; // 大於

    public static final String FUZZY = "FUZZY"; // 模糊匹配 %xxx%

    public static final String FUZZY_LEFT = "FUZZY_LEFT"; // 左模糊 %xxx

    public static final String FUZZY_RIGHT = "FUZZY_RIGHT"; // 右模糊 xxx%

    public static final String NOT_EMPTY = "NOT_EMPTY"; // 不爲空值的狀況

    public static final String EMPTY = "EMPTY"; // 空值的狀況

    public static final String IN = "IN"; // 在範圍內

    public static final String NOT_IN = "NOT_IN"; // 不在範圍內

    // 用於接收SQL語句
    private ThreadLocal<String> sql = new ThreadLocal<String>();
    //select * from
    private ThreadLocal<String> selectorsql = new ThreadLocal<String>();

    // 用於接收參數數組
    private ThreadLocal<ArrayList<Object>> paramList = new ThreadLocal<ArrayList<Object>>();

    //String-column;object-value
    private ThreadLocal<Map<String,Object>> colvaluesMap = new ThreadLocal<Map<String, Object>>();

    // 用於存放設置的條件
    private ThreadLocal<Map<String, Object[]>> conditionMap = new ThreadLocal<Map<String, Object[]>>();

    // 用於存放須要排除的字段
    private ThreadLocal<Map<String, String>> excludeFieldMap = new ThreadLocal<Map<String, String>>();

    // 構造方法(表示沒有設置查詢類型的字段所有按照等於來處理)
    public Conditions() {
        colvaluesMap.set(new HashMap<String, Object>());
        conditionMap.set(new HashMap<String, Object[]>());
        excludeFieldMap.set(new HashMap<String, String>());
    }

    // 構造方法(設置後表示字段全部的查詢方式按照設置類型來處理,除非後面針對字段的從新設置)
    public Conditions(String type) {
        Map<String, Object[]> map = new HashMap<String, Object[]>();
        map.put("GLOBALTYPE", new String[] { type });
        conditionMap.set(map);
        excludeFieldMap.set(new HashMap<String, String>());
    }

    /***************************************************************************
     * 設置字段的查詢類型
     *
     * @param QueryType
     *            查詢類型
     * @param filedName
     *            字段名稱數組
     */
    public Conditions setFiledQuery(String QueryType, String... filedName) {
        if (StringKit.notBlank(QueryType) && StringKit.notNull(filedName)) {
            Map<String, Object[]> map = conditionMap.get();
            map.put(QueryType, filedName);
            conditionMap.set(map);
        }
        return this;
    }

    /***************************************************************************
     * 設置須要排除的字段
     *
     * setexcludeField<br>
     *
     * @param filedName
     * @return 返回對象
     * @Exception 異常對象
     *
     */
    public Conditions setExcludeField(String... filedName) {
        if (StringKit.notNull(filedName)) {
            Map<String, String> map = excludeFieldMap.get();
            for (String str : filedName) {
                map.put(str, str);
            }
            excludeFieldMap.set(map);
        }
        return this;
    }

    /***************************************************************************
     * 查詢空值或者不爲空值的狀況 setNullFieldQuery
     *
     * @param QueryType
     * @param filedName
     * @return 返回對象
     * @Exception 異常對象
     */
    public void setNullOrNotNullFieldQuery(String QueryType, String... filedName) {
        if (StringKit.notBlank(QueryType) && StringKit.notNull(filedName)) {
            if (!NOT_EMPTY.equals(QueryType) && !EMPTY.equals(QueryType)) {
                log.error("空值或者非空查詢的類型只能爲:EMPTY、NOT_EMPTY");
                throw new RuntimeException("空值或者非空查詢的類型只能爲:EMPTY、NOT_EMPTY");
            }
            Map<String, Object[]> map = conditionMap.get();
            map.put(QueryType, filedName);
            conditionMap.set(map);
        }
    }

    /***************************************************************************
     * <b>傳值查詢</b><br>
     * 注:若是QueryType爲<b>in</b>或者<b>not in</b>那麼filedValue必須爲一個list對象
     *
     * @param QueryType
     *            查詢類型
     * @param fieldName
     *            字段名稱
     * @param filedValue
     *            字段值
     */
    public Conditions setValueQuery(String QueryType, String fieldName, Object filedValue) {
        if (StringKit.notBlank(QueryType) && StringKit.notBlank(fieldName) && StringKit.notNull(filedValue)) {
            Object[] param = new Object[2];
            param[0] = fieldName; // 字段名
            param[1] = filedValue;// 字段值
            Map<String, Object[]> map = conditionMap.get();
            map.put(QueryType + "#" + fieldName, param);// 避免類型重複被覆蓋掉就加上字段名
            conditionMap.set(map);
        }
        return this;
    }

    /**
     * 當非主動調用modelToCondition,recordToCondition方法時
     * 須要此方法觸發sql拼接方法
     * @param val
     * @TODO
     * @return
     */
    public Conditions buildSQL(HashMap<String,Object> val){
        //@TODO
//        buildCondition("", val.keySet().toArray(new String[val.size()]), val);
        return this;
    }
    /***************************************************************************
     * 用於生成SQL條件語句不帶別名
     *
     * @param modelClass
     *            必須繼承於Model
     */
    public void modelToCondition(Model<?> modelClass) {
        modelToCondition(modelClass, null,true);
    }

    /***************************************************************************
     * 用於生成SQL條件語句不帶別名
     *
     * @param recordClass
     *            必須是一個Record類
     */
    public void recordToCondition(Record recordClass) {
        recordToCondition(recordClass, null,true);
    }

    /***************************************************************************
     * 用於生成SQL條件語句帶別名
     * 生成時以modelClass對象中的非空非null字段爲準
     * @param modelClass 必須繼承於Model
     * @param alias 別名 默承認覺得[null or ""]
     * @param isAll 是否須要以Modelclass中的屬性和值爲準,默認爲true <br>
     *               [true 使用conditionMap過濾,false 只用excludeFieldMap 過濾]
     */
    public void modelToCondition(Model<?> modelClass, String alias,boolean isAll) {
        alias = StringKit.notBlank(alias) ? alias + "." : "";
        if (modelClass != null) {
            // 全部的字段
            String[] fieldNames = modelClass.getAttrNames();
            // 字段名和值的map集合
//            Map<String, Object> valueMap = Common.modelToMap(modelClass);
            Map<String, Object> valueMap = new HashMap<String, Object>();
            for(Map.Entry<String,Object> en : modelClass.getAttrsEntrySet()){
                //不在excludeFieldMap 可是存在與conditionMap中的value才能傳入生成sql
                if (!excludeFieldMap.get().containsKey(en.getKey())
                        && (isAll || conditionMap.get().containsKey(en.getKey()))) {
                    valueMap.put(en.getKey(), en.getValue());
                }
            }
            // 構建查詢條件
            buildCondition(alias, fieldNames, valueMap);
        } else {
            if (!conditionMap.get().isEmpty()) {
                buildCondition(alias, new String[] {}, new HashMap<String, Object>());
            } else {
                sql.set("");
                paramList.set(new ArrayList<Object>(0));
            }
        }
    }

    /***************************************************************************
     * 用於生成SQL條件語句不帶別名
     *
     * @param recordClass
     *            必須是一個Record類
     * @param alias 別名 默承認覺得[null or ""]
     * @param isAll 是否須要以Modelclass中的屬性和值爲準,默認爲true <br>
     *               [true 使用conditionMap過濾,false 只用excludeFieldMap 過濾]
     */
    public void recordToCondition(Record recordClass, String alias,boolean isAll) {
        // 別名
        alias = StringKit.notBlank(alias) ? alias + "." : "";
        if (recordClass != null) {
            // 全部的字段
            String[] fieldNames = recordClass.getColumnNames();
            // 字段名和值的map集合
//            Map<String, Object> valueMap = Common.recordToMap(recordClass);
            Map<String, Object> valueMap = recordClass.getColumns();
            for(Map.Entry<String,Object> en : recordClass.getColumns().entrySet()){
                //即便按照#查詢 也要從exclude過濾
                if (!excludeFieldMap.get().containsKey(en.getKey())
                        && (isAll || conditionMap.get().containsKey(en.getKey()))) {
                    valueMap.put(en.getKey(), en.getValue());
                }
            }
            // 構建查詢條件
            buildCondition(alias, fieldNames, valueMap);
        } else {
            if (!conditionMap.get().isEmpty()) {
                buildCondition(alias, new String[] {}, new HashMap<String, Object>());
            } else {
                sql.set("");
                paramList.set(new ArrayList<Object>(0));
            }
        }
    }

    /***************************************************************************
     * 構建條件語句
     *
     * @param alias
     *            別名
     * @param fieldNames
     *            全部查詢的字段名稱
     * @param valueMap
     *            全部的值的map
     */
    private void buildCondition(String alias, String[] fieldNames, Map<String, Object> valueMap) {
        try {
            // 構建條件前先清空變量
            sql.set("");
            paramList.set(new ArrayList<Object>());
            // 用於存放參數列表
            ArrayList<Object> paramArrayList = new ArrayList<Object>();
            StringBuilder sb = new StringBuilder();
            // 全部的字段名稱
            Map<String, String> usedFieldMap = new HashMap<String, String>();
            if (!conditionMap.get().isEmpty()) {
                for (Map.Entry<String, Object[]> map : conditionMap.get().entrySet()) {
                    String queryType = map.getKey();
                    Object[] array = map.getValue();
                    if (queryType.indexOf("#") > 0) {// 傳值查詢
                        String fieldQueryType = queryType.split("#")[0];
                        String fieldName = array[0] != null ? array[0].toString() : "";
                        Object fieldValue = array[1];
                        // 將設置過的字段保存到數組中
                        usedFieldMap.put(fieldName, fieldName);
                        // 構建SQL語句
                        buildSQL(sb, fieldQueryType, fieldName, fieldValue, alias, paramArrayList);
                    } else {// 字段查詢
                        if (!"GLOBALTYPE".equals(queryType)) {
                            for (Object field : array) {
                                String filedName = field != null ? field.toString() : "";
                                if (!excludeFieldMap.get().containsKey(filedName)) {
                                    Object fieldValue = valueMap.get(filedName);
                                    // 將設置過的字段保存到數組中
                                    usedFieldMap.put(filedName, filedName);
                                    // 構建查詢語句
                                    buildSQL(sb, queryType, filedName, fieldValue, alias, paramArrayList);
                                }
                            }
                        }
                    }
                }
            }
            // 對沒有設置條件的字段進行查詢類型設置
            String queryType = EQUAL;
            if (conditionMap.get().containsKey("GLOBALTYPE")) {
                String[] typeArray = (String[]) conditionMap.get().get("GLOBALTYPE");
                queryType = typeArray[0];
            }
            // 對未使用過的字段進行build
            for (String field : fieldNames) {
                if (!usedFieldMap.containsKey(field)) {
                    Object fieldValue = valueMap.get(field);
                    // 構建查詢語句
                    buildSQL(sb, queryType, field, fieldValue, alias, paramArrayList);
                }
            }

            // 合併傳入的參數到參數對象中
            sql.set(sb.toString());
            paramList.set(paramArrayList);
            conditionMap.set(new HashMap<String, Object[]>(0));// 清空本次的條件map
            excludeFieldMap.set(new HashMap<String, String>(0));// 清空本次的排除字段
        } catch (Exception e) {
            log.error("Conditions構建SQL語句出現錯誤,請仔細檢查!",e);
            e.printStackTrace();
        }
    }

    /***************************************************************************
     * 構建SQL語句
     *
     * @param sb
     *            用於拼接SQL語句
     * @param queryType
     *            查詢類型
     * @param fieldName
     *            字段名稱
     * @param fieldValue
     *            字段值
     * @param alias
     *            別名
     * @return
     */
    @SuppressWarnings("unchecked")
    private void buildSQL(StringBuilder sb, String queryType, String fieldName, Object fieldValue, String alias, ArrayList<Object> params) {
        // 非空的時候進行設置
        if (StringKit.notNull(fieldValue) && StringKit.notNull(fieldName)) {
            if (EQUAL.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " = ? ");
                params.add(fieldValue);
            } else if (NOT_EQUAL.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " <> ? ");
                params.add(fieldValue);
            } else if (LESS_THEN.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " < ? ");
                params.add(fieldValue);
            } else if (LESS_EQUAL.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " <= ? ");
                params.add(fieldValue);
            } else if (GREATER_THEN.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " > ? ");
                params.add(fieldValue);
            } else if (GREATER_EQUAL.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " >= ? ");
                params.add(fieldValue);
            } else if (FUZZY.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " like ? ");
                params.add("%" + fieldValue + "%");
            } else if (FUZZY_LEFT.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " like ? ");
                params.add("%" + fieldValue);
            } else if (FUZZY_RIGHT.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " like ? ");
                params.add(fieldValue + "%");
            } else if (IN.equals(queryType)) {
                try {
                    List list = (List) fieldValue;
                    StringBuffer instr = new StringBuffer();
                    sb.append(" and " + alias + fieldName + " in (");
                    for (Object obj : list) {
                        instr.append(StringKit.notBlank(instr) ? ",?" : "?");
                        params.add(obj);
                    }
                    sb.append(instr + ") ");
                } catch (Exception e) {
                    throw new RuntimeException("使用IN條件的時候傳入的值必須是個List對象,不然將會轉換出錯!例如將 in('1','2','3')中的'1','2','3'分爲三個分別添加到List中作爲值傳入.",e);
                }
            } else if (NOT_IN.equals(queryType)) {
                try {
                    List list = (List) fieldValue;
                    StringBuffer instr = new StringBuffer();
                    sb.append(" and " + alias + fieldName + " not in (");
                    for (Object obj : list) {
                        instr.append(StringKit.notBlank(instr) ? ",?" : "?");
                        params.add(obj);
                    }
                    sb.append(instr + ") ");
                } catch (Exception e) {
                    throw new RuntimeException("使用NOT IN條件的時候傳入的值必須是個List對象,不然將會轉換出錯!例如將 not in('1','2','3')中的'1','2','3'分爲三個分別添加到List中作爲值傳入.",e);
                }
            }
        } else {
            if (EMPTY.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " is null ");
            } else if (NOT_EMPTY.equals(queryType)) {
                sb.append(" and " + alias + fieldName + " is not null ");
            }
        }
    }

    public String getSql() {
        return sql.get();
    }

    public List<Object> getParamList() {
        return paramList.get();
    }

    public Map<String, Object> getParamMap() {
        return colvaluesMap.get();
    }

    public String getSelector(){
        return selectorsql.get();
    }
    public void setSelector(String selector){
        selectorsql.set(selector);
    }

    public static void main(String[] args){
//        conditions.setFiledQuery(Conditions.FUZZY, BizUser.COL_NAME,BizUser.COL_PHONE);
//        System.out.println(conditions.getSql());
//        conditions=new Conditions();
//        conditions.modelToCondition(BizUser.dao.searchFirst(BizUser.COL_LIVEFLAG, 1));
//        conditions.modelToCondition(new BizUser());
//        System.out.println(conditions.getSql());
//        System.out.println(conditions.getParamList());

//        conditions=new Conditions().setExcludeField(BizUser.COL_UUID);
          /*當setValueQuery中字段和BizUser對象中的字段重疊時,以setValueQuery爲準*/
//        conditions.setValueQuery(Conditions.FUZZY_LEFT,BizUser.COL_NAME,"wang");
//        conditions.modelToCondition(new BizUser().set(BizUser.COL_NAME,"wang"));

//        System.out.println(conditions.getSql());
//        System.out.println(conditions.getParamList());
    }

}
相關文章
相關標籤/搜索