Browse Source

Merge branch 'dev'

Caratacus 8 years ago
parent
commit
53a15af3e7

+ 24 - 36
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/PerformanceInterceptor.java

@@ -16,6 +16,8 @@
 package com.baomidou.mybatisplus.plugins;
 
 import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.toolkit.SqlUtils;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
 import com.baomidou.mybatisplus.toolkit.SystemClock;
 import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.mapping.BoundSql;
@@ -33,8 +35,7 @@ import org.apache.ibatis.session.ResultHandler;
 import org.apache.ibatis.session.RowBounds;
 import org.apache.ibatis.type.TypeHandlerRegistry;
 
-import java.text.SimpleDateFormat;
-import java.util.Date;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
@@ -46,7 +47,9 @@ import java.util.Properties;
  * @author hubin
  * @Date 2016-07-07
  */
-@Intercepts({@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }),
+@Intercepts({
+		@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class,
+				ResultHandler.class }),
 		@Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
 public class PerformanceInterceptor implements Interceptor {
 
@@ -55,6 +58,8 @@ public class PerformanceInterceptor implements Interceptor {
 	 */
 	private long maxTime = 0;
 
+	private boolean format = false;
+
 	public Object intercept(Invocation invocation) throws Throwable {
 		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
 		Object parameterObject = null;
@@ -65,13 +70,16 @@ public class PerformanceInterceptor implements Interceptor {
 		String statementId = mappedStatement.getId();
 		BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
 		Configuration configuration = mappedStatement.getConfiguration();
-		String sql = getSql(boundSql, parameterObject, configuration);
+		String sql = SqlUtils.sqlFormat(boundSql.getSql(), format);
+
+		List<String> params = getParams(boundSql, parameterObject, configuration);
 
 		long start = SystemClock.now();
 		Object result = invocation.proceed();
 		long end = SystemClock.now();
 		long timing = end - start;
-		System.err.println(" Time:" + timing + " ms" + " - ID:" + statementId + "\n Execute SQL:" + sql + "\n");
+		System.err.println(" Time:" + timing + " ms" + " - ID:" + statementId + "\n SQL Params:" + params.toString()
+				+ "\n Execute SQL:" + sql + "\n");
 		if (maxTime >= 1 && timing > maxTime) {
 			throw new MybatisPlusException(" The SQL execution time is too large, please optimize ! ");
 		}
@@ -89,10 +97,10 @@ public class PerformanceInterceptor implements Interceptor {
 		// TODO
 	}
 
-	private String getSql(BoundSql boundSql, Object parameterObject, Configuration configuration) {
-		String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
+	private List<String> getParams(BoundSql boundSql, Object parameterObject, Configuration configuration) {
 		List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
 		TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
+		List<String> params = new ArrayList<String>();
 		if (parameterMappings != null) {
 			for (int i = 0; i < parameterMappings.size(); i++) {
 				ParameterMapping parameterMapping = parameterMappings.get(i);
@@ -109,38 +117,11 @@ public class PerformanceInterceptor implements Interceptor {
 						MetaObject metaObject = configuration.newMetaObject(parameterObject);
 						value = metaObject.getValue(propertyName);
 					}
-					sql = replacePlaceholder(sql, value);
+					params.add(StringUtils.sqlParam(value));
 				}
 			}
 		}
-		return sql;
-	}
-
-	private String replacePlaceholder(String sql, Object propertyValue) {
-		String result;
-		if (propertyValue != null) {
-			if (propertyValue instanceof String) {
-				result = "'" + propertyValue + "'";
-			} else if (propertyValue instanceof Date) {
-				result = "'" + dateToString(propertyValue) + "'";
-			} else {
-				result = propertyValue.toString();
-			}
-		} else {
-			result = "null";
-		}
-
-		/* 特殊处理 $ 符内容 */
-		if (null != result && result.contains("$")) {
-			return sql.replaceFirst("\\?", "[?]").replace("[?]", result);
-		}
-
-		/* 填充占位符 */
-		return sql.replaceFirst("\\?", result);
-	}
-
-	private synchronized String dateToString(Object obj) {
-		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(obj);
+		return params;
 	}
 
 	public long getMaxTime() {
@@ -151,4 +132,11 @@ public class PerformanceInterceptor implements Interceptor {
 		this.maxTime = maxTime;
 	}
 
+	public boolean isFormat() {
+		return format;
+	}
+
+	public void setFormat(boolean format) {
+		this.format = format;
+	}
 }

+ 372 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/SQLFormatter.java

@@ -0,0 +1,372 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
+ * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
+ */
+package com.baomidou.mybatisplus.plugins;
+
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * Performs formatting of basic SQL statements (DML + query).
+ * <P>
+ * Copy Hibernate BasicFormatterImpl
+ * </P>
+ * 
+ * @author Gavin King
+ * @author Steve Ebersole
+ */
+public class SQLFormatter {
+
+	private static final Set<String> BEGIN_CLAUSES = new HashSet<String>();
+	private static final Set<String> END_CLAUSES = new HashSet<String>();
+	private static final Set<String> LOGICAL = new HashSet<String>();
+	private static final Set<String> QUANTIFIERS = new HashSet<String>();
+	private static final Set<String> DML = new HashSet<String>();
+	private static final Set<String> MISC = new HashSet<String>();
+	public static final String WHITESPACE = " \n\r\f\t";
+
+	static {
+		BEGIN_CLAUSES.add("left");
+		BEGIN_CLAUSES.add("right");
+		BEGIN_CLAUSES.add("inner");
+		BEGIN_CLAUSES.add("outer");
+		BEGIN_CLAUSES.add("group");
+		BEGIN_CLAUSES.add("order");
+
+		END_CLAUSES.add("where");
+		END_CLAUSES.add("set");
+		END_CLAUSES.add("having");
+		END_CLAUSES.add("join");
+		END_CLAUSES.add("from");
+		END_CLAUSES.add("by");
+		END_CLAUSES.add("join");
+		END_CLAUSES.add("into");
+		END_CLAUSES.add("union");
+
+		LOGICAL.add("and");
+		LOGICAL.add("or");
+		LOGICAL.add("when");
+		LOGICAL.add("else");
+		LOGICAL.add("end");
+
+		QUANTIFIERS.add("in");
+		QUANTIFIERS.add("all");
+		QUANTIFIERS.add("exists");
+		QUANTIFIERS.add("some");
+		QUANTIFIERS.add("any");
+
+		DML.add("insert");
+		DML.add("update");
+		DML.add("delete");
+
+		MISC.add("select");
+		MISC.add("on");
+	}
+
+	private static final String INDENT_STRING = "    ";
+	private static final String INITIAL = "\n    ";
+
+	public String format(String source) {
+		return new FormatProcess(source).perform();
+	}
+
+	private static class FormatProcess {
+		boolean beginLine = true;
+		boolean afterBeginBeforeEnd;
+		boolean afterByOrSetOrFromOrSelect;
+		boolean afterValues;
+		boolean afterOn;
+		boolean afterBetween;
+		boolean afterInsert;
+		int inFunction;
+		int parensSinceSelect;
+		private LinkedList<Integer> parenCounts = new LinkedList<Integer>();
+		private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<Boolean>();
+
+		int indent = 1;
+
+		StringBuilder result = new StringBuilder();
+		StringTokenizer tokens;
+		String lastToken;
+		String token;
+		String lcToken;
+
+		public FormatProcess(String sql) {
+			tokens = new StringTokenizer(sql, "()+*/-=<>'`\"[]," + WHITESPACE, true);
+		}
+
+		public String perform() {
+
+			result.append(INITIAL);
+
+			while (tokens.hasMoreTokens()) {
+				token = tokens.nextToken();
+				lcToken = token.toLowerCase(Locale.ROOT);
+
+				if ("'".equals(token)) {
+					String t;
+					do {
+						t = tokens.nextToken();
+						token += t;
+					}
+					// cannot handle single quotes
+					while (!"'".equals(t) && tokens.hasMoreTokens());
+				} else if ("\"".equals(token)) {
+					String t;
+					do {
+						t = tokens.nextToken();
+						token += t;
+					} while (!"\"".equals(t));
+				}
+
+				if (afterByOrSetOrFromOrSelect && ",".equals(token)) {
+					commaAfterByOrFromOrSelect();
+				} else if (afterOn && ",".equals(token)) {
+					commaAfterOn();
+				}
+
+				else if ("(".equals(token)) {
+					openParen();
+				} else if (")".equals(token)) {
+					closeParen();
+				}
+
+				else if (BEGIN_CLAUSES.contains(lcToken)) {
+					beginNewClause();
+				}
+
+				else if (END_CLAUSES.contains(lcToken)) {
+					endNewClause();
+				}
+
+				else if ("select".equals(lcToken)) {
+					select();
+				}
+
+				else if (DML.contains(lcToken)) {
+					updateOrInsertOrDelete();
+				}
+
+				else if ("values".equals(lcToken)) {
+					values();
+				}
+
+				else if ("on".equals(lcToken)) {
+					on();
+				}
+
+				else if (afterBetween && lcToken.equals("and")) {
+					misc();
+					afterBetween = false;
+				}
+
+				else if (LOGICAL.contains(lcToken)) {
+					logical();
+				}
+
+				else if (isWhitespace(token)) {
+					white();
+				}
+
+				else {
+					misc();
+				}
+
+				if (!isWhitespace(token)) {
+					lastToken = lcToken;
+				}
+
+			}
+			return result.toString();
+		}
+
+		private void commaAfterOn() {
+			out();
+			indent--;
+			newline();
+			afterOn = false;
+			afterByOrSetOrFromOrSelect = true;
+		}
+
+		private void commaAfterByOrFromOrSelect() {
+			out();
+			newline();
+		}
+
+		private void logical() {
+			if ("end".equals(lcToken)) {
+				indent--;
+			}
+			newline();
+			out();
+			beginLine = false;
+		}
+
+		private void on() {
+			indent++;
+			afterOn = true;
+			newline();
+			out();
+			beginLine = false;
+		}
+
+		private void misc() {
+			out();
+			if ("between".equals(lcToken)) {
+				afterBetween = true;
+			}
+			if (afterInsert) {
+				newline();
+				afterInsert = false;
+			} else {
+				beginLine = false;
+				if ("case".equals(lcToken)) {
+					indent++;
+				}
+			}
+		}
+
+		private void white() {
+			if (!beginLine) {
+				result.append(" ");
+			}
+		}
+
+		private void updateOrInsertOrDelete() {
+			out();
+			indent++;
+			beginLine = false;
+			if ("update".equals(lcToken)) {
+				newline();
+			}
+			if ("insert".equals(lcToken)) {
+				afterInsert = true;
+			}
+		}
+
+		private void select() {
+			out();
+			indent++;
+			newline();
+			parenCounts.addLast(parensSinceSelect);
+			afterByOrFromOrSelects.addLast(afterByOrSetOrFromOrSelect);
+			parensSinceSelect = 0;
+			afterByOrSetOrFromOrSelect = true;
+		}
+
+		private void out() {
+			result.append(token);
+		}
+
+		private void endNewClause() {
+			if (!afterBeginBeforeEnd) {
+				indent--;
+				if (afterOn) {
+					indent--;
+					afterOn = false;
+				}
+				newline();
+			}
+			out();
+			if (!"union".equals(lcToken)) {
+				indent++;
+			}
+			newline();
+			afterBeginBeforeEnd = false;
+			afterByOrSetOrFromOrSelect = "by".equals(lcToken) || "set".equals(lcToken) || "from".equals(lcToken);
+		}
+
+		private void beginNewClause() {
+			if (!afterBeginBeforeEnd) {
+				if (afterOn) {
+					indent--;
+					afterOn = false;
+				}
+				indent--;
+				newline();
+			}
+			out();
+			beginLine = false;
+			afterBeginBeforeEnd = true;
+		}
+
+		private void values() {
+			indent--;
+			newline();
+			out();
+			indent++;
+			newline();
+			afterValues = true;
+		}
+
+		private void closeParen() {
+			parensSinceSelect--;
+			if (parensSinceSelect < 0) {
+				indent--;
+				parensSinceSelect = parenCounts.removeLast();
+				afterByOrSetOrFromOrSelect = afterByOrFromOrSelects.removeLast();
+			}
+			if (inFunction > 0) {
+				inFunction--;
+				out();
+			} else {
+				if (!afterByOrSetOrFromOrSelect) {
+					indent--;
+					newline();
+				}
+				out();
+			}
+			beginLine = false;
+		}
+
+		private void openParen() {
+			if (isFunctionName(lastToken) || inFunction > 0) {
+				inFunction++;
+			}
+			beginLine = false;
+			if (inFunction > 0) {
+				out();
+			} else {
+				out();
+				if (!afterByOrSetOrFromOrSelect) {
+					indent++;
+					newline();
+					beginLine = true;
+				}
+			}
+			parensSinceSelect++;
+		}
+
+		private static boolean isFunctionName(String tok) {
+			final char begin = tok.charAt(0);
+			final boolean isIdentifier = Character.isJavaIdentifierStart(begin) || '"' == begin;
+			return isIdentifier && !LOGICAL.contains(tok) && !END_CLAUSES.contains(tok) && !QUANTIFIERS.contains(tok)
+					&& !DML.contains(tok) && !MISC.contains(tok);
+		}
+
+		private static boolean isWhitespace(String token) {
+			return WHITESPACE.contains(token);
+		}
+
+		private void newline() {
+			result.append("\n");
+			for (int i = 0; i < indent; i++) {
+				result.append(INDENT_STRING);
+			}
+			beginLine = true;
+		}
+	}
+
+	public static void main(String[] args) {
+		String sql = "select     *          from suber where id = '11  122'";
+        String format = new SQLFormatter().format(sql);
+        System.out.println(format);
+        System.out.println(format.replaceAll("([\\s]+(\"|'')?)", ""));
+	}
+}

+ 16 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlUtils.java

@@ -15,6 +15,7 @@
  */
 package com.baomidou.mybatisplus.toolkit;
 
+import com.baomidou.mybatisplus.plugins.SQLFormatter;
 import com.baomidou.mybatisplus.plugins.entity.CountOptimize;
 import com.baomidou.mybatisplus.plugins.pagination.Pagination;
 
@@ -27,6 +28,7 @@ import com.baomidou.mybatisplus.plugins.pagination.Pagination;
  * @Date 2016-11-13
  */
 public class SqlUtils {
+	private final static SQLFormatter sqlFormatter = new SQLFormatter();
 
 	/**
 	 * 获取CountOptimize
@@ -91,4 +93,18 @@ public class SqlUtils {
 		return originalSql;
 	}
 
+	/**
+	 * 格式sql
+	 * 
+	 * @param boundSql
+	 * @param format
+	 * @return
+	 */
+	public static String sqlFormat(String boundSql, boolean format) {
+		if (format) {
+			return sqlFormatter.format(boundSql);
+		} else {
+			return boundSql.replaceAll("[\\s]+", " ");
+		}
+	}
 }

+ 236 - 211
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/StringUtils.java

@@ -15,7 +15,6 @@
  */
 package com.baomidou.mybatisplus.toolkit;
 
-import java.text.MessageFormat;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.regex.Matcher;
@@ -31,229 +30,255 @@ import java.util.regex.Pattern;
  */
 public class StringUtils {
 
-    /**
-     * 下划线字符
-     */
-    public static final char UNDERLINE = '_';
+	/**
+	 * 下划线字符
+	 */
+	public static final char UNDERLINE = '_';
 
-    /**
-     * 空字符串
-     */
-    public static final String EMPTY_STRING = "";
+	/**
+	 * 空字符串
+	 */
+	public static final String EMPTY_STRING = "";
+	/**
+	 * 占位符
+	 */
+	public static final String PLACE_HOLDER = "{%s}";
 
-    /**
-     * <p>
-     * 判断字符串是否为空
-     * </p>
-     *
-     * @param str 需要判断字符串
-     * @return 判断结果
-     */
-    public static boolean isEmpty(String str) {
-        return str == null || EMPTY_STRING.equals(str.trim());
-    }
+	/**
+	 * <p>
+	 * 判断字符串是否为空
+	 * </p>
+	 *
+	 * @param str
+	 *            需要判断字符串
+	 * @return 判断结果
+	 */
+	public static boolean isEmpty(String str) {
+		return str == null || EMPTY_STRING.equals(str.trim());
+	}
 
-    /**
-     * <p>
-     * 判断字符串是否不为空
-     * </p>
-     *
-     * @param str 需要判断字符串
-     * @return 判断结果
-     */
-    public static boolean isNotEmpty(String str) {
-        return !isEmpty(str);
-    }
+	/**
+	 * <p>
+	 * 判断字符串是否不为空
+	 * </p>
+	 *
+	 * @param str
+	 *            需要判断字符串
+	 * @return 判断结果
+	 */
+	public static boolean isNotEmpty(String str) {
+		return !isEmpty(str);
+	}
 
-    /**
-     * <p>
-     * 字符串驼峰转下划线格式
-     * </p>
-     *
-     * @param param 需要转换的字符串
-     * @return 转换好的字符串
-     */
-    public static String camelToUnderline(String param) {
-        if (isEmpty(param)) {
-            return EMPTY_STRING;
-        }
-        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 (isEmpty(param)) {
+			return EMPTY_STRING;
+		}
+		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 EMPTY_STRING;
-        }
-        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 EMPTY_STRING;
+		}
+		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>
-     * SQL 参数填充
-     * </p>
-     *
-     * @param content 填充内容
-     * @param args    填充参数
-     * @return
-     */
-    public static String sqlArgsFill(String content, Object... args) {
-        if (null == content) {
-            return null;
-        }
-        if (args != null) {
-            int length = args.length;
-            if (length >= 1) {
-                for (int i = 0; i < length; i++) {
-                    if (args[i] instanceof Collection) {
-                        args[i] = StringUtils.quotaMarkList((Collection<?>) args[i]);
-                    } else {
-                        args[i] = StringUtils.quotaMark(args[i]);
-                    }
-                }
-                content = MessageFormat.format(content, args);
-            }
-        }
-        return content;
-    }
+	/**
+	 * <p>
+	 * SQL 参数填充
+	 * </p>
+	 *
+	 * @param content
+	 *            填充内容
+	 * @param args
+	 *            填充参数
+	 * @return
+	 */
+	public static String sqlArgsFill(String content, Object... args) {
+		if (null == content) {
+			return null;
+		}
+		if (args != null) {
+			int length = args.length;
+			if (length >= 1) {
+				for (int i = 0; i < length; i++) {
+					content = content.replace(String.format(PLACE_HOLDER, i), sqlParam(args[i]));
+				}
+			}
+		}
+		return content;
+	}
 
-    /**
-     * <p>
-     * 使用单引号包含字符串
-     * </p>
-     *
-     * @param obj 原字符串
-     * @return 单引号包含的原字符串
-     */
-    public static String quotaMark(Object obj) {
-        String srcStr = String.valueOf(obj);
-        if (obj instanceof String) {
-            // fix #79
-            return StringEscape.escapeString(srcStr);
-        }
-        return srcStr;
-    }
+	/**
+	 * 获取SQL PARAMS字符串
+	 * 
+	 * @param obj
+	 * @return
+	 */
+	public static String sqlParam(Object obj) {
+		String repStr;
+		if (obj instanceof Collection) {
+			repStr = StringUtils.quotaMarkList((Collection<?>) obj);
+		} else {
+			repStr = StringUtils.quotaMark(obj);
+		}
+		return repStr;
+	}
 
-    /**
-     * <p>
-     * 使用单引号包含字符串
-     * </p>
-     *
-     * @param coll 集合
-     * @return 单引号包含的原字符串的集合形式
-     */
-    public static String quotaMarkList(Collection<?> coll) {
-        StringBuilder sqlBuild = new StringBuilder();
-        sqlBuild.append("(");
-        int _size = coll.size();
-        int i = 0;
-        Iterator<?> iterator = coll.iterator();
-        while (iterator.hasNext()) {
-            String tempVal = StringUtils.quotaMark(iterator.next());
-            if (i + 1 == _size) {
-                sqlBuild.append(tempVal);
-            } else {
-                sqlBuild.append(tempVal);
-                sqlBuild.append(",");
-            }
-            i++;
-        }
-        sqlBuild.append(")");
-        return sqlBuild.toString();
-    }
+	/**
+	 * <p>
+	 * 使用单引号包含字符串
+	 * </p>
+	 *
+	 * @param obj
+	 *            原字符串
+	 * @return 单引号包含的原字符串
+	 */
+	public static String quotaMark(Object obj) {
+		String srcStr = String.valueOf(obj);
+		if (obj instanceof String) {
+			// fix #79
+			return StringEscape.escapeString(srcStr);
+		}
+		return srcStr;
+	}
 
-    /**
-     * <p>
-     * 拼接字符串第二个字符串第一个字母大写
-     *
-     * @param concatStr
-     * @param str
-     * @return
-     */
-    public static String concatCapitalize(String concatStr, final String str) {
-        if (isEmpty(concatStr)) {
-            concatStr = EMPTY_STRING;
-        }
-        int strLen;
-        if (str == null || (strLen = str.length()) == 0) {
-            return str;
-        }
+	/**
+	 * <p>
+	 * 使用单引号包含字符串
+	 * </p>
+	 *
+	 * @param coll
+	 *            集合
+	 * @return 单引号包含的原字符串的集合形式
+	 */
+	public static String quotaMarkList(Collection<?> coll) {
+		StringBuilder sqlBuild = new StringBuilder();
+		sqlBuild.append("(");
+		int _size = coll.size();
+		int i = 0;
+		Iterator<?> iterator = coll.iterator();
+		while (iterator.hasNext()) {
+			String tempVal = StringUtils.quotaMark(iterator.next());
+			if (i + 1 == _size) {
+				sqlBuild.append(tempVal);
+			} else {
+				sqlBuild.append(tempVal);
+				sqlBuild.append(",");
+			}
+			i++;
+		}
+		sqlBuild.append(")");
+		return sqlBuild.toString();
+	}
 
-        final char firstChar = str.charAt(0);
-        if (Character.isTitleCase(firstChar)) {
-            // already capitalized
-            return str;
-        }
+	/**
+	 * <p>
+	 * 拼接字符串第二个字符串第一个字母大写
+	 *
+	 * @param concatStr
+	 * @param str
+	 * @return
+	 */
+	public static String concatCapitalize(String concatStr, final String str) {
+		if (isEmpty(concatStr)) {
+			concatStr = EMPTY_STRING;
+		}
+		int strLen;
+		if (str == null || (strLen = str.length()) == 0) {
+			return str;
+		}
 
-        return new StringBuilder(strLen).append(concatStr).append(Character.toTitleCase(firstChar)).append(str.substring(1))
-                .toString();
-    }
+		final char firstChar = str.charAt(0);
+		if (Character.isTitleCase(firstChar)) {
+			// already capitalized
+			return str;
+		}
 
-    /**
-     * <p>
-     * 字符串第一个字母大写
-     * </p>
-     *
-     * @param str
-     * @return
-     */
-    public static String capitalize(final String str) {
-        return concatCapitalize(null, str);
-    }
+		return new StringBuilder(strLen).append(concatStr).append(Character.toTitleCase(firstChar)).append(str.substring(1))
+				.toString();
+	}
+
+	/**
+	 * <p>
+	 * 字符串第一个字母大写
+	 * </p>
+	 *
+	 * @param str
+	 * @return
+	 */
+	public static String capitalize(final String str) {
+		return concatCapitalize(null, str);
+	}
 
 }

+ 2 - 0
mybatis-plus/src/test/resources/wiki/plugin.md

@@ -28,6 +28,8 @@
     <!-- SQL 执行性能分析,开发环境使用,线上不推荐。 maxTime 指的是 sql 最大执行时长 -->
     <plugin interceptor="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
         <property name="maxTime" value="100" />
+        <!--添加打印SQL格式化-->
+        <property name="format" value="true"/>
     </plugin>
     <!-- SQL 执行分析拦截器 stopProceed 发现全表执行 delete update 是否停止运行 -->
     <plugin interceptor="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">