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());
}
}
转载于:https://my.oschina.net/u/261246/blog/336272