All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.sylinx.hbatis.db.common.FS Maven / Gradle / Ivy

There is a newer version: 2.0.0.RELEASE
Show newest version
package cn.sylinx.hbatis.db.common;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import cn.sylinx.hbatis.db.mapper.ModelBuilder;
import cn.sylinx.hbatis.db.mapper.anno.PrimaryKey;
import cn.sylinx.hbatis.exception.HbatisException;
import cn.sylinx.hbatis.ext.lambda.LambdaUtil;
import cn.sylinx.hbatis.ext.lambda.TypeFunction;
import cn.sylinx.hbatis.kit.StrKit;
import cn.sylinx.hbatis.log.GLog;
import cn.sylinx.hbatis.plugin.model.ModelFabric;

/**
 * fluent sql support, KEY WORD CAN NOT BE USED!
 * 
 * @author han
 *
 * @param 
 */
public class FS {

	public static final String AND_STR = " AND ";
	public static final String BLANK_STR = "";

	protected Class modelClass;
	protected StringBuilder conditionSQL = new StringBuilder();
	protected StringBuilder orderBySQL = new StringBuilder();
	protected StringBuilder limitSQL = new StringBuilder();
	protected List excludedColumns = new ArrayList<>(8);
	protected List paramValues = new ArrayList<>(8);
	protected Map updateColumns = new LinkedHashMap<>(8);
	protected Map updateColumnExpression = new LinkedHashMap<>(8);
	protected String selectColumns;
	protected String selectExpressionColumns;
	protected boolean distinct = false;
	protected boolean count = false;
	protected String[] primaryKeyColumn;
	protected String tableName;
	protected Map attrs = null;
	protected T model;
	protected String preEscape;
	protected String postEscape;
	protected boolean singleField = false;
	protected String hint;

	protected String tablePostfix = BLANK_STR;
	protected String tablePrefix = BLANK_STR;

	public static  FS of(Class modelClass) {
		return of(BLANK_STR, modelClass, BLANK_STR);
	}

	public static  FS of(Class modelClass, String tablePostfix) {
		return of(BLANK_STR, modelClass, tablePostfix);
	}

	public static  FS of(String tablePrefix, Class modelClass) {
		return of(tablePrefix, modelClass, BLANK_STR);
	}

	public static  FS of(String tablePrefix, Class modelClass, String tablePostfix) {
		return new FS().init(tablePrefix, modelClass, tablePostfix);
	}

	protected String[] getEscape() {
		return new String[] { BLANK_STR, BLANK_STR };
	}

	public FS init(Class modelClass) {
		return init(BLANK_STR, modelClass, BLANK_STR);
	}

	public FS init(String tablePrefix, Class modelClass) {
		return init(tablePrefix, modelClass, BLANK_STR);
	}

	public FS init(Class modelClass, String tablePostfix) {
		return init(BLANK_STR, modelClass, tablePostfix);
	}

	public FS init(String tablePrefix, Class modelClass, String tablePostfix) {
		return parse(tablePrefix, modelClass, tablePostfix);
	}

	public FluentSqlParams build() {

		this.beforeCheck();

		FluentSqlParams fsp = new FluentSqlParams();
		fsp.setConditionSQL(conditionSQL);
		fsp.setModelClass(modelClass);
		fsp.setOrderBy(orderBySQL.toString());
		fsp.setLimitSQL(limitSQL.toString());
		fsp.setExcludedColumns(excludedColumns);
		fsp.setParamValues(paramValues);
		fsp.setUpdateColumns(updateColumns);
		fsp.setUpdateColumnExpression(updateColumnExpression);
		fsp.setSelectColumns(selectColumns);
		fsp.setSelectExpressionColumns(selectExpressionColumns);
		fsp.setPrimaryKeyColumn(primaryKeyColumn);
		fsp.setTableName(tableName);
		fsp.setModel(model);
		fsp.setDistinct(distinct);
		fsp.setCount(count);
		fsp.setAttrs(attrs);
		fsp.setPreEscape(preEscape);
		fsp.setPostEscape(postEscape);
		fsp.setSingleField(singleField);
		fsp.setHint(hint);
		fsp.setTablePrefix(tablePrefix);
		fsp.setTablePostfix(tablePostfix);
		
		return fsp;

	}

	private FS parse(String tablePrefix, Class modelClass, String tablePostfix) {

		this.tablePrefix = tablePrefix == null ? BLANK_STR : tablePrefix.trim();
		this.tablePostfix = tablePostfix == null ? BLANK_STR : tablePostfix.trim();

		String[] escapes = getEscape();
		this.preEscape = escapes[0];
		this.postEscape = escapes[1];

		this.modelClass = modelClass;
		this.tableName = preEscape + tablePrefix + ModelBuilder.getModelFabric(modelClass).getTableName() + tablePostfix
				+ postEscape;
		PrimaryKey pk = ModelBuilder.getModelFabric(modelClass).getPrimaryKey();
		this.primaryKeyColumn = pk == null ? new String[] { "id" } : pk.value();
		this.attrs = ModelBuilder.getModelFabric(modelClass).getAttrMapping();
		if (this.attrs == null) {
			this.attrs = new HashMap<>();
		}
		return this;
	}

	public FS exclude(String... columnNames) {

		if (columnNames == null) {
			throw new HbatisException("exclude columnNames is null");
		}

		List columnExcludeList = new ArrayList<>();
		for (int i = 0; i < columnNames.length; ++i) {
			columnExcludeList.add(columnNames[i]);
			columnExcludeList.add(mapColumn(columnNames[i]));
		}

		String[] tempColumnNames = new String[columnExcludeList.size()];
		columnExcludeList.toArray(tempColumnNames);

		Collections.addAll(excludedColumns, tempColumnNames);
		return this;
	}

	@SafeVarargs
	public final  FS exclude(TypeFunction... lambdaArray) {
		String[] columnNames = new String[lambdaArray.length];
		for (int i = 0; i < lambdaArray.length; ++i) {
			columnNames[i] = LambdaUtil.getLambdaFieldName(lambdaArray[i]);
		}
		return exclude(columnNames);
	}

	public FS select(String columns) {
		if (null != this.selectColumns) {
			throw new HbatisException("Select method can only be called once.");
		}
		this.selectColumns = mapColumns(columns);
		return this;
	}

	/**
	 * 使用native sql表达式, 不要用 ',' 号结束
	 * 
	 * @param exp
	 * @return
	 */
	public FS selectExp(String exp) {
		if (null != this.selectExpressionColumns) {
			throw new HbatisException("SelectExp method can only be called once.");
		}
		this.selectExpressionColumns = exp;
		return this;
	}

	public FS select(String... columnArray) {
		if (null != this.selectColumns) {
			throw new HbatisException("Select method can only be called once.");
		}
		this.selectColumns = mapColumns(columnArray);
		return this;
	}

	@SafeVarargs
	public final  FS select(TypeFunction... lambdaArray) {
		String[] columnNames = new String[lambdaArray.length];
		for (int i = 0; i < lambdaArray.length; ++i) {
			columnNames[i] = LambdaUtil.getLambdaFieldName(lambdaArray[i]);
		}
		return select(columnNames);
	}

	/**
	 * 放在sql最前面的提示
	 * 
	 * @param hint
	 * @return
	 */
	public FS hint(String hint) {
		this.hint = hint;
		return this;
	}

	public FS distinct() {
		this.distinct = true;
		return this;
	}

	public FS count() {
		this.count = true;
		return this;
	}

	public FS singleField(String column) {
		this.select(column);
		this.singleField = true;
		return this;
	}

	public  FS singleField(TypeFunction lambda) {
		return singleField(LambdaUtil.getLambdaFieldName(lambda));
	}

	private String mapColumns(String[] columnArray) {

		this.beforeCheck();
		if (columnArray == null || columnArray.length == 0) {
			return null;
		}
		StringBuilder mappedClumns = new StringBuilder();
		for (String column : columnArray) {
			mappedClumns.append(mapColumn(column.trim())).append(",");
		}
		mappedClumns.deleteCharAt(mappedClumns.length() - 1);
		return mappedClumns.toString();
	}

	private String mapColumns(String columns) {

		this.beforeCheck();
		if (StrKit.isBlank(columns)) {
			return null;
		}
		StringBuilder mappedClumns = new StringBuilder();
		String[] columnArray = columns.split(",");
		for (String column : columnArray) {
			mappedClumns.append(mapColumn(column.trim())).append(",");
		}
		mappedClumns.deleteCharAt(mappedClumns.length() - 1);
		return mappedClumns.toString();
	}

	private String mapColumn(String column) {

		String trueColumn = attrs.get(column);
		return preEscape + (trueColumn == null ? column : trueColumn) + postEscape;
	}

	/**
	 * where condition
	 *
	 * @param column
	 * @return SqlGenerator
	 */
	public FS where(String column) {
		String trueStatement = mapColumn(column);
		conditionSQL.append(AND_STR).append(trueStatement);
		return this;
	}

	/**
	 * 表达式
	 * 
	 * @param exp
	 * @return
	 */
	public FS whereExp(String exp) {
		conditionSQL.append(AND_STR).append(exp);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @return
	 */
	public  FS where(TypeFunction lambda) {
		return where(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * where condition, simultaneous setting value
	 *
	 * @param column
	 * 
	 * @param value  column name
	 * @return SqlGenerator
	 */
	public FS where(String column, Object value) {
		String trueStatement = mapColumn(column) + " = ?";
		conditionSQL.append(AND_STR).append(trueStatement);
		paramValues.add(value);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS where(TypeFunction lambda, Object value) {
		return where(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * Set the where parameter according to model, and generate sql like where where
	 * age = ? and name = ?
	 *
	 * @param model
	 * @return SqlGenerator
	 */
	public FS where(T model) {

		ModelFabric mf = ModelBuilder.getModelFabric(model.getClass());
		List declaredFields = mf.getFields();
		Map attrs = mf.getAttrMapping();

		try {
			for (Field declaredField : declaredFields) {

				Object value = declaredField.get(model);

				if (null == value) {
					continue;
				}
				if (declaredField.getType().equals(String.class) && StrKit.isBlank(value.toString())) {
					continue;
				}

				String columnName = attrs.get(declaredField.getName());
				this.where(columnName, value);
			}
		} catch (IllegalArgumentException | IllegalAccessException e) {
			GLog.error("where model error:", e);
		}

		return this;
	}

	/**
	 * Equals statement
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS eq(Object value) {
		conditionSQL.append(" = ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "IS NOT NULL" statement
	 *
	 * @return SqlGenerator
	 */
	public FS notNull() {
		conditionSQL.append(" IS NOT NULL");
		return this;
	}

	/**
	 * generate AND statement, simultaneous setting value
	 *
	 * @param column
	 * @param value  column value
	 * @return
	 */
	public FS and(String column, Object value) {
		return this.where(column, value);
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS and(TypeFunction lambda, Object value) {
		return and(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * 
	 * @param column
	 * @return
	 */
	public FS and(String column) {
		return this.where(column);
	}

	/**
	 * 
	 * @param lambda
	 * @return
	 */
	public  FS and(TypeFunction lambda) {
		return this.and(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * generate OR statement, simultaneous setting value
	 *
	 * @param column
	 * 
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS or(String column, Object value) {

		String trueStatement = mapColumn(column) + " = ?";
		conditionSQL.append(" OR (").append(trueStatement);
		conditionSQL.append(')');
		paramValues.add(value);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS or(TypeFunction lambda, Object value) {
		return or(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "!=" statement, simultaneous setting value
	 *
	 * @param columnName column name [sql]
	 * @param value      column value
	 * @return SqlGenerator
	 */
	public FS andNotEq(String columnName, Object value) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" != ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS andNotEq(TypeFunction lambda, Object value) {
		return andNotEq(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "!=" statement, simultaneous setting value
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS notEq(Object value) {
		conditionSQL.append(" != ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "!= ''" statement
	 *
	 * @param columnName column name
	 * @return SqlGenerator
	 */
	public FS andNotEmpty(String columnName) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" != ''");
		return this;
	}

	/**
	 * 
	 * @param columnName
	 * @return
	 */
	public FS notEmpty(String columnName) {
		conditionSQL.append(mapColumn(columnName)).append(" != ''");
		return this;
	}

	/**
	 * generate "!= ''" statement
	 *
	 * @return
	 */
	public FS notEmpty() {
		conditionSQL.append(" != ''");
		return this;
	}

	/**
	 * generate "IS NOT NULL" statement
	 *
	 * @param columnName column name
	 * @return
	 */
	public FS andNotNull(String columnName) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" IS NOT NULL");
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @return
	 */
	public  FS andNotNull(TypeFunction lambda) {
		return andNotNull(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * generate "IS NOT NULL" statement
	 *
	 * @param columnName column name
	 * @return
	 */
	public FS notNull(String columnName) {
		conditionSQL.append(mapColumn(columnName)).append(" IS NOT NULL");
		return this;
	}

	public FS isNull() {
		conditionSQL.append(" IS NULL");
		return this;
	}

	public FS isNull(String columnName) {
		conditionSQL.append(mapColumn(columnName)).append(" IS NULL");
		return this;
	}

	public FS andIsNull(String columnName) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" IS NULL");
		return this;
	}

	public  FS andIsNull(TypeFunction lambda) {
		return andIsNull(LambdaUtil.getLambdaFieldName(lambda));
	}

	public  FS isNull(TypeFunction lambda) {
		return isNull(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * 默认使用Mysql limit语法
	 * 
	 * @param size
	 * @return
	 */
	public FS limit(int size) {
		if (limitSQL.length() == 0) {
			limitSQL.append(" LIMIT ").append(size);
		}
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @return
	 */
	public  FS notNull(TypeFunction lambda) {
		return notNull(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * generate like statement, simultaneous setting value
	 *
	 * @param columnName column name
	 * @param value      column value
	 * @return SqlGenerator
	 */
	public FS andLike(String columnName, Object value) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" LIKE ?");
		paramValues.add("%" + value + "%");
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS andLike(TypeFunction lambda, Object value) {
		return andLike(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate like statement, simultaneous setting value
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS like(Object value) {
		conditionSQL.append(" LIKE ?");
		paramValues.add("%" + value + "%");
		return this;
	}

	/**
	 * generate like statement, simultaneous setting value
	 *
	 * @param columnName column name
	 * @param value      column value
	 * @return SqlGenerator
	 */
	public FS like(String columnName, Object value) {
		String trueColumnName = mapColumn(columnName);
		conditionSQL.append(trueColumnName).append(" LIKE ?");
		paramValues.add("%" + value + "%");
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS like(TypeFunction lambda, Object value) {
		return like(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * 
	 * @param columnName
	 * @param value
	 * @return
	 */
	public FS andLikeLeft(String columnName, Object value) {
		String trueColumnName = mapColumn(columnName);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" LIKE ?");
		paramValues.add("%" + value);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS andLikeLeft(TypeFunction lambda, Object value) {
		return andLikeLeft(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * 
	 * @param value
	 * @return
	 */
	public FS likeLeft(Object value) {
		conditionSQL.append(" LIKE ?");
		paramValues.add("%" + value);
		return this;
	}

	/**
	 * 
	 * @param columnName
	 * @param value
	 * @return
	 */
	public FS likeLeft(String columnName, Object value) {
		conditionSQL.append(mapColumn(columnName)).append(" LIKE ?");
		paramValues.add("%" + value);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS likeLeft(TypeFunction lambda, Object value) {
		return likeLeft(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * 
	 * @param columnName
	 * @param value
	 * @return
	 */
	public FS andLikeRight(String columnName, Object value) {
		String trueColumnName = mapColumn(columnName);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" LIKE ?");
		paramValues.add(value + "%");
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS andLikeRight(TypeFunction lambda, Object value) {
		return andLikeRight(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * 
	 * @param value
	 * @return
	 */
	public FS likeRight(Object value) {
		conditionSQL.append(" LIKE ?");
		paramValues.add(value + "%");
		return this;
	}

	/**
	 * 
	 * @param columnName
	 * @param value
	 * @return
	 */
	public FS likeRight(String columnName, Object value) {
		conditionSQL.append(mapColumn(columnName)).append(" LIKE ?");
		paramValues.add(value + "%");
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS likeRight(TypeFunction lambda, Object value) {
		return likeRight(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate between statement, simultaneous setting value
	 *
	 * @param columnName column name
	 * @param a          first range value
	 * @param b          second range value
	 * @return SqlGenerator
	 */
	public FS andBetween(String columnName, Object a, Object b) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" BETWEEN ? and ?");
		paramValues.add(a);
		paramValues.add(b);
		return this;
	}

	/**
	 * not between
	 * 
	 * @param columnName
	 * @param a
	 * @param b
	 * @return
	 */
	public FS andNotBetween(String columnName, Object a, Object b) {
		conditionSQL.append(AND_STR).append(mapColumn(columnName)).append(" NOT BETWEEN ? and ?");
		paramValues.add(a);
		paramValues.add(b);
		return this;
	}

	/**
	 * generate between statement with lambda, simultaneous setting value
	 *
	 * @param function column name with lambda
	 * @param a        first range value
	 * @param b        second range value
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS andBetween(TypeFunction lambda, Object a, Object b) {
		return andBetween(LambdaUtil.getLambdaFieldName(lambda), a, b);
	}

	/**
	 * not between
	 * 
	 * @param lambda
	 * @param a
	 * @param b
	 * @return
	 */
	public  FS andNotBetween(TypeFunction lambda, Object a, Object b) {
		return andNotBetween(LambdaUtil.getLambdaFieldName(lambda), a, b);
	}

	/**
	 * generate between values
	 *
	 * @param a first range value
	 * @param b second range value
	 * @return SqlGenerator
	 */
	public FS between(Object a, Object b) {
		conditionSQL.append(" BETWEEN ? and ?");
		paramValues.add(a);
		paramValues.add(b);
		return this;
	}

	/**
	 * not between
	 * 
	 * @param a
	 * @param b
	 * @return
	 */
	public FS notBetween(Object a, Object b) {
		conditionSQL.append(" NOT BETWEEN ? and ?");
		paramValues.add(a);
		paramValues.add(b);
		return this;
	}

	/**
	 * generate between statement, simultaneous setting value
	 *
	 * @param columnName column name
	 * @param a          first range value
	 * @param b          second range value
	 * @return SqlGenerator
	 */
	public FS between(String columnName, Object a, Object b) {
		conditionSQL.append(mapColumn(columnName)).append(" BETWEEN ? and ?");
		paramValues.add(a);
		paramValues.add(b);
		return this;
	}

	/**
	 * not between
	 * 
	 * @param columnName
	 * @param a
	 * @param b
	 * @return
	 */
	public FS notBetween(String columnName, Object a, Object b) {
		conditionSQL.append(mapColumn(columnName)).append(" NOT BETWEEN ? and ?");
		paramValues.add(a);
		paramValues.add(b);
		return this;
	}

	/**
	 * generate between statement with lambda, simultaneous setting value
	 *
	 * @param function column name with lambda
	 * @param a        first range value
	 * @param b        second range value
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS between(TypeFunction lambda, Object a, Object b) {
		return between(LambdaUtil.getLambdaFieldName(lambda), a, b);
	}

	/**
	 * not between
	 * 
	 * @param lambda
	 * @param a
	 * @param b
	 * @return
	 */
	public  FS notBetween(TypeFunction lambda, Object a, Object b) {
		return notBetween(LambdaUtil.getLambdaFieldName(lambda), a, b);
	}

	/**
	 * generate ">" statement, simultaneous setting value
	 *
	 * @param columnName table column name [sql]
	 * @param value      column value
	 * @return SqlGenerator
	 */
	public FS andGt(String columnName, Object value) {
		String trueColumnName = mapColumn(columnName);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" > ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate ">" statement with lambda, simultaneous setting value
	 *
	 * @param function column name with lambda
	 * @param value    column value
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS andGt(TypeFunction lambda, Object value) {
		return andGt(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate ">" statement value
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS gt(Object value) {
		conditionSQL.append(" > ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate ">" statement, simultaneous setting value
	 *
	 * @param columnName table column name [sql]
	 * @param value      column value
	 * @return SqlGenerator
	 */
	public FS gt(String columnName, Object value) {
		String trueColumnName = mapColumn(columnName);
		conditionSQL.append(trueColumnName).append(" > ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate ">" statement with lambda, simultaneous setting value
	 *
	 * @param function column name with lambda
	 * @param value    column value
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS gt(TypeFunction lambda, Object value) {
		return gt(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate ">=" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS andGte(String column, Object value) {
		String trueColumnName = mapColumn(column);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" >= ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate ">=" statement, simultaneous setting value
	 * 
	 * @param lambda table column name with lambda
	 * @param value
	 * @return
	 */
	public  FS andGte(TypeFunction lambda, Object value) {
		return andGte(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate ">=" statement value
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS gte(Object value) {
		conditionSQL.append(" >= ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "<" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS andLt(String column, Object value) {
		String trueColumnName = mapColumn(column);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" < ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "<" statement, simultaneous setting value
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS andLt(TypeFunction lambda, Object value) {
		return andLt(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "<" statement value
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS lt(Object value) {
		conditionSQL.append(" < ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "<=" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS andLte(String column, Object value) {
		String trueColumnName = mapColumn(column);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" <= ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "<=" statement, simultaneous setting value
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS andLte(TypeFunction lambda, Object value) {
		return andLte(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "<=" statement value
	 *
	 * @param value column value
	 * @return SqlGenerator
	 */
	public FS lte(Object value) {
		conditionSQL.append(" <= ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate ">=" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS gte(String column, Object value) {
		conditionSQL.append(mapColumn(column)).append(" >= ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate ">=" statement, simultaneous setting value
	 * 
	 * @param lambda table column name with lambda
	 * @param value
	 * @return
	 */
	public  FS gte(TypeFunction lambda, Object value) {
		return gte(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "<" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS lt(String column, Object value) {
		String trueColumnName = mapColumn(column);
		conditionSQL.append(trueColumnName).append(" < ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "<" statement, simultaneous setting value
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS lt(TypeFunction lambda, Object value) {
		return lt(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "<=" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS lte(String column, Object value) {
		String trueColumnName = mapColumn(column);
		conditionSQL.append(trueColumnName).append(" <= ?");
		paramValues.add(value);
		return this;
	}

	/**
	 * generate "<=" statement, simultaneous setting value
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS lte(TypeFunction lambda, Object value) {
		return lte(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * generate "in" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param args   column value
	 * @return SqlGenerator
	 */
	public FS andIn(String column, Object... args) {
		if (null == args || args.length == 0) {
			GLog.error("column:{}, in params is empty.", column);
			return this;
		}
		String trueColumnName = mapColumn(column);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" IN (");
		this.setArguments(args);
		conditionSQL.append(")");
		return this;
	}

	/**
	 * not in
	 * 
	 * @param column
	 * @param args
	 * @return
	 */
	public FS andNotIn(String column, Object... args) {
		if (null == args || args.length == 0) {
			GLog.error("column:{}, in params is empty.", column);
			return this;
		}
		String trueColumnName = mapColumn(column);
		conditionSQL.append(AND_STR).append(trueColumnName).append(" NOT IN (");
		this.setArguments(args);
		conditionSQL.append(")");
		return this;
	}

	/**
	 * generate "in" statement, simultaneous setting value
	 *
	 * @param column table column name [sql]
	 * @param args   column value
	 * @return SqlGenerator
	 */
	public FS in(String column, Object... args) {
		if (null == args || args.length == 0) {
			GLog.error("column:{}, in params is empty.", column);
			return this;
		}
		String trueColumnName = mapColumn(column);
		conditionSQL.append(trueColumnName).append(" IN (");
		this.setArguments(args);
		conditionSQL.append(")");
		return this;
	}

	/**
	 * not in
	 * 
	 * @param column
	 * @param args
	 * @return
	 */
	public FS notIn(String column, Object... args) {
		if (null == args || args.length == 0) {
			GLog.error("column:{}, in params is empty.", column);
			return this;
		}
		String trueColumnName = mapColumn(column);
		conditionSQL.append(trueColumnName).append(" NOT IN (");
		this.setArguments(args);
		conditionSQL.append(")");
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS in(TypeFunction lambda, Object... args) {
		return in(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * not in
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS notIn(TypeFunction lambda, Object... args) {
		return notIn(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS andIn(TypeFunction lambda, Object... args) {
		return andIn(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * and not in
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS andNotIn(TypeFunction lambda, Object... args) {
		return andNotIn(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * generate "in" statement value
	 *
	 * @param args column value
	 * @return SqlGenerator
	 */
	public FS in(Object... args) {
		if (null == args || args.length == 0) {
			GLog.error("Column: {}, query params is empty.");
			return this;
		}
		conditionSQL.append(" IN (");
		this.setArguments(args);
		conditionSQL.append(")");
		return this;
	}

	/**
	 * not in
	 * 
	 * @param args
	 * @return
	 */
	public FS notIn(Object... args) {
		if (null == args || args.length == 0) {
			GLog.error("Column: {}, query params is empty.");
			return this;
		}
		conditionSQL.append(" NOT IN (");
		this.setArguments(args);
		conditionSQL.append(")");
		return this;
	}

	/**
	 * Set in params
	 *
	 * @param list in param values
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS in(List list) {
		return this.in(list.toArray());
	}

	/**
	 * not in
	 * 
	 * @param list
	 * @return
	 */
	public  FS notIn(List list) {
		return this.notIn(list.toArray());
	}

	/**
	 * generate "in" statement, simultaneous setting value
	 *
	 * @param column column name
	 * @param args   in param values
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS in(String column, List args) {
		return this.in(column, args.toArray());
	}

	/**
	 * not in
	 * 
	 * @param column
	 * @param args
	 * @return
	 */
	public  FS notIn(String column, List args) {
		return this.notIn(column, args.toArray());
	}

	/**
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS in(TypeFunction lambda, List args) {
		return this.in(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * not in
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS notIn(TypeFunction lambda, List args) {
		return this.notIn(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * generate "in" statement, simultaneous setting value
	 *
	 * @param column column name
	 * @param args   in param values
	 * @param 
	 * @return SqlGenerator
	 */
	public  FS andIn(String column, List args) {
		return this.andIn(column, args.toArray());
	}

	/**
	 * and not in
	 * 
	 * @param column
	 * @param args
	 * @return
	 */
	public  FS andNotIn(String column, List args) {
		return this.andNotIn(column, args.toArray());
	}

	/**
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS andIn(TypeFunction lambda, List args) {
		return this.andIn(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * and not in
	 * 
	 * @param lambda
	 * @param args
	 * @return
	 */
	public  FS andNotIn(TypeFunction lambda, List args) {
		return this.andNotIn(LambdaUtil.getLambdaFieldName(lambda), args);
	}

	/**
	 * generate order by statement
	 *
	 * @param order like "id desc"
	 * @return SqlGenerator
	 */
	public FS order(String order) {
		if (StrKit.isBlank(order)) {
			throw new HbatisException("order is empty");
		}

		if (this.orderBySQL.length() > 0) {
			this.orderBySQL.append(',');
		}

		String orderTemp = order.trim();
		String newOrder = orderTemp;
		String column = null;
		String flag = null;

		int index = orderTemp.indexOf(" ");
		if (index > -1) {
			column = orderTemp.substring(0, index);
			flag = orderTemp.substring(index);
			newOrder = mapColumn(column) + " " + flag;
		}

		this.orderBySQL.append(' ').append(newOrder);
		return this;
	}

	/**
	 * generate order by statement
	 *
	 * @param columnName column name
	 * @param orderBy    order by @see OrderBy
	 * @return SqlGenerator
	 */
	public FS order(String columnName, OrderBy orderBy) {
		if (this.orderBySQL.length() > 0) {
			this.orderBySQL.append(',');
		}
		String trueColumnName = mapColumn(columnName);
		this.orderBySQL.append(' ').append(trueColumnName).append(' ').append(orderBy.toString());
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param orderBy
	 * @return
	 */
	public  FS order(TypeFunction lambda, OrderBy orderBy) {
		return order(LambdaUtil.getLambdaFieldName(lambda), orderBy);
	}

	/**
	 * Update columns set value
	 *
	 * @param column column name
	 * @param value  column value
	 * @return SqlGenerator
	 */
	public FS set(String column, Object value) {
		String trueColumnName = mapColumn(column);
		updateColumns.put(trueColumnName, value);
		return this;
	}

	/**
	 * 更新字段自增
	 * 
	 * @param column
	 * @param count
	 * @return
	 */
	public FS inc(String column, Number count) {
		String trueColumnName = mapColumn(column);
		String exp = trueColumnName + " + " + count;
		setExp(trueColumnName, exp);
		return this;
	}

	/**
	 * 更新字段自增
	 * 
	 * @param lambda
	 * @param count
	 * @return
	 */
	public  FS inc(TypeFunction lambda, Number count) {
		return inc(LambdaUtil.getLambdaFieldName(lambda), count);
	}

	/**
	 * 更新字段自减
	 * 
	 * @param column
	 * @param count
	 * @return
	 */
	public FS dec(String column, Number count) {
		String trueColumnName = mapColumn(column);
		String exp = trueColumnName + " - " + count;
		setExp(trueColumnName, exp);
		return this;
	}

	/**
	 * 更新字段自减
	 * 
	 * @param lambda
	 * @param count
	 * @return
	 */
	public  FS dec(TypeFunction lambda, Number count) {
		return dec(LambdaUtil.getLambdaFieldName(lambda), count);
	}

	/**
	 * 更新字段自增 1
	 * 
	 * @param column
	 * @param count
	 * @return
	 */
	public FS inc(String column) {
		return inc(column, 1);
	}

	/**
	 * 更新字段自增 1
	 * 
	 * @param lambda
	 * @return
	 */
	public  FS inc(TypeFunction lambda) {
		return inc(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * 更新字段自减 1
	 * 
	 * @param column
	 * @return
	 */
	public FS dec(String column) {
		return dec(column, 1);
	}

	/**
	 * 更新字段自减 1
	 * 
	 * @param lambda
	 * @return
	 */
	public  FS dec(TypeFunction lambda) {
		return dec(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * 更新字段为native sql
	 * 
	 * @param column
	 * @param exp    native sql表达式
	 * @return
	 */
	public FS setExp(String column, String exp) {
		String trueColumnName = mapColumn(column);
		updateColumnExpression.put(trueColumnName, exp);
		return this;
	}

	/**
	 * 
	 * @param lambda
	 * @param value
	 * @return
	 */
	public  FS set(TypeFunction lambda, Object value) {
		return set(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/**
	 * 更新字段为native sql
	 * 
	 * @param lambda
	 * @param exp
	 * @return
	 */
	public  FS setExp(TypeFunction lambda, String exp) {
		return setExp(LambdaUtil.getLambdaFieldName(lambda), exp);
	}

	public FS set(T model) {
		this.model = model;
		return this;
	}

	/**
	 * Update a model
	 *
	 * @param model model instance
	 * @param 
	 * @return affect the number of rows
	 */

	private void setArguments(Object[] args) {
		for (int i = 0; i < args.length; i++) {
			if (i == args.length - 1) {
				conditionSQL.append("?");
			} else {
				conditionSQL.append("?, ");
			}
			paramValues.add(args[i]);
		}
	}

	/**
	 * pre check
	 */
	private void beforeCheck() {
		if (null == this.modelClass) {
			throw new HbatisException("model calss is null");
		}
	}

	public FS orNest(Function, FS> func) {
		return or().nest(func);
	}

	public FS andNest(Function, FS> func) {
		return and().nest(func);
	}

	public FS nest(Function, FS> func) {
		conditionSQL.append("(");
		func.apply(this);
		conditionSQL.append(")");
		return this;
	}

	public FS and() {
		conditionSQL.append(AND_STR);
		return this;
	}

	public FS or() {
		conditionSQL.append(" OR ");
		return this;
	}

	public FS eq(String column, Object value) {
		conditionSQL.append(mapColumn(column)).append(" = ?");
		paramValues.add(value);
		return this;
	}

	public  FS eq(TypeFunction lambda, Object value) {
		return eq(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	public FS andEq(String column, Object value) {
		conditionSQL.append(AND_STR).append(mapColumn(column)).append(" = ?");
		paramValues.add(value);
		return this;
	}

	public  FS andEq(TypeFunction lambda, Object value) {
		return andEq(LambdaUtil.getLambdaFieldName(lambda), value);
	}

	/////////// NEW API /////////
	public FS ltMeta(String column) {
		conditionSQL.append(" < ").append(mapColumn(column));
		return this;
	}

	public  FS ltMeta(TypeFunction lambda) {
		return ltMeta(LambdaUtil.getLambdaFieldName(lambda));
	}

	/**
	 * 条件添加表达式
	 * 
	 * @param exp native sql expression
	 * @return
	 */
	public FS exp(String exp) {
		conditionSQL.append(exp);
		return this;
	}

	/**
	 * 条件添加表达式
	 * 
	 * @param exp native sql expression
	 * @return
	 */
	public FS andExp(String exp) {
		conditionSQL.append(AND_STR).append(exp);
		return this;
	}

	/**
	 * 
	 * @param exp native sql expression
	 * @return
	 */
	public FS ltExp(String exp) {
		conditionSQL.append(" < ").append(exp);
		return this;
	}

	public FS lteMeta(String column) {
		conditionSQL.append(" <= ").append(mapColumn(column));
		return this;
	}

	public  FS lteMeta(TypeFunction lambda) {
		return lteMeta(LambdaUtil.getLambdaFieldName(lambda));
	}

	public FS lteExp(String exp) {
		conditionSQL.append(" <= ").append(exp);
		return this;
	}

	public FS ltMeta(String column1, String column2) {
		conditionSQL.append(mapColumn(column1)).append(" < ").append(mapColumn(column2));
		return this;
	}

	public FS andLtMeta(String column1, String column2) {
		conditionSQL.append(AND_STR).append(mapColumn(column1)).append(" < ").append(mapColumn(column2));
		return this;
	}

	public  FS ltMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return ltMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public  FS andLtMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return andLtMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public FS lteMeta(String column1, String column2) {
		conditionSQL.append(mapColumn(column1)).append(" <= ").append(mapColumn(column2));
		return this;
	}

	public FS andLteMeta(String column1, String column2) {
		conditionSQL.append(AND_STR).append(mapColumn(column1)).append(" <= ").append(mapColumn(column2));
		return this;
	}

	public  FS lteMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return lteMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public  FS andLteMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return andLteMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	/////// NEW API2 //////////
	public FS eqMeta(String column) {
		conditionSQL.append(" = ").append(mapColumn(column));
		return this;
	}

	public FS eqExp(String exp) {
		conditionSQL.append(" = ").append(exp);
		return this;
	}

	public  FS eqMeta(TypeFunction lambda) {
		return eqMeta(LambdaUtil.getLambdaFieldName(lambda));
	}

	public FS eqMeta(String column1, String column2) {
		conditionSQL.append(mapColumn(column1)).append(" = ").append(mapColumn(column2));
		return this;
	}

	public FS andEqMeta(String column1, String column2) {
		conditionSQL.append(AND_STR).append(mapColumn(column1)).append(" = ").append(mapColumn(column2));
		return this;
	}

	public  FS eqMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return eqMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public  FS andEqMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return andEqMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	///////// NEW API3 //////////
	public FS gtMeta(String column) {
		conditionSQL.append(" > ").append(mapColumn(column));
		return this;
	}

	public FS gtExp(String exp) {
		conditionSQL.append(" > ").append(exp);
		return this;
	}

	public  FS gtMeta(TypeFunction lambda) {
		return gtMeta(LambdaUtil.getLambdaFieldName(lambda));
	}

	public FS gtMeta(String column1, String column2) {
		conditionSQL.append(mapColumn(column1)).append(" > ").append(mapColumn(column2));
		return this;
	}

	public FS andGtMeta(String column1, String column2) {
		conditionSQL.append(AND_STR).append(mapColumn(column1)).append(" > ").append(mapColumn(column2));
		return this;
	}

	public  FS gtMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return gtMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public  FS andGtMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return andGtMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public FS gteMeta(String column) {
		conditionSQL.append(" >= ").append(mapColumn(column));
		return this;
	}

	public FS gteExp(String exp) {
		conditionSQL.append(" >= ").append(exp);
		return this;
	}

	public  FS gteMeta(TypeFunction lambda) {
		return gteMeta(LambdaUtil.getLambdaFieldName(lambda));
	}

	public FS gteMeta(String column1, String column2) {
		conditionSQL.append(mapColumn(column1)).append(" >= ").append(mapColumn(column2));
		return this;
	}

	public FS andGteMeta(String column1, String column2) {
		conditionSQL.append(AND_STR).append(mapColumn(column1)).append(" >= ").append(mapColumn(column2));
		return this;
	}

	public  FS gteMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return gteMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public  FS andGteMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return andGteMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public FS notEqMeta(String column) {
		conditionSQL.append(" != ").append(mapColumn(column));
		return this;
	}

	public FS notEqExp(String exp) {
		conditionSQL.append(" != ").append(exp);
		return this;
	}

	public  FS notEqMeta(TypeFunction lambda) {
		return notEqMeta(LambdaUtil.getLambdaFieldName(lambda));
	}

	public FS notEqMeta(String column1, String column2) {
		conditionSQL.append(mapColumn(column1)).append(" != ").append(mapColumn(column2));
		return this;
	}

	public FS andNotEqMeta(String column1, String column2) {
		conditionSQL.append(AND_STR).append(mapColumn(column1)).append(" != ").append(mapColumn(column2));
		return this;
	}

	public  FS notEqMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return notEqMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}

	public  FS andNotEqMeta(TypeFunction lambda1, TypeFunction lambda2) {
		return andNotEqMeta(LambdaUtil.getLambdaFieldName(lambda1), LambdaUtil.getLambdaFieldName(lambda2));
	}
}