Browse Source

1、修改TSQL语句构建逻辑。
2、添加LIKE、NOT_LIKE、IS_NULL、IS_NOT_NULL常用方法。
3、addFilter及addFilterIfNeed 可以使用 and() andIf() 方法直接替代,语义看起来更明确。

yanghu 9 years ago
parent
commit
a5003068ce

+ 193 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisAbstractSQL.java

@@ -0,0 +1,193 @@
+package com.baomidou.mybatisplus;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <p>
+ * 重定义 AbstractSQL ,实现标准TSQL的 查询条件自定义
+ * </p>
+ *
+ * @author yanghu
+ * @Date 2016-08-22
+ */
+public abstract class MybatisAbstractSQL<T> {
+
+    private static final String AND = " AND ";
+    private static final String OR = " OR ";
+    private static final String AND_NEW = ") \nAND (";
+    private static final String OR_NEW = ") \nOR (";
+
+    /**
+     * SQL条件
+     */
+    private SQLCondition sql = new SQLCondition();
+
+    /**
+     * 子类泛型实现
+     *
+     * @return 泛型实例
+     */
+    public abstract T getSelf();
+
+    public T WHERE(String conditions) {
+        sql().where.add(conditions);
+        sql().lastList = sql().where;
+        return getSelf();
+    }
+
+    public T OR() {
+        sql().lastList.add(OR);
+        return getSelf();
+    }
+
+    public T OR_NEW() {
+        sql().lastList.add(OR_NEW);
+        return getSelf();
+    }
+
+    public T AND() {
+        sql().lastList.add(AND);
+        return getSelf();
+    }
+
+    public T AND_NEW() {
+        sql().lastList.add(AND_NEW);
+        return getSelf();
+    }
+
+    public T GROUP_BY(String columns) {
+        sql().groupBy.add(columns);
+        return getSelf();
+    }
+
+    public T HAVING(String conditions) {
+        sql().having.add(conditions);
+        sql().lastList = sql().having;
+        return getSelf();
+    }
+
+    public T ORDER_BY(String columns) {
+        sql().orderBy.add(columns);
+        return getSelf();
+    }
+
+    private SQLCondition sql() {
+        return sql;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sql().sql(sb);
+        return sb.toString();
+    }
+
+    /**
+     * SQL连接器
+     */
+    private static class SafeAppendable {
+        private final Appendable a;
+        private boolean empty = true;
+
+        public SafeAppendable(Appendable a) {
+            super();
+            this.a = a;
+        }
+
+        public SafeAppendable append(CharSequence s) {
+            try {
+                if (empty && s.length() > 0) {
+                    empty = false;
+                }
+                a.append(s);
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            return this;
+        }
+
+        public boolean isEmpty() {
+            return empty;
+        }
+
+    }
+
+    /**
+     * SQL条件类
+     */
+    private static class SQLCondition {
+
+        List<String> where = new ArrayList<String>();
+        List<String> having = new ArrayList<String>();
+        List<String> groupBy = new ArrayList<String>();
+        List<String> orderBy = new ArrayList<String>();
+        List<String> lastList = new ArrayList<String>();
+        List<String> andOr = new ArrayList<String>();
+
+        public SQLCondition() {
+            andOr.add(AND);
+            andOr.add(OR);
+            andOr.add(AND_NEW);
+            andOr.add(OR_NEW);
+        }
+
+        /**
+         * 构建SQL的条件
+         *
+         * @param builder     连接器
+         * @param keyword     TSQL中的关键字
+         * @param parts       SQL条件语句集合
+         * @param open        起始符号
+         * @param close       结束符号
+         * @param conjunction 连接条件
+         */
+        private void sqlClause(SafeAppendable builder, String keyword, List<String> parts, String open, String close,
+                               String conjunction) {
+            if (!parts.isEmpty()) {
+                if (!builder.isEmpty()) {
+                    builder.append("\n");
+                }
+
+                builder.append(keyword);
+                builder.append(" ");
+                builder.append(open);
+                String last = "__";
+                for (int i = 0, n = parts.size(); i < n; i++) {
+                    String part = parts.get(i);
+                    if (i > 0) {
+                        if (andOr.contains(part) || andOr.contains(last)) {
+                            builder.append(part);
+                            last = part;
+                            continue;
+                        } else {
+                            builder.append(conjunction);
+                        }
+                    }
+                    builder.append(part);
+                }
+                builder.append(close);
+            }
+        }
+
+        /**
+         * 按标准顺序连接并构建SQL
+         *
+         * @param builder 连接器
+         * @return
+         */
+        private String buildSQL(SafeAppendable builder) {
+            sqlClause(builder, "WHERE", where, "(", ")", AND);
+            sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
+            sqlClause(builder, "HAVING", having, "(", ")", AND);
+            sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
+            return builder.toString();
+        }
+
+        public String sql(Appendable a) {
+            SafeAppendable builder = new SafeAppendable(a);
+            return buildSQL(builder);
+        }
+    }
+}

+ 381 - 321
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/EntityWrapper.java

@@ -15,9 +15,10 @@
  */
 package com.baomidou.mybatisplus.mapper;
 
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 
+import java.text.MessageFormat;
+
 /**
  * <p>
  * Entity 对象封装操作类,定义T-SQL语法
@@ -26,329 +27,388 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @author hubin , yanghu , Dyang
  * @Date 2016-03-15
  */
-public class EntityWrapper<T> extends QueryFilter {
-
-	/**
-	 * WHERE关键字
-	 */
-	protected final String WHERE = " WHERE ";
-
-	/**
-	 * AND关键字
-	 */
-	protected final String AND = " AND ";
-
-	/**
-	 * OR关键字
-	 */
-	protected final String OR = " OR ";
-
-	/**
-	 * GROUP BY关键字
-	 */
-	protected final String GROUPBY = " GROUP BY ";
-
-	/**
-	 * HAVING关键字
-	 */
-	protected final String HAVING = " HAVING ";
-
-	/**
-	 * ORDER BY关键字
-	 */
-	protected final String ORDERBY = " ORDER BY ";
-
-	/**
-	 * ORDER BY语句中排序的 DESC关键字
-	 */
-	protected final String DESC = " DESC ";
-
-	/**
-	 * ORDER BY语句中排序的 ASC关键字
-	 */
-	protected final String ASC = " ASC ";
-
-	/**
-	 * 是否使用了 T-SQL 语法
-	 */
-	protected boolean tsql = false;
-
-	/**
-	 * 数据库表映射实体类
-	 */
-	protected T entity = null;
-
-	/**
-	 * SQL 查询字段内容,例如:id,name,age
-	 */
-	protected String sqlSelect = null;
-
-	public EntityWrapper() {
-		// to do nothing
-	}
-
-	public EntityWrapper(T entity) {
-		this.entity = entity;
-	}
-
-	public EntityWrapper(T entity, String sqlSelect) {
-		this.entity = entity;
-		this.sqlSelect = sqlSelect;
-	}
-
-	public T getEntity() {
-		return entity;
-	}
-
-	public void setEntity(T entity) {
-		this.entity = entity;
-	}
-
-	public String getSqlSelect() {
-		if (StringUtils.isEmpty(sqlSelect)) {
-			return null;
-		}
-		return stripSqlInjection(sqlSelect);
-	}
-
-	public void setSqlSelect(String sqlSelect) {
-		if (StringUtils.isNotEmpty(sqlSelect)) {
-			this.sqlSelect = sqlSelect;
-		}
-	}
-
-	/**
-	 * SQL 片段
-	 */
-	public String getSqlSegment() {
-		/*
-		 * 无条件
+public class EntityWrapper<T> {
+
+    /**
+     * 数据库表映射实体类
+     */
+    protected T entity = null;
+
+    /**
+     * SQL 查询字段内容,例如:id,name,age
+     */
+    protected String sqlSelect = null;
+
+    /**
+     * 实现了TSQL语法的SQL实体
+     */
+    protected TSQLPlus sql = new TSQLPlus();
+
+
+    public EntityWrapper() {
+
+    }
+
+    public EntityWrapper(T entity) {
+        this.entity = entity;
+    }
+
+    public EntityWrapper(T entity, String sqlSelect) {
+        this.entity = entity;
+        this.sqlSelect = sqlSelect;
+    }
+
+    public T getEntity() {
+        return entity;
+    }
+
+    public void setEntity(T entity) {
+        this.entity = entity;
+    }
+
+    public String getSqlSelect() {
+        if (StringUtils.isEmpty(sqlSelect)) {
+            return null;
+        }
+        return stripSqlInjection(sqlSelect);
+    }
+
+    public void setSqlSelect(String sqlSelect) {
+        if (StringUtils.isNotEmpty(sqlSelect)) {
+            this.sqlSelect = sqlSelect;
+        }
+    }
+
+    /**
+     * SQL 片段
+     */
+    public String getSqlSegment() {
+        /*
+         * 无条件
 		 */
-		String tempQuery = queryFilter.toString();
-		if (StringUtils.isEmpty(tempQuery)) {
-			return null;
-		}
+        String sqlWhere = sql.toString();
+        if (StringUtils.isEmpty(sqlWhere)) {
+            return null;
+        }
 
-		/*
-		 * 只排序、直接返回
-		 */
-		if (tempQuery.trim().toUpperCase().indexOf("ORDER BY") == 0) {
-			return stripSqlInjection(queryFilter.toString());
-		}
+        // 根据当前实体判断是否需要将WHERE替换成AND
+        sqlWhere = (null != entity) ? sqlWhere.replaceFirst("WHERE", "AND") : sqlWhere;
 
-		/*
-		 * SQL 片段,兼容非 T-SQL 语法
-		 */
-		if (!tsql) {
-			StringBuffer sqlSegment = new StringBuffer();
-			if (null == this.getEntity()) {
-				sqlSegment.append(WHERE);
-			} else {
-				sqlSegment.append(AND);
-			}
-			sqlSegment.append(queryFilter.toString());
-			return stripSqlInjection(sqlSegment.toString());
-		}
-
-		/*
-		 * 使用防SQL注入处理后返回
-		 */
-		return stripSqlInjection(queryFilter.toString());
-	}
-
-	/**
-	 * <p>
-	 * SQL中WHERE关键字跟的条件语句
-	 * </p>
-	 * <p>
-	 * eg: ew.where("name='zhangsan'").and("id={0}",22).and(
-	 * "password is not null")
-	 * </p>
-	 *
-	 * @param sqlWhere
-	 *            where语句
-	 * @param params
-	 *            参数集
-	 * @return
-	 */
-	public EntityWrapper<T> where(String sqlWhere, Object... params) {
-		if (tsql) {
-			throw new MybatisPlusException("SQL already contains the string where.");
-		}
-		/*
-		 * 使用 T-SQL 语法
+        /*
+         * 使用防SQL注入处理后返回
 		 */
-		tsql = true;
-		if (null == this.getEntity()) {
-			addFilter(WHERE, sqlWhere, params);
-		} else {
-			addFilter(AND, sqlWhere, params);
-		}
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中 AND 关键字跟的条件语句
-	 * </p>
-	 * <p>
-	 * eg: ew.where("name='zhangsan'").and("id={0}",22).and(
-	 * "password is not null")
-	 * </p>
-	 *
-	 * @param sqlAnd
-	 *            and连接串
-	 * @param params
-	 *            参数集
-	 * @return
-	 */
-	public EntityWrapper<T> and(String sqlAnd, Object... params) {
-		addFilter(AND, sqlAnd, params);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 与 AND 方法的区别是 可根据需要判断是否添加该条件
-	 * </p>
-	 *
-	 * @param need
-	 *            是否需要使用该and条件
-	 * @param sqlAnd
-	 *            and条件语句
-	 * @param params
-	 *            参数集
-	 * @return
-	 */
-	public EntityWrapper<T> andIfNeed(boolean need, String sqlAnd, Object... params) {
-		addFilterIfNeed(need, AND, sqlAnd, params);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中AND关键字跟的条件语句
-	 * </p>
-	 * <p>
-	 * eg: ew.where("name='zhangsan'").or("password is not null")
-	 * </p>
-	 *
-	 * @param sqlOr
-	 *            or条件语句
-	 * @param params
-	 *            参数集
-	 * @return
-	 */
-	public EntityWrapper<T> or(String sqlOr, Object... params) {
-		addFilter(OR, sqlOr, params);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 与or方法的区别是 可根据需要判断是否添加该条件
-	 * </p>
-	 *
-	 * @param need
-	 *            是否需要使用OR条件
-	 * @param sqlOr
-	 *            OR条件语句
-	 * @param params
-	 *            参数集
-	 * @return
-	 */
-	public EntityWrapper<T> orIfNeed(boolean need, String sqlOr, Object... params) {
-		addFilterIfNeed(need, OR, sqlOr, params);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中groupBy关键字跟的条件语句
-	 * </p>
-	 * <p>
-	 * eg: ew.where("name='zhangsan'").and("id={0}",22).and(
-	 * "password is not null") .groupBy("id,name")
-	 * </p>
-	 *
-	 * @param sqlGroupBy
-	 *            SQL 中的 Group by 语句,无需输入 Group By 关键字
-	 * @return this
-	 */
-	public EntityWrapper<T> groupBy(String sqlGroupBy) {
-		addFilter(GROUPBY, sqlGroupBy);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中having关键字跟的条件语句
-	 * </p>
-	 * <p>
-	 * eg: ew.groupBy("id,name").having("id={0}",22).and("password is not null")
-	 * </p>
-	 *
-	 * @param sqlHaving
-	 *            having关键字后面跟随的语句
-	 * @param params
-	 *            参数集
-	 * @return EntityWrapper
-	 */
-	public EntityWrapper<T> having(String sqlHaving, Object... params) {
-		addFilter(HAVING, sqlHaving, params);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中orderby关键字跟的条件语句
-	 * </p>
-	 * <p>
-	 * eg: ew.groupBy("id,name").having("id={0}",22).and("password is not null"
-	 * ).orderBy("id,name")
-	 * </p>
-	 *
-	 * @param sqlOrderBy
-	 *            SQL 中的 order by 语句,无需输入 Order By 关键字
-	 * @return this
-	 */
-	public EntityWrapper<T> orderBy(String sqlOrderBy) {
-		addFilter(ORDERBY, sqlOrderBy);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中orderby关键字跟的条件语句,可根据变更动态排序
-	 * </p>
-	 *
-	 * @param sqlOrderBy
-	 *            SQL 中的 order by 语句,无需输入 Order By 关键字
-	 * @param isAsc
-	 *            是否为升序
-	 * @return
-	 */
-	public EntityWrapper<T> orderBy(String sqlOrderBy, boolean isAsc) {
-		addFilter(ORDERBY, sqlOrderBy);
-		if (isAsc) {
-			queryFilter.append(ASC);
-		} else {
-			queryFilter.append(DESC);
-		}
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL注入内容剥离
-	 * </p>
-	 *
-	 * @param value
-	 *            待处理内容
-	 * @return
-	 */
-	protected String stripSqlInjection(String value) {
-		return value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
-	}
+        return stripSqlInjection(sqlWhere);
+    }
+
+    /**
+     * <p>
+     * SQL中WHERE关键字跟的条件语句
+     * </p>
+     * <p>
+     * eg: ew.where("name='zhangsan'").where("id={0}","123");
+     * <p>
+     * 输出: WHERE (NAME='zhangsan' AND id=123)
+     * </p>
+     *
+     * @param sqlWhere where语句
+     * @param params   参数集
+     * @return this
+     */
+    public EntityWrapper<T> where(String sqlWhere, Object... params) {
+        String sqlPart = formatSql(sqlWhere, params);
+        if (retNeed(sqlPart)) {
+            sql.WHERE(sqlPart);
+        }
+        return this;
+    }
+
+    /**
+     * <p>
+     * AND  连接后续条件
+     * </p>
+     *
+     * @param sqlAnd and条件语句
+     * @param params 参数集
+     * @return this
+     */
+    public EntityWrapper<T> and(String sqlAnd, Object... params) {
+        return where(sqlAnd, params);
+    }
+
+    /**
+     * <p>
+     * 动态判断是否需要添加条件语句
+     * </p>
+     *
+     * @param sqlAnd and条件语句
+     * @param params 参数集
+     * @return this
+     */
+    public EntityWrapper<T> andIf(boolean need, String sqlAnd, Object... params) {
+        return need ? where(sqlAnd, params) : this;
+    }
+
+    /**
+     * <p>
+     * 使用AND连接并换行
+     * </p>
+     * <p>
+     * eg: ew.where("name='zhangsan'").and("id=11").andNew("statu=1");
+     * 输出:
+     * WHERE (name='zhangsan' AND id=11)
+     * AND (statu=1)
+     * </p>
+     *
+     * @param sqlAnd AND 条件语句
+     * @param params 参数值
+     * @return this
+     */
+    public EntityWrapper<T> andNew(String sqlAnd, Object... params) {
+        String sqlPart = formatSql(sqlAnd, params);
+        if (retNeed(sqlPart)) {
+            sql.AND_NEW().WHERE(sqlPart);
+        }
+        return this;
+    }
+
+    /**
+     * <p>
+     * 添加OR条件
+     * </p>
+     *
+     * @param sqlOr  or 条件语句
+     * @param params 参数集
+     * @return
+     */
+    public EntityWrapper<T> or(String sqlOr, Object... params) {
+        String sqlPart = formatSql(sqlOr, params);
+        if (retNeed(sqlPart)) {
+            sql.OR().WHERE(sqlPart);
+        }
+        return this;
+    }
+
+    /**
+     * <p>
+     * 使用OR换行,并添加一个带()的新的条件
+     * </p>
+     * <p>
+     * eg: ew.where("name='zhangsan'").and("id=11").orNew("statu=1");
+     * 输出:
+     * WHERE (name='zhangsan' AND id=11)
+     * OR (statu=1)
+     * </p>
+     *
+     * @param sqlOr  AND 条件语句
+     * @param params 参数值
+     * @return this
+     */
+    public EntityWrapper<T> orNew(String sqlOr, Object... params) {
+        String sqlPart = formatSql(sqlOr, params);
+        if (retNeed(sqlPart)) {
+            sql.OR_NEW().WHERE(sqlPart);
+        }
+        return this;
+    }
+
+    /**
+     * <p>
+     * SQL中groupBy关键字跟的条件语句
+     * </p>
+     * <p>
+     * eg: ew.where("name='zhangsan'").groupBy("id,name")
+     * </p>
+     *
+     * @param columns SQL 中的 Group by 语句,无需输入 Group By 关键字
+     * @return this
+     */
+    public EntityWrapper<T> groupBy(String columns) {
+        sql.GROUP_BY(columns);
+        return this;
+    }
+
+    /**
+     * <p>
+     * SQL中having关键字跟的条件语句
+     * </p>
+     * <p>
+     * eg: ew.groupBy("id,name").having("id={0}",22).and("password is not null")
+     * </p>
+     *
+     * @param sqlHaving having关键字后面跟随的语句
+     * @param params    参数集
+     * @return EntityWrapper
+     */
+    public EntityWrapper<T> having(String sqlHaving, Object... params) {
+        String sqlPart = formatSql(sqlHaving, params);
+        if (retNeed(sqlPart)) {
+            sql.HAVING(sqlPart);
+        }
+        return this;
+    }
+
+    /**
+     * <p>
+     * SQL中orderby关键字跟的条件语句
+     * </p>
+     * <p>
+     * eg: ew.groupBy("id,name").having("id={0}",22).and("password is not null"
+     * ).orderBy("id,name")
+     * </p>
+     *
+     * @param columns SQL 中的 order by 语句,无需输入 Order By 关键字
+     * @return this
+     */
+    public EntityWrapper<T> orderBy(String columns) {
+        sql.ORDER_BY(columns);
+        return this;
+    }
+
+    /**
+     * <p>
+     * SQL中orderby关键字跟的条件语句,可根据变更动态排序
+     * </p>
+     *
+     * @param columns SQL 中的 order by 语句,无需输入 Order By 关键字
+     * @param isAsc   是否为升序
+     * @return
+     */
+    public EntityWrapper<T> orderBy(String columns, boolean isAsc) {
+        sql.ORDER_BY(columns + (isAsc ? " ASC" : " DESC"));
+        return this;
+    }
+
+    /**
+     * LIKE条件语句,value中无需前后% 目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  匹配值
+     * @return
+     */
+    public EntityWrapper<T> like(String column, String value) {
+        sql.LIKE(column, value);
+        return this;
+    }
+
+    /**
+     * NOT LIKE条件语句,value中无需前后% 目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  匹配值
+     * @return
+     */
+    public EntityWrapper<T> notLike(String column, String value) {
+        sql.NOT_LIKE(column, value);
+        return this;
+    }
+
+    /**
+     * is not null 条件
+     *
+     * @param columns 字段名称。多个字段以逗号分隔。
+     * @return
+     */
+    public EntityWrapper<T> isNotNull(String columns) {
+        sql.IS_NOT_NULL(columns);
+        return this;
+    }
+
+    /**
+     * is not null 条件
+     *
+     * @param columns 字段名称。多个字段以逗号分隔。
+     * @return
+     */
+    public EntityWrapper<T> isNull(String columns) {
+        sql.IS_NULL(columns);
+        return this;
+    }
+
+
+    /**
+     * 为了兼容之前的版本,可使用where()或and()替代
+     *
+     * @param sqlWhere where sql部分
+     * @param params   参数集
+     * @return this
+     */
+//    @Deprecated
+    public EntityWrapper<T> addFilter(String sqlWhere, Object... params) {
+        return and(sqlWhere, params);
+    }
+
+    /**
+     * <p>
+     * 根据判断条件来添加条件语句部分     使用 andIf() 替代
+     * </p>
+     * <p>
+     * eg: ew.filterIfNeed(false,"name='zhangsan'").where("name='zhangsan'")
+     * .filterIfNeed(true,"id={0}",22)
+     * <p>
+     * 输出: WHERE (name='zhangsan' AND id=22)
+     * </p>
+     *
+     * @param need     是否需要添加该条件
+     * @param sqlWhere 条件语句
+     * @param params   参数集
+     * @return this
+     */
+//    @Deprecated
+    public EntityWrapper<T> addFilterIfNeed(boolean need, String sqlWhere, Object... params) {
+        return andIf(need, sqlWhere, params);
+    }
+
+    /**
+     * <p>
+     * SQL注入内容剥离
+     * </p>
+     *
+     * @param value 待处理内容
+     * @return
+     */
+    protected String stripSqlInjection(String value) {
+        return value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
+    }
+
+
+    /**
+     * formatSql的结果如果返回NULL,就会产生WHERE(NULL) 这样的结果
+     * 所以此处要判断后,根据结果来添加当前关键字处理
+     *
+     * @param sqlPart 当前SQL语句
+     * @return boolean
+     */
+    private boolean retNeed(String sqlPart) {
+        return StringUtils.isNotEmpty(sqlPart);
+    }
+
+    /**
+     * 格式化SQL
+     *
+     * @param sqlStr SQL语句部分
+     * @param params 参数集
+     * @return
+     */
+    private String formatSql(String sqlStr, Object... params) {
+        return formatSqlIfNeed(true, sqlStr, params);
+    }
+
+    /**
+     * 根据需要格式化SQL
+     *
+     * @param need   是否需要格式化
+     * @param sqlStr SQL语句部分
+     * @param params 参数集
+     * @return
+     */
+    private String formatSqlIfNeed(boolean need, String sqlStr, Object... params) {
+        if (!need || StringUtils.isEmpty(sqlStr)) {
+            return null;
+        }
+        if (null != params && params.length > 0) {
+            sqlStr = MessageFormat.format(sqlStr, params);
+        }
+        return sqlStr;
+    }
 
 }

+ 107 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/TSQLPlus.java

@@ -0,0 +1,107 @@
+package com.baomidou.mybatisplus.mapper;
+
+import com.baomidou.mybatisplus.MybatisAbstractSQL;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+
+import java.text.MessageFormat;
+
+/**
+ * <p>
+ * 实现AbstractSQL ,实现WHERE条件自定义
+ * </p>
+ *
+ * @author yanghu
+ * @Date 2016-08-22
+ */
+public class TSQLPlus extends MybatisAbstractSQL<TSQLPlus> {
+
+    private final String IS_NOT_NULL = " IS NOT NULL";
+    private final String IS_NULL = " IS NULL";
+
+    @Override
+    public TSQLPlus getSelf() {
+        return this;
+    }
+
+    /**
+     * 将LIKE语句添加到WHERE条件中
+     *
+     * @param column 字段名
+     * @param value  like值,无需前后%, MYSQL及ORACEL通用
+     * @return
+     */
+    public TSQLPlus LIKE(String column, String value) {
+        handerLike(column, value, false);
+        return this;
+    }
+
+    /**
+     * 将LIKE语句添加到WHERE条件中
+     *
+     * @param column 字段名
+     * @param value  like值,无需前后%, MYSQL及ORACEL通用
+     * @return
+     */
+    public TSQLPlus NOT_LIKE(String column, String value) {
+        handerLike(column, value, true);
+        return this;
+    }
+
+    /**
+     * IS NOT NULL查询
+     *
+     * @param columns 以逗号分隔的字段名称
+     * @return this
+     */
+    public TSQLPlus IS_NOT_NULL(String columns) {
+        handerNull(columns, IS_NOT_NULL);
+        return this;
+    }
+
+    /**
+     * IS NULL查询
+     *
+     * @param columns 以逗号分隔的字段名称
+     * @return
+     */
+    public TSQLPlus IS_NULL(String columns) {
+        handerNull(columns, IS_NULL);
+        return this;
+    }
+
+    /**
+     * 处理LIKE操作
+     *
+     * @param column 字段名称
+     * @param value  like匹配值
+     * @param isNot  是否为NOT LIKE操作
+     */
+    private void handerLike(String column, String value, boolean isNot) {
+        if (StringUtils.isNotEmpty(column) && StringUtils.isNotEmpty(value)) {
+            String likeSql = " LIKE CONCAT(CONCAT({0},{1}),{2})";
+            if (isNot) {
+                likeSql = " NOT" + likeSql;
+            }
+            String percent = StringUtils.quotaMark("%");
+            WHERE(column + MessageFormat.format(likeSql, percent, StringUtils.quotaMark(value), percent));
+        }
+    }
+
+    /**
+     * 以相同的方式处理null和notnull
+     *
+     * @param columns 以逗号分隔的字段名称
+     * @param sqlPart SQL部分
+     */
+    private void handerNull(String columns, String sqlPart) {
+        if (StringUtils.isNotEmpty(columns)) {
+            String[] cols = columns.split(",");
+            for (String col : cols) {
+                if (StringUtils.isNotEmpty(col.trim())) {
+                    WHERE(col + sqlPart);
+                }
+            }
+        }
+    }
+
+}

+ 115 - 110
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/StringUtils.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2014, hubin (jobob@qq.com).
- *
+ * <p>
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- *
+ * <p>
  * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -28,117 +28,122 @@ import java.util.regex.Pattern;
  */
 public class StringUtils {
 
-	/**
-	 * 下划线字符
-	 */
-	public static final char UNDERLINE = '_';
+    /**
+     * 下划线字符
+     */
+    public static final char UNDERLINE = '_';
+
+    /**
+     * <p>
+     * 判断字符串是否为空
+     * </p>
+     *
+     * @param str 需要判断字符串
+     * @return 判断结果
+     */
+    public static boolean isEmpty(String str) {
+        return str == null || "".equals(str.trim());
+    }
 
-	/**
-	 * <p>
-	 * 判断字符串是否为空
-	 * </p>
-	 *
-	 * @param str
-	 *            需要判断字符串
-	 * @return 判断结果
-	 */
-	public static boolean isEmpty(String str) {
-		return str == null || "".equals(str.trim());
-	}
+    /**
+     * <p>
+     * 判断字符串是否不为空
+     * </p>
+     *
+     * @param str 需要判断字符串
+     * @return 判断结果
+     */
+    public static boolean isNotEmpty(String str) {
+        return (str != null) && !"".equals(str.trim());
+    }
 
-	/**
-	 * <p>
-	 * 判断字符串是否不为空
-	 * </p>
-	 *
-	 * @param str
-	 *            需要判断字符串
-	 * @return 判断结果
-	 */
-	public static boolean isNotEmpty(String str) {
-		return (str != null) && !"".equals(str.trim());
-	}
+    /**
+     * <p>
+     * 字符串驼峰转下划线格式
+     * </p>
+     *
+     * @param param 需要转换的字符串
+     * @return 转换好的字符串
+     */
+    public static String camelToUnderline(String param) {
+        if (StringUtils.isEmpty(param)) {
+            return "";
+        }
+        int len = param.length();
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            char c = param.charAt(i);
+            if (Character.isUpperCase(c) && i > 0) {
+                sb.append(UNDERLINE);
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
 
-	/**
-	 * <p>
-	 * 字符串驼峰转下划线格式
-	 * </p>
-	 *
-	 * @param param
-	 *            需要转换的字符串
-	 * @return 转换好的字符串
-	 */
-	public static String camelToUnderline(String param) {
-		if (StringUtils.isEmpty(param)) {
-			return "";
-		}
-		int len = param.length();
-		StringBuilder sb = new StringBuilder(len);
-		for (int i = 0; i < len; i++) {
-			char c = param.charAt(i);
-			if (Character.isUpperCase(c) && i > 0) {
-				sb.append(UNDERLINE);
-			}
-			sb.append(Character.toLowerCase(c));
-		}
-		return sb.toString();
-	}
+    /**
+     * <p>
+     * 字符串下划线转驼峰格式
+     * </p>
+     *
+     * @param param 需要转换的字符串
+     * @return 转换好的字符串
+     */
+    public static String underlineToCamel(String param) {
+        if (isEmpty(param)) {
+            return "";
+        }
+        int len = param.length();
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            char c = param.charAt(i);
+            if (c == UNDERLINE) {
+                if (++i < len) {
+                    sb.append(Character.toUpperCase(param.charAt(i)));
+                }
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
 
-	/**
-	 * <p>
-	 * 字符串下划线转驼峰格式
-	 * </p>
-	 *
-	 * @param param
-	 *            需要转换的字符串
-	 * @return 转换好的字符串
-	 */
-	public static String underlineToCamel(String param) {
-		if (isEmpty(param)) {
-			return "";
-		}
-		int len = param.length();
-		StringBuilder sb = new StringBuilder(len);
-		for (int i = 0; i < len; i++) {
-			char c = param.charAt(i);
-			if (c == UNDERLINE) {
-				if (++i < len) {
-					sb.append(Character.toUpperCase(param.charAt(i)));
-				}
-			} else {
-				sb.append(c);
-			}
-		}
-		return sb.toString();
-	}
+    /**
+     * <p>
+     * 判断字符串是否为纯大写字母
+     * </p>
+     *
+     * @param str 要匹配的字符串
+     * @return
+     */
+    public static boolean isUpperCase(String str) {
+        return match("^[A-Z]+$", str);
+    }
 
-	/**
-	 * <p>
-	 * 判断字符串是否为纯大写字母
-	 * </p>
-	 * 
-	 * @param str
-	 *            要匹配的字符串
-	 * @return
-	 */
-	public static boolean isUpperCase(String str) {
-		return match("^[A-Z]+$", str);
-	}
+    /**
+     * <p>
+     * 正则表达式匹配
+     * </p>
+     *
+     * @param regex 正则表达式字符串
+     * @param str   要匹配的字符串
+     * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
+     */
+    public static boolean match(String regex, String str) {
+        Pattern pattern = Pattern.compile(regex);
+        Matcher matcher = pattern.matcher(str);
+        return matcher.matches();
+    }
 
-	/**
-	 * <p>
-	 * 正则表达式匹配
-	 * </p>
-	 * 
-	 * @param regex
-	 *            正则表达式字符串
-	 * @param str
-	 *            要匹配的字符串
-	 * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
-	 */
-	public static boolean match(String regex, String str) {
-		Pattern pattern = Pattern.compile(regex);
-		Matcher matcher = pattern.matcher(str);
-		return matcher.matches();
-	}
+    /**
+     * <p>
+     * 使用单引号包含字符串
+     * </p>
+     *
+     * @param srcStr 原字符串
+     * @return 单引号包含的原字符串
+     */
+    public static String quotaMark(String srcStr) {
+        return isEmpty(srcStr) ? "" : "\'" + srcStr + "\'";
+    }
 }

+ 103 - 78
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/EntityWrapperTest.java

@@ -31,97 +31,122 @@ import com.baomidou.mybatisplus.test.mysql.entity.User;
  */
 public class EntityWrapperTest {
 
-	/*
-	 * User 查询包装器
-	 */
-	private EntityWrapper<User> ew = new EntityWrapper<User>();
+    /*
+     * User 查询包装器
+     */
+    private EntityWrapper<User> ew = new EntityWrapper<User>();
 
-	@Test
-	public void test() {
-		/*
-		 * 无条件测试
+    @Test
+    public void test() {
+        /*
+         * 无条件测试
 		 */
-		Assert.assertNull(ew.getSqlSegment());
-	}
+        Assert.assertNull(ew.getSqlSegment());
+    }
 
-	@Test
-	public void test11() {
-		ew.setEntity(new User(1));
-		ew.where("name={0}", "'123'").andIfNeed(false, "id=12");
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("test11 = " + sqlSegment);
-		Assert.assertEquals(" AND name='123'", sqlSegment);
-	}
+    @Test
+    public void test11() {
+        /*
+         * 实体带where   ifneed
+         */
+        ew.setEntity(new User(1));
+        ew.where("name={0}", "'123'").addFilterIfNeed(false, "id=12");
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("test11 = " + sqlSegment);
+        Assert.assertEquals("AND (name='123')", sqlSegment);
+    }
 
-	@Test
-	public void test12() {
-		ew.setEntity(new User(1));
-		ew.where("name={0}", "'123'").orderBy("id", false);
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("test12 = " + sqlSegment);
-		Assert.assertEquals(" AND name='123' ORDER BY id DESC ", sqlSegment);
-	}
+    @Test
+    public void test12() {
+        /*
+         * 实体带where orderby
+         */
+        ew.setEntity(new User(1));
+        ew.where("name={0}", "'123'").orderBy("id", false);
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("test12 = " + sqlSegment);
+        Assert.assertEquals("AND (name='123')\nORDER BY id DESC", sqlSegment);
+    }
 
-	@Test
-	public void test13() {
-		/*
-		 * 存在实体查询,只排序
+    @Test
+    public void test13() {
+        /*
+         * 实体排序
 		 */
-		ew.setEntity(new User(1));
-		ew.orderBy("id", false);
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("test13 = " + sqlSegment);
-		Assert.assertEquals(" ORDER BY id DESC ", sqlSegment);
-	}
+        ew.setEntity(new User(1));
+        ew.orderBy("id", false);
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("test13 = " + sqlSegment);
+        Assert.assertEquals("ORDER BY id DESC", sqlSegment);
+    }
 
-	@Test
-	public void test21() {
-		ew.where("name={0}", "'123'").andIfNeed(false, "id=1").orderBy("id");
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("test21 = " + sqlSegment);
-		Assert.assertEquals(" WHERE name='123' ORDER BY id", sqlSegment);
-	}
+    @Test
+    public void test21() {
+        /*
+         * 无实体 where ifneed orderby
+         */
+        ew.where("name={0}", "'123'").addFilterIfNeed(false, "id=1").orderBy("id");
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("test21 = " + sqlSegment);
+        Assert.assertEquals("WHERE (name='123')\nORDER BY id", sqlSegment);
+    }
 
-	@Test
-	public void test22() {
-		ew.where("name={0}", "'123'").orderBy("id", false);
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("test22 = " + sqlSegment);
-		Assert.assertEquals(" WHERE name='123' ORDER BY id DESC ", sqlSegment);
-	}
+    @Test
+    public void test22() {
+        ew.where("name={0}", "'123'").orderBy("id", false);
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("test22 = " + sqlSegment);
+        Assert.assertEquals("WHERE (name='123')\nORDER BY id DESC", sqlSegment);
+    }
 
-	@Test
-	public void test23() {
-		/*
-		 * 无实体查询,只排序
+    @Test
+    public void test23() {
+        /*
+         * 无实体查询,只排序
 		 */
-		ew.orderBy("id", false);
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("test23 = " + sqlSegment);
-		Assert.assertEquals(" ORDER BY id DESC ", sqlSegment);
-	}
+        ew.orderBy("id", false);
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("test23 = " + sqlSegment);
+        Assert.assertEquals("ORDER BY id DESC", sqlSegment);
+    }
 
-	@Test
-	public void testNoTSQL() {
-		/*
-		 * 非 T-SQL 实体查询
+    @Test
+    public void testNoTSQL() {
+        /*
+         * 实体 filter orderby
 		 */
-		ew.setEntity(new User(1));
-		ew.addFilter("name={0}", "'123'").addFilterIfNeed(true, " order by id");
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("testNoTSQL = " + sqlSegment);
-		Assert.assertEquals(" AND name='123' order by id", sqlSegment);
-	}
+        ew.setEntity(new User(1));
+        ew.addFilter("name={0}", "'123'").orderBy("id,name");
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("testNoTSQL = " + sqlSegment);
+        Assert.assertEquals("AND (name='123')\nORDER BY id,name", sqlSegment);
+    }
 
-	@Test
-	public void testNoTSQL1() {
-		/*
-		 * 非 T-SQL 无实体查询
+    @Test
+    public void testNoTSQL1() {
+        /*
+         * 非 T-SQL 无实体查询
 		 */
-		ew.addFilter("name={0}", "'123'").addFilterIfNeed(false, " order by id");
-		String sqlSegment = ew.getSqlSegment();
-		System.err.println("testNoTSQL1 = " + sqlSegment);
-		Assert.assertEquals(" WHERE name='123'", sqlSegment);
-	}
+        ew.addFilter("name={0}", "'123'").addFilterIfNeed(false, "status={1}", "1");
+        String sqlSegment = ew.getSqlSegment();
+        System.err.println("testNoTSQL1 = " + sqlSegment);
+        Assert.assertEquals("WHERE (name='123')", sqlSegment);
+    }
 
+    @Test
+    public void testTSQL11() {
+        /*
+         * 实体带查询使用方法  输出看结果
+         */
+        ew.setEntity(new User(1));
+        ew.where("name={0}", "'zhangsan'").and("id=1")
+                .orNew("status={0}", "0").or("status=1")
+                .notLike("nlike","notvalue")
+                .andNew("new=xx").like("hhh", "ddd")
+                .andNew("pwd=11").isNotNull("n1,n2").isNull("n3")
+                .groupBy("x1").groupBy("x2,x3")
+                .having("x1=11").having("x3=433")
+                .orderBy("dd").orderBy("d1,d2");
+        System.out.println(ew.getSqlSegment());
+    }
 }