Kaynağa Gözat

全局优化

Caratacus 8 yıl önce
ebeveyn
işleme
e13ea795b5
100 değiştirilmiş dosya ile 12318 ekleme ve 12448 silme
  1. 5 4
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisAbstractSQL.java
  2. 69 69
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisConfiguration.java
  3. 179 179
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisDefaultParameterHandler.java
  4. 575 574
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisMapperAnnotationBuilder.java
  5. 74 73
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisMapperRegistry.java
  6. 33 33
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisSessionFactoryBuilder.java
  7. 383 382
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisSqlSessionTemplate.java
  8. 12 13
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisXMLConfigBuilder.java
  9. 10 10
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisXMLLanguageDriver.java
  10. 383 383
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisXMLMapperBuilder.java
  11. 337 336
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/activerecord/Model.java
  12. 38 38
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/annotations/TableField.java
  13. 16 16
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/annotations/TableName.java
  14. 2 2
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/annotations/Version.java
  15. 29 28
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/CountOptimize.java
  16. 344 343
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/GlobalConfiguration.java
  17. 124 124
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/TableFieldInfo.java
  18. 146 145
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/TableInfo.java
  19. 78 78
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/DBType.java
  20. 35 35
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/FieldStrategy.java
  21. 40 40
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/IdType.java
  22. 45 45
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/Optimize.java
  23. 34 34
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/SqlLike.java
  24. 51 51
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/SqlMethod.java
  25. 14 14
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/exceptions/MybatisPlusException.java
  26. 90 96
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/AbstractGenerator.java
  27. 253 250
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/AutoGenerator.java
  28. 34 34
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/InjectionConfig.java
  29. 34 34
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/ConstVal.java
  30. 121 123
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/DataSourceConfig.java
  31. 20 19
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/FileOutConfig.java
  32. 151 150
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/GlobalConfig.java
  33. 13 13
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/ITypeConvert.java
  34. 108 108
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/PackageConfig.java
  35. 225 227
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/StrategyConfig.java
  36. 44 44
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateConfig.java
  37. 532 549
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/builder/ConfigBuilder.java
  38. 30 30
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/MySqlTypeConvert.java
  39. 25 25
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OracleTypeConvert.java
  40. 30 30
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/PostgreSqlTypeConvert.java
  41. 28 28
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqlServerTypeConvert.java
  42. 104 101
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableField.java
  43. 194 194
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java
  44. 35 31
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbColumnType.java
  45. 8 8
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbType.java
  46. 99 100
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/NamingStrategy.java
  47. 106 106
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/QuerySQL.java
  48. 894 897
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/AutoSqlInjector.java
  49. 217 215
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/BaseMapper.java
  50. 28 28
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/Condition.java
  51. 36 36
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/EntityWrapper.java
  52. 14 14
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/IMetaObjectHandler.java
  53. 25 25
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/ISqlInjector.java
  54. 138 137
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/SqlHelper.java
  55. 78 83
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/SqlPlus.java
  56. 119 121
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/SqlRunner.java
  57. 746 811
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/Wrapper.java
  58. 103 102
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/CachePaginationInterceptor.java
  59. 231 233
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/OptimisticLockerInterceptor.java
  60. 44 44
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/Page.java
  61. 141 140
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/PaginationInterceptor.java
  62. 74 74
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/PerformanceInterceptor.java
  63. 117 117
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/SqlExplainInterceptor.java
  64. 4 4
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/VersionHandler.java
  65. 124 123
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/DialectFactory.java
  66. 16 16
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/IDialect.java
  67. 187 186
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/Pagination.java
  68. 48 34
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/DB2Dialect.java
  69. 14 14
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/H2Dialect.java
  70. 10 10
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/HSQLDialect.java
  71. 10 10
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/MySqlDialect.java
  72. 12 12
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/OracleDialect.java
  73. 10 10
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/PostgreDialect.java
  74. 40 40
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/SQLServer2005Dialect.java
  75. 11 11
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/SQLServerDialect.java
  76. 10 10
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/SQLiteDialect.java
  77. 334 334
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/service/IService.java
  78. 18 27
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/service/impl/ServiceImpl.java
  79. 233 236
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/spring/MybatisMapperRefresh.java
  80. 554 552
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/spring/MybatisSqlSessionFactoryBean.java
  81. 6 6
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/ArrayUtils.java
  82. 25 25
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/CollectionUtils.java
  83. 13 13
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/DruidUtils.java
  84. 458 458
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/IOUtils.java
  85. 18 18
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/IdWorker.java
  86. 40 40
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/JdbcUtils.java
  87. 65 64
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/JsqlParserUtils.java
  88. 18 18
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/MapUtils.java
  89. 47 46
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/PackageHelper.java
  90. 13 13
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/PluginUtils.java
  91. 182 191
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/ReflectionKit.java
  92. 125 124
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/Sequence.java
  93. 315 339
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlFormatter.java
  94. 150 150
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlReservedWords.java
  95. 136 135
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlUtils.java
  96. 98 98
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/StringEscape.java
  97. 576 603
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/StringUtils.java
  98. 14 13
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SystemClock.java
  99. 1 1
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/TableInfoHelper.java
  100. 38 38
      mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/VersionUtils.java

+ 5 - 4
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisAbstractSQL.java

@@ -15,13 +15,13 @@
  */
 package com.baomidou.mybatisplus;
 
-import com.baomidou.mybatisplus.toolkit.StringUtils;
-
 import java.io.IOException;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+
 /**
  * <p>
  * 重定义 AbstractSQL ,实现标准TSQL的 查询条件自定义
@@ -106,7 +106,8 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
     /**
      * SQL连接器
      */
-	private static class SafeAppendable implements Serializable {
+    private static class SafeAppendable implements Serializable {
+
         private final Appendable appendable;
         private boolean empty = true;
 
@@ -136,7 +137,7 @@ public abstract class MybatisAbstractSQL<T> implements Serializable {
     /**
      * SQL条件类
      */
-	private static class SQLCondition implements Serializable {
+    private static class SQLCondition implements Serializable {
 
         List<String> where = new ArrayList<String>();
         List<String> having = new ArrayList<String>();

+ 69 - 69
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisConfiguration.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -37,87 +37,87 @@ import com.baomidou.mybatisplus.entity.GlobalConfiguration;
  */
 public class MybatisConfiguration extends Configuration {
 
-	private static final Log logger = LogFactory.getLog(MybatisConfiguration.class);
+    private static final Log logger = LogFactory.getLog(MybatisConfiguration.class);
 
-	/*
-	 * Mapper 注册
-	 */
-	public final MybatisMapperRegistry mybatisMapperRegistry = new MybatisMapperRegistry(this);
+    /*
+     * Mapper 注册
+     */
+    public final MybatisMapperRegistry mybatisMapperRegistry = new MybatisMapperRegistry(this);
 
-	/**
-	 * 初始化调用
-	 */
-	public MybatisConfiguration() {
-		System.err.println("mybatis-plus init success.");
-	}
+    /**
+     * 初始化调用
+     */
+    public MybatisConfiguration() {
+        System.err.println("mybatis-plus init success.");
+    }
 
-	/**
-	 * <p>
-	 * MybatisPlus 加载 SQL 顺序:
-	 * </p>
-	 * 1、加载XML中的SQL<br>
-	 * 2、加载sqlProvider中的SQL<br>
-	 * 3、xmlSql 与 sqlProvider不能包含相同的SQL<br>
-	 * <br>
-	 * 调整后的SQL优先级:xmlSql > sqlProvider > curdSql <br>
-	 */
-	@Override
-	public void addMappedStatement(MappedStatement ms) {
-		logger.debug("addMappedStatement: " + ms.getId());
-		if (GlobalConfiguration.getGlobalConfig(ms.getConfiguration()).isRefresh()) {
-			/*
+    /**
+     * <p>
+     * MybatisPlus 加载 SQL 顺序:
+     * </p>
+     * 1、加载XML中的SQL<br>
+     * 2、加载sqlProvider中的SQL<br>
+     * 3、xmlSql 与 sqlProvider不能包含相同的SQL<br>
+     * <br>
+     * 调整后的SQL优先级:xmlSql > sqlProvider > curdSql <br>
+     */
+    @Override
+    public void addMappedStatement(MappedStatement ms) {
+        logger.debug("addMappedStatement: " + ms.getId());
+        if (GlobalConfiguration.getGlobalConfig(ms.getConfiguration()).isRefresh()) {
+            /*
 			 * 支持是否自动刷新 XML 变更内容,开发环境使用【 注:生产环境勿用!】
 			 */
-			this.mappedStatements.remove(ms.getId());
-		} else {
-			if (this.mappedStatements.containsKey(ms.getId())) {
+            this.mappedStatements.remove(ms.getId());
+        } else {
+            if (this.mappedStatements.containsKey(ms.getId())) {
 				/*
 				 * 说明已加载了xml中的节点; 忽略mapper中的SqlProvider数据
 				 */
-				logger.error("mapper[" + ms.getId() + "] is ignored, because it's exists, maybe from xml file");
-				return;
-			}
-		}
-		super.addMappedStatement(ms);
-	}
+                logger.error("mapper[" + ms.getId() + "] is ignored, because it's exists, maybe from xml file");
+                return;
+            }
+        }
+        super.addMappedStatement(ms);
+    }
 
-	@Override
-	public void setDefaultScriptingLanguage(Class<?> driver) {
-		if (driver == null) {
+    @Override
+    public void setDefaultScriptingLanguage(Class<?> driver) {
+        if (driver == null) {
 			/* 设置自定义 driver */
-			driver = MybatisXMLLanguageDriver.class;
-		}
-		super.setDefaultScriptingLanguage(driver);
-	}
+            driver = MybatisXMLLanguageDriver.class;
+        }
+        super.setDefaultScriptingLanguage(driver);
+    }
 
-	@Override
-	public MapperRegistry getMapperRegistry() {
-		return mybatisMapperRegistry;
-	}
+    @Override
+    public MapperRegistry getMapperRegistry() {
+        return mybatisMapperRegistry;
+    }
 
-	@Override
-	public <T> void addMapper(Class<T> type) {
-		mybatisMapperRegistry.addMapper(type);
-	}
+    @Override
+    public <T> void addMapper(Class<T> type) {
+        mybatisMapperRegistry.addMapper(type);
+    }
 
-	@Override
-	public void addMappers(String packageName, Class<?> superType) {
-		mybatisMapperRegistry.addMappers(packageName, superType);
-	}
+    @Override
+    public void addMappers(String packageName, Class<?> superType) {
+        mybatisMapperRegistry.addMappers(packageName, superType);
+    }
 
-	@Override
-	public void addMappers(String packageName) {
-		mybatisMapperRegistry.addMappers(packageName);
-	}
+    @Override
+    public void addMappers(String packageName) {
+        mybatisMapperRegistry.addMappers(packageName);
+    }
 
-	@Override
-	public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
-		return mybatisMapperRegistry.getMapper(type, sqlSession);
-	}
+    @Override
+    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
+        return mybatisMapperRegistry.getMapper(type, sqlSession);
+    }
 
-	@Override
-	public boolean hasMapper(Class<?> type) {
-		return mybatisMapperRegistry.hasMapper(type);
-	}
+    @Override
+    public boolean hasMapper(Class<?> type) {
+        return mybatisMapperRegistry.hasMapper(type);
+    }
 
 }

+ 179 - 179
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisDefaultParameterHandler.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
@@ -51,197 +51,197 @@ import com.baomidou.mybatisplus.toolkit.TableInfoHelper;
  * <p>
  * 自定义 ParameterHandler 重装构造函数,填充插入方法主键 ID
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-03-11
  */
 public class MybatisDefaultParameterHandler extends DefaultParameterHandler {
 
-	/**
-	 * @see org.apache.ibatis.mapping.BoundSql
-	 */
-	private static Field additionalParametersField;
-	private final TypeHandlerRegistry typeHandlerRegistry;
-	private final MappedStatement mappedStatement;
-	private final Object parameterObject;
-	private BoundSql boundSql;
-	private Configuration configuration;
-	static {
-		try {
-			additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
-			additionalParametersField.setAccessible(true);
-		} catch (NoSuchFieldException e) {
-			// ignored, Because it will never happen.
-		}
-	}
+    /**
+     * @see org.apache.ibatis.mapping.BoundSql
+     */
+    private static Field additionalParametersField;
+
+    static {
+        try {
+            additionalParametersField = BoundSql.class.getDeclaredField("additionalParameters");
+            additionalParametersField.setAccessible(true);
+        } catch (NoSuchFieldException e) {
+            // ignored, Because it will never happen.
+        }
+    }
 
-	public MybatisDefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
-		super(mappedStatement, processBatch(mappedStatement, parameterObject), boundSql);
-		this.mappedStatement = mappedStatement;
-		this.configuration = mappedStatement.getConfiguration();
-		this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
-		this.parameterObject = parameterObject;
-		this.boundSql = boundSql;
-	}
+    private final TypeHandlerRegistry typeHandlerRegistry;
+    private final MappedStatement mappedStatement;
+    private final Object parameterObject;
+    private BoundSql boundSql;
+    private Configuration configuration;
 
-	/**
-	 * <p>
-	 * 批量(填充主键 ID)
-	 * </p>
-	 * 
-	 * @param ms
-	 * @param parameterObject
-	 *            插入数据库对象
-	 * @return
-	 */
-	protected static Object processBatch(MappedStatement ms, Object parameterObject) {
-		if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
-			/**
-			 * 只处理插入操作
-			 */
-			Collection<Object> parameters = getParameters(parameterObject);
-			if (null != parameters) {
-				List<Object> objList = new ArrayList<Object>();
-				for (Object parameter : parameters) {
-					TableInfo tableInfo = TableInfoHelper.getTableInfo(parameter.getClass());
-					if (null != tableInfo) {
-						objList.add(populateKeys(tableInfo, ms, parameter));
-					} else {
-						/*
+    public MybatisDefaultParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
+        super(mappedStatement, processBatch(mappedStatement, parameterObject), boundSql);
+        this.mappedStatement = mappedStatement;
+        this.configuration = mappedStatement.getConfiguration();
+        this.typeHandlerRegistry = mappedStatement.getConfiguration().getTypeHandlerRegistry();
+        this.parameterObject = parameterObject;
+        this.boundSql = boundSql;
+    }
+
+    /**
+     * <p>
+     * 批量(填充主键 ID)
+     * </p>
+     *
+     * @param ms
+     * @param parameterObject
+     *            插入数据库对象
+     * @return
+     */
+    protected static Object processBatch(MappedStatement ms, Object parameterObject) {
+        if (ms.getSqlCommandType() == SqlCommandType.INSERT) {
+            /**
+             * 只处理插入操作
+             */
+            Collection<Object> parameters = getParameters(parameterObject);
+            if (null != parameters) {
+                List<Object> objList = new ArrayList<Object>();
+                for (Object parameter : parameters) {
+                    TableInfo tableInfo = TableInfoHelper.getTableInfo(parameter.getClass());
+                    if (null != tableInfo) {
+                        objList.add(populateKeys(tableInfo, ms, parameter));
+                    } else {
+                        /*
 						 * 非表映射类不处理
 						 */
-						objList.add(parameter);
-					}
-				}
-				return objList;
-			} else {
-				TableInfo tableInfo = TableInfoHelper.getTableInfo(parameterObject.getClass());
-				return populateKeys(tableInfo, ms, parameterObject);
-			}
-		}
-		return parameterObject;
-	}
+                        objList.add(parameter);
+                    }
+                }
+                return objList;
+            } else {
+                TableInfo tableInfo = TableInfoHelper.getTableInfo(parameterObject.getClass());
+                return populateKeys(tableInfo, ms, parameterObject);
+            }
+        }
+        return parameterObject;
+    }
 
-	/**
-	 * <p>
-	 * 处理正常批量插入逻辑
-	 * </p>
-	 * <p>
-	 * org.apache.ibatis.session.defaults.DefaultSqlSession$StrictMap 该类方法
-	 * wrapCollection 实现 StrictMap 封装逻辑
-	 * </p>
-	 * 
-	 * @param parameter
-	 *            插入数据库对象
-	 * @return
-	 */
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	protected static Collection<Object> getParameters(Object parameter) {
-		Collection<Object> parameters = null;
-		if (parameter instanceof Collection) {
-			parameters = (Collection) parameter;
-		} else if (parameter instanceof Map) {
-			Map parameterMap = (Map) parameter;
-			if (parameterMap.containsKey("collection")) {
-				parameters = (Collection) parameterMap.get("collection");
-			} else if (parameterMap.containsKey("list")) {
-				parameters = (List) parameterMap.get("list");
-			} else if (parameterMap.containsKey("array")) {
-				parameters = Arrays.asList((Object[]) parameterMap.get("array"));
-			}
-		}
-		return parameters;
-	}
+    /**
+     * <p>
+     * 处理正常批量插入逻辑
+     * </p>
+     * <p>
+     * org.apache.ibatis.session.defaults.DefaultSqlSession$StrictMap 该类方法
+     * wrapCollection 实现 StrictMap 封装逻辑
+     * </p>
+     *
+     * @param parameter
+     *            插入数据库对象
+     * @return
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected static Collection<Object> getParameters(Object parameter) {
+        Collection<Object> parameters = null;
+        if (parameter instanceof Collection) {
+            parameters = (Collection) parameter;
+        } else if (parameter instanceof Map) {
+            Map parameterMap = (Map) parameter;
+            if (parameterMap.containsKey("collection")) {
+                parameters = (Collection) parameterMap.get("collection");
+            } else if (parameterMap.containsKey("list")) {
+                parameters = (List) parameterMap.get("list");
+            } else if (parameterMap.containsKey("array")) {
+                parameters = Arrays.asList((Object[]) parameterMap.get("array"));
+            }
+        }
+        return parameters;
+    }
 
-	/**
-	 * <p>
-	 * 自定义元对象填充控制器
-	 * </p>
-	 *
-	 * @param tableInfo
-	 * @param ms
-	 * @param parameterObject 插入数据库对象
-	 * @return
-	 */
-	protected static Object populateKeys(TableInfo tableInfo, MappedStatement ms, Object parameterObject) {
-		if (null == tableInfo || StringUtils.isEmpty(tableInfo.getKeyProperty()) || null == tableInfo.getIdType()) {
+    /**
+     * <p>
+     * 自定义元对象填充控制器
+     * </p>
+     *
+     * @param tableInfo
+     * @param ms
+     * @param parameterObject 插入数据库对象
+     * @return
+     */
+    protected static Object populateKeys(TableInfo tableInfo, MappedStatement ms, Object parameterObject) {
+        if (null == tableInfo || StringUtils.isEmpty(tableInfo.getKeyProperty()) || null == tableInfo.getIdType()) {
             /*
              * 不处理
              */
-			return parameterObject;
-		}
-		MetaObject metaObject = ms.getConfiguration().newMetaObject(parameterObject);
-		if (tableInfo.getIdType().getKey() >= 2) {
-			Object idValue = metaObject.getValue(tableInfo.getKeyProperty());
+            return parameterObject;
+        }
+        MetaObject metaObject = ms.getConfiguration().newMetaObject(parameterObject);
+        if (tableInfo.getIdType().getKey() >= 2) {
+            Object idValue = metaObject.getValue(tableInfo.getKeyProperty());
             /* 自定义 ID */
-			if (StringUtils.checkValNull(idValue)) {
-				if (tableInfo.getIdType() == IdType.ID_WORKER) {
-					metaObject.setValue(tableInfo.getKeyProperty(), IdWorker.getId());
-				} else if (tableInfo.getIdType() == IdType.UUID) {
-					metaObject.setValue(tableInfo.getKeyProperty(), IdWorker.get32UUID());
-				}
-			}
-		}
+            if (StringUtils.checkValNull(idValue)) {
+                if (tableInfo.getIdType() == IdType.ID_WORKER) {
+                    metaObject.setValue(tableInfo.getKeyProperty(), IdWorker.getId());
+                } else if (tableInfo.getIdType() == IdType.UUID) {
+                    metaObject.setValue(tableInfo.getKeyProperty(), IdWorker.get32UUID());
+                }
+            }
+        }
         /* 自定义元对象填充控制器 */
-		IMetaObjectHandler metaObjectHandler = GlobalConfiguration.getMetaObjectHandler(ms.getConfiguration());
-		if (null != metaObjectHandler) {
-			metaObjectHandler.insertFill(metaObject);
-		}
-		return metaObject.getOriginalObject();
-	}
+        IMetaObjectHandler metaObjectHandler = GlobalConfiguration.getMetaObjectHandler(ms.getConfiguration());
+        if (null != metaObjectHandler) {
+            metaObjectHandler.insertFill(metaObject);
+        }
+        return metaObject.getOriginalObject();
+    }
 
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	@Override
-	public void setParameters(PreparedStatement ps) {
-		// 反射获取动态参数
-		Map<String, Object> additionalParameters = null;
-		try {
-			additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
-		} catch (IllegalAccessException e) {
-			// ignored, Because it will never happen.
-		}
-		ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
-		List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
-		if (parameterMappings != null) {
-			for (int i = 0; i < parameterMappings.size(); i++) {
-				ParameterMapping parameterMapping = parameterMappings.get(i);
-				if (parameterMapping.getMode() != ParameterMode.OUT) {
-					Object value;
-					String propertyName = parameterMapping.getProperty();
-					if (boundSql.hasAdditionalParameter(propertyName)) { // issue
-																			// #448
-																			// ask
-																			// first
-																			// for
-																			// additional
-																			// params
-						value = boundSql.getAdditionalParameter(propertyName);
-					} else if (parameterObject == null) {
-						value = null;
-					} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
-						value = parameterObject;
-					} else {
-						MetaObject metaObject = configuration.newMetaObject(parameterObject);
-						value = metaObject.getValue(propertyName);
-						if (value == null && MapUtils.isNotEmpty(additionalParameters)) {
-							// issue #138
-							value = additionalParameters.get(propertyName);
-						}
-					}
-					TypeHandler typeHandler = parameterMapping.getTypeHandler();
-					JdbcType jdbcType = parameterMapping.getJdbcType();
-					if (value == null && jdbcType == null) {
-						jdbcType = configuration.getJdbcTypeForNull();
-					}
-					try {
-						typeHandler.setParameter(ps, i + 1, value, jdbcType);
-					} catch (TypeException e) {
-						throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
-					} catch (SQLException e) {
-						throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
-					}
-				}
-			}
-		}
-	}
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Override
+    public void setParameters(PreparedStatement ps) {
+        // 反射获取动态参数
+        Map<String, Object> additionalParameters = null;
+        try {
+            additionalParameters = (Map<String, Object>) additionalParametersField.get(boundSql);
+        } catch (IllegalAccessException e) {
+            // ignored, Because it will never happen.
+        }
+        ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
+        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
+        if (parameterMappings != null) {
+            for (int i = 0; i < parameterMappings.size(); i++) {
+                ParameterMapping parameterMapping = parameterMappings.get(i);
+                if (parameterMapping.getMode() != ParameterMode.OUT) {
+                    Object value;
+                    String propertyName = parameterMapping.getProperty();
+                    if (boundSql.hasAdditionalParameter(propertyName)) { // issue
+                        // #448
+                        // ask
+                        // first
+                        // for
+                        // additional
+                        // params
+                        value = boundSql.getAdditionalParameter(propertyName);
+                    } else if (parameterObject == null) {
+                        value = null;
+                    } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
+                        value = parameterObject;
+                    } else {
+                        MetaObject metaObject = configuration.newMetaObject(parameterObject);
+                        value = metaObject.getValue(propertyName);
+                        if (value == null && MapUtils.isNotEmpty(additionalParameters)) {
+                            // issue #138
+                            value = additionalParameters.get(propertyName);
+                        }
+                    }
+                    TypeHandler typeHandler = parameterMapping.getTypeHandler();
+                    JdbcType jdbcType = parameterMapping.getJdbcType();
+                    if (value == null && jdbcType == null) {
+                        jdbcType = configuration.getJdbcTypeForNull();
+                    }
+                    try {
+                        typeHandler.setParameter(ps, i + 1, value, jdbcType);
+                    } catch (TypeException | SQLException e) {
+                        throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
+                    }
+                }
+            }
+        }
+    }
 }

+ 575 - 574
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisMapperAnnotationBuilder.java

@@ -15,8 +15,25 @@
  */
 package com.baomidou.mybatisplus;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-import com.baomidou.mybatisplus.mapper.BaseMapper;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
 import org.apache.ibatis.annotations.Arg;
 import org.apache.ibatis.annotations.CacheNamespace;
 import org.apache.ibatis.annotations.CacheNamespaceRef;
@@ -74,587 +91,571 @@ import org.apache.ibatis.type.JdbcType;
 import org.apache.ibatis.type.TypeHandler;
 import org.apache.ibatis.type.UnknownTypeHandler;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Array;
-import java.lang.reflect.GenericArrayType;
-import java.lang.reflect.Method;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.mapper.BaseMapper;
 
 /**
  * <p>
  * 继承 MapperAnnotationBuilder 没有XML配置文件注入基础CRUD方法
  * </p>
- * 
+ *
  * @author Caratacus
  * @Date 2017-01-04
  */
 public class MybatisMapperAnnotationBuilder extends MapperAnnotationBuilder {
 
-	private final Set<Class<? extends Annotation>> sqlAnnotationTypes = new HashSet<Class<? extends Annotation>>();
-	private final Set<Class<? extends Annotation>> sqlProviderAnnotationTypes = new HashSet<Class<? extends Annotation>>();
-
-	private Configuration configuration;
-	private MapperBuilderAssistant assistant;
-	private Class<?> type;
-
-	public MybatisMapperAnnotationBuilder(Configuration configuration, Class<?> type) {
-		super(configuration, type);
-		String resource = type.getName().replace('.', '/') + ".java (best guess)";
-		this.assistant = new MapperBuilderAssistant(configuration, resource);
-		this.configuration = configuration;
-		this.type = type;
-		sqlAnnotationTypes.add(Select.class);
-		sqlAnnotationTypes.add(Insert.class);
-		sqlAnnotationTypes.add(Update.class);
-		sqlAnnotationTypes.add(Delete.class);
-		sqlProviderAnnotationTypes.add(SelectProvider.class);
-		sqlProviderAnnotationTypes.add(InsertProvider.class);
-		sqlProviderAnnotationTypes.add(UpdateProvider.class);
-		sqlProviderAnnotationTypes.add(DeleteProvider.class);
-	}
-
-	public void parse() {
-		String resource = type.toString();
-		if (!configuration.isResourceLoaded(resource)) {
-			boolean existXml = loadXmlResource();
-			configuration.addLoadedResource(resource);
-			assistant.setCurrentNamespace(type.getName());
-			parseCache();
-			parseCacheRef();
-			Method[] methods = type.getMethods();
-			// TODO 注入存在 xxMapper.xml CURD (应该在注解之前注入)
-			inspectInject(existXml);
-			for (Method method : methods) {
-				try {
-					// issue #237
-					if (!method.isBridge()) {
-						parseStatement(method);
-					}
-				} catch (IncompleteElementException e) {
-					configuration.addIncompleteMethod(new MethodResolver(this, method));
-				}
-			}
-
-		}
-		parsePendingMethods();
-	}
-
-	/*
-	 * 注入 CURD 动态 SQL(XML不存在时注入)
-	 */
-	private void inspectInject(boolean flag) {
-		if (!flag && BaseMapper.class.isAssignableFrom(type)) {
-			GlobalConfiguration.getSqlInjector(configuration).inspectInject(assistant, type);
-		}
-	}
-
-	private void parsePendingMethods() {
-		Collection<MethodResolver> incompleteMethods = configuration.getIncompleteMethods();
-		synchronized (incompleteMethods) {
-			Iterator<MethodResolver> iter = incompleteMethods.iterator();
-			while (iter.hasNext()) {
-				try {
-					iter.next().resolve();
-					iter.remove();
-				} catch (IncompleteElementException e) {
-					// This method is still missing a resource
-				}
-			}
-		}
-	}
-
-	/**
-	 * 是否存在XML(该方法并不能客观的判断resource的路径,只是Mybatis默认认为的xml路径)
-	 *
-	 * @return boolean ture存在,flase不存在
-	 */
-	// TODO 该方法改为返回 boolean 判断是否存在 xxxMapper.xml
-	private boolean loadXmlResource() {
-		boolean flag = true;
-		// Spring may not know the real resource name so we check a flag
-		// to prevent loading again a resource twice
-		// this flag is set at MybatisXMLMapperBuilder#bindMapperForNamespace
-		if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
-			String xmlResource = type.getName().replace('.', '/') + ".xml";
-			InputStream inputStream = null;
-			try {
-				inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
-			} catch (IOException e) {
-				// ignore, resource is not required
-				flag = false;
-			}
-			if (inputStream != null) {
-				MybatisXMLMapperBuilder xmlParser = new MybatisXMLMapperBuilder(inputStream, assistant.getConfiguration(),
-						xmlResource, configuration.getSqlFragments(), type.getName());
-				xmlParser.parse();
-			}
-		}
-		return flag;
-	}
-
-	private void parseCache() {
-		CacheNamespace cacheDomain = type.getAnnotation(CacheNamespace.class);
-		if (cacheDomain != null) {
-			Integer size = cacheDomain.size() == 0 ? null : cacheDomain.size();
-			Long flushInterval = cacheDomain.flushInterval() == 0 ? null : cacheDomain.flushInterval();
-			Properties props = convertToProperties(cacheDomain.properties());
-			assistant.useNewCache(cacheDomain.implementation(), cacheDomain.eviction(), flushInterval, size,
-					cacheDomain.readWrite(), cacheDomain.blocking(), props);
-		}
-	}
-
-	private Properties convertToProperties(Property[] properties) {
-		if (properties.length == 0) {
-			return null;
-		}
-		Properties props = new Properties();
-		for (Property property : properties) {
-			props.setProperty(property.name(), PropertyParser.parse(property.value(), configuration.getVariables()));
-		}
-		return props;
-	}
-
-	private void parseCacheRef() {
-		CacheNamespaceRef cacheDomainRef = type.getAnnotation(CacheNamespaceRef.class);
-		if (cacheDomainRef != null) {
-			Class<?> refType = cacheDomainRef.value();
-			String refName = cacheDomainRef.name();
-			if (refType == void.class && refName.isEmpty()) {
-				throw new BuilderException("Should be specified either value() or name() attribute in the @CacheNamespaceRef");
-			}
-			if (refType != void.class && !refName.isEmpty()) {
-				throw new BuilderException("Cannot use both value() and name() attribute in the @CacheNamespaceRef");
-			}
-			String namespace = (refType != void.class) ? refType.getName() : refName;
-			assistant.useCacheRef(namespace);
-		}
-	}
-
-	private String parseResultMap(Method method) {
-		Class<?> returnType = getReturnType(method);
-		ConstructorArgs args = method.getAnnotation(ConstructorArgs.class);
-		Results results = method.getAnnotation(Results.class);
-		TypeDiscriminator typeDiscriminator = method.getAnnotation(TypeDiscriminator.class);
-		String resultMapId = generateResultMapName(method);
-		applyResultMap(resultMapId, returnType, argsIf(args), resultsIf(results), typeDiscriminator);
-		return resultMapId;
-	}
-
-	private String generateResultMapName(Method method) {
-		Results results = method.getAnnotation(Results.class);
-		if (results != null && !results.id().isEmpty()) {
-			return type.getName() + "." + results.id();
-		}
-		StringBuilder suffix = new StringBuilder();
-		for (Class<?> c : method.getParameterTypes()) {
-			suffix.append("-");
-			suffix.append(c.getSimpleName());
-		}
-		if (suffix.length() < 1) {
-			suffix.append("-void");
-		}
-		return type.getName() + "." + method.getName() + suffix;
-	}
-
-	private void applyResultMap(String resultMapId, Class<?> returnType, Arg[] args, Result[] results,
-			TypeDiscriminator discriminator) {
-		List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
-		applyConstructorArgs(args, returnType, resultMappings);
-		applyResults(results, returnType, resultMappings);
-		Discriminator disc = applyDiscriminator(resultMapId, returnType, discriminator);
-		// TODO add AutoMappingBehaviour
-		assistant.addResultMap(resultMapId, returnType, null, disc, resultMappings, null);
-		createDiscriminatorResultMaps(resultMapId, returnType, discriminator);
-	}
-
-	private void createDiscriminatorResultMaps(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
-		if (discriminator != null) {
-			for (Case c : discriminator.cases()) {
-				String caseResultMapId = resultMapId + "-" + c.value();
-				List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
-				// issue #136
-				applyConstructorArgs(c.constructArgs(), resultType, resultMappings);
-				applyResults(c.results(), resultType, resultMappings);
-				// TODO add AutoMappingBehaviour
-				assistant.addResultMap(caseResultMapId, c.type(), resultMapId, null, resultMappings, null);
-			}
-		}
-	}
-
-	private Discriminator applyDiscriminator(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
-		if (discriminator != null) {
-			String column = discriminator.column();
-			Class<?> javaType = discriminator.javaType() == void.class ? String.class : discriminator.javaType();
-			JdbcType jdbcType = discriminator.jdbcType() == JdbcType.UNDEFINED ? null : discriminator.jdbcType();
-			@SuppressWarnings("unchecked")
-			Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) (discriminator.typeHandler() == UnknownTypeHandler.class ? null
-					: discriminator.typeHandler());
-			Case[] cases = discriminator.cases();
-			Map<String, String> discriminatorMap = new HashMap<String, String>();
-			for (Case c : cases) {
-				String value = c.value();
-				String caseResultMapId = resultMapId + "-" + value;
-				discriminatorMap.put(value, caseResultMapId);
-			}
-			return assistant.buildDiscriminator(resultType, column, javaType, jdbcType, typeHandler, discriminatorMap);
-		}
-		return null;
-	}
-
-	void parseStatement(Method method) {
-		Class<?> parameterTypeClass = getParameterType(method);
-		LanguageDriver languageDriver = getLanguageDriver(method);
-		SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver);
-		if (sqlSource != null) {
-			Options options = method.getAnnotation(Options.class);
-			final String mappedStatementId = type.getName() + "." + method.getName();
-			Integer fetchSize = null;
-			Integer timeout = null;
-			StatementType statementType = StatementType.PREPARED;
-			ResultSetType resultSetType = ResultSetType.FORWARD_ONLY;
-			SqlCommandType sqlCommandType = getSqlCommandType(method);
-			boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
-			boolean flushCache = !isSelect;
-			boolean useCache = isSelect;
-
-			KeyGenerator keyGenerator;
-			String keyProperty = "id";
-			String keyColumn = null;
-			if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
-				// first check for SelectKey annotation - that overrides
-				// everything else
-				SelectKey selectKey = method.getAnnotation(SelectKey.class);
-				if (selectKey != null) {
-					keyGenerator = handleSelectKeyAnnotation(selectKey, mappedStatementId, getParameterType(method),
-							languageDriver);
-					keyProperty = selectKey.keyProperty();
-				} else if (options == null) {
-					keyGenerator = configuration.isUseGeneratedKeys() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
-				} else {
-					keyGenerator = options.useGeneratedKeys() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
-					keyProperty = options.keyProperty();
-					keyColumn = options.keyColumn();
-				}
-			} else {
-				keyGenerator = new NoKeyGenerator();
-			}
-
-			if (options != null) {
-				if (FlushCachePolicy.TRUE.equals(options.flushCache())) {
-					flushCache = true;
-				} else if (FlushCachePolicy.FALSE.equals(options.flushCache())) {
-					flushCache = false;
-				}
-				useCache = options.useCache();
-				fetchSize = options.fetchSize() > -1 || options.fetchSize() == Integer.MIN_VALUE ? options.fetchSize() : null; // issue
-																																// #348
-				timeout = options.timeout() > -1 ? options.timeout() : null;
-				statementType = options.statementType();
-				resultSetType = options.resultSetType();
-			}
-
-			String resultMapId = null;
-			ResultMap resultMapAnnotation = method.getAnnotation(ResultMap.class);
-			if (resultMapAnnotation != null) {
-				String[] resultMaps = resultMapAnnotation.value();
-				StringBuilder sb = new StringBuilder();
-				for (String resultMap : resultMaps) {
-					if (sb.length() > 0) {
-						sb.append(",");
-					}
-					sb.append(resultMap);
-				}
-				resultMapId = sb.toString();
-			} else if (isSelect) {
-				resultMapId = parseResultMap(method);
-			}
-
-			assistant.addMappedStatement(mappedStatementId, sqlSource, statementType, sqlCommandType, fetchSize, timeout,
-			// ParameterMapID
-					null, parameterTypeClass, resultMapId, getReturnType(method), resultSetType, flushCache, useCache,
-					// TODO gcode issue #577
-					false, keyGenerator, keyProperty, keyColumn,
-					// DatabaseID
-					null, languageDriver,
-					// ResultSets
-					options != null ? nullOrEmpty(options.resultSets()) : null);
-		}
-	}
-
-	private LanguageDriver getLanguageDriver(Method method) {
-		Lang lang = method.getAnnotation(Lang.class);
-		Class<?> langClass = null;
-		if (lang != null) {
-			langClass = lang.value();
-		}
-		return assistant.getLanguageDriver(langClass);
-	}
-
-	private Class<?> getParameterType(Method method) {
-		Class<?> parameterType = null;
-		Class<?>[] parameterTypes = method.getParameterTypes();
-		for (Class<?> currentParameterType : parameterTypes) {
-			if (!RowBounds.class.isAssignableFrom(currentParameterType)
-					&& !ResultHandler.class.isAssignableFrom(currentParameterType)) {
-				if (parameterType == null) {
-					parameterType = currentParameterType;
-				} else {
-					// issue #135
-					parameterType = ParamMap.class;
-				}
-			}
-		}
-		return parameterType;
-	}
-
-	private Class<?> getReturnType(Method method) {
-		Class<?> returnType = method.getReturnType();
-		Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, type);
-		if (resolvedReturnType instanceof Class) {
-			returnType = (Class<?>) resolvedReturnType;
-			if (returnType.isArray()) {
-				returnType = returnType.getComponentType();
-			}
-			// gcode issue #508
-			if (void.class.equals(returnType)) {
-				ResultType rt = method.getAnnotation(ResultType.class);
-				if (rt != null) {
-					returnType = rt.value();
-				}
-			}
-		} else if (resolvedReturnType instanceof ParameterizedType) {
-			ParameterizedType parameterizedType = (ParameterizedType) resolvedReturnType;
-			Class<?> rawType = (Class<?>) parameterizedType.getRawType();
-			if (Collection.class.isAssignableFrom(rawType) || Cursor.class.isAssignableFrom(rawType)) {
-				Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
-				if (actualTypeArguments != null && actualTypeArguments.length == 1) {
-					Type returnTypeParameter = actualTypeArguments[0];
-					if (returnTypeParameter instanceof Class<?>) {
-						returnType = (Class<?>) returnTypeParameter;
-					} else if (returnTypeParameter instanceof ParameterizedType) {
-						// (gcode issue #443) actual type can be a also a
-						// parameterized type
-						returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
-					} else if (returnTypeParameter instanceof GenericArrayType) {
-						Class<?> componentType = (Class<?>) ((GenericArrayType) returnTypeParameter).getGenericComponentType();
-						// (gcode issue #525) support List<byte[]>
-						returnType = Array.newInstance(componentType, 0).getClass();
-					}
-				}
-			} else if (method.isAnnotationPresent(MapKey.class) && Map.class.isAssignableFrom(rawType)) {
-				// (gcode issue 504) Do not look into Maps if there is not
-				// MapKey annotation
-				Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
-				if (actualTypeArguments != null && actualTypeArguments.length == 2) {
-					Type returnTypeParameter = actualTypeArguments[1];
-					if (returnTypeParameter instanceof Class<?>) {
-						returnType = (Class<?>) returnTypeParameter;
-					} else if (returnTypeParameter instanceof ParameterizedType) {
-						// (gcode issue 443) actual type can be a also a
-						// parameterized type
-						returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
-					}
-				}
-			}
-		}
-
-		return returnType;
-	}
-
-	private SqlSource getSqlSourceFromAnnotations(Method method, Class<?> parameterType, LanguageDriver languageDriver) {
-		try {
-			Class<? extends Annotation> sqlAnnotationType = getSqlAnnotationType(method);
-			Class<? extends Annotation> sqlProviderAnnotationType = getSqlProviderAnnotationType(method);
-			if (sqlAnnotationType != null) {
-				if (sqlProviderAnnotationType != null) {
-					throw new BindingException("You cannot supply both a static SQL and SqlProvider to method named "
-							+ method.getName());
-				}
-				Annotation sqlAnnotation = method.getAnnotation(sqlAnnotationType);
-				final String[] strings = (String[]) sqlAnnotation.getClass().getMethod("value").invoke(sqlAnnotation);
-				return buildSqlSourceFromStrings(strings, parameterType, languageDriver);
-			} else if (sqlProviderAnnotationType != null) {
-				Annotation sqlProviderAnnotation = method.getAnnotation(sqlProviderAnnotationType);
-				return new ProviderSqlSource(assistant.getConfiguration(), sqlProviderAnnotation);
-			}
-			return null;
-		} catch (Exception e) {
-			throw new BuilderException("Could not find value method on SQL annotation.  Cause: " + e, e);
-		}
-	}
-
-	private SqlSource buildSqlSourceFromStrings(String[] strings, Class<?> parameterTypeClass, LanguageDriver languageDriver) {
-		final StringBuilder sql = new StringBuilder();
-		for (String fragment : strings) {
-			sql.append(fragment);
-			sql.append(" ");
-		}
-		return languageDriver.createSqlSource(configuration, sql.toString().trim(), parameterTypeClass);
-	}
-
-	private SqlCommandType getSqlCommandType(Method method) {
-		Class<? extends Annotation> type = getSqlAnnotationType(method);
-
-		if (type == null) {
-			type = getSqlProviderAnnotationType(method);
-
-			if (type == null) {
-				return SqlCommandType.UNKNOWN;
-			}
-
-			if (type == SelectProvider.class) {
-				type = Select.class;
-			} else if (type == InsertProvider.class) {
-				type = Insert.class;
-			} else if (type == UpdateProvider.class) {
-				type = Update.class;
-			} else if (type == DeleteProvider.class) {
-				type = Delete.class;
-			}
-		}
-
-		return SqlCommandType.valueOf(type.getSimpleName().toUpperCase(Locale.ENGLISH));
-	}
-
-	private Class<? extends Annotation> getSqlAnnotationType(Method method) {
-		return chooseAnnotationType(method, sqlAnnotationTypes);
-	}
-
-	private Class<? extends Annotation> getSqlProviderAnnotationType(Method method) {
-		return chooseAnnotationType(method, sqlProviderAnnotationTypes);
-	}
-
-	private Class<? extends Annotation> chooseAnnotationType(Method method, Set<Class<? extends Annotation>> types) {
-		for (Class<? extends Annotation> type : types) {
-			Annotation annotation = method.getAnnotation(type);
-			if (annotation != null) {
-				return type;
-			}
-		}
-		return null;
-	}
-
-	private void applyResults(Result[] results, Class<?> resultType, List<ResultMapping> resultMappings) {
-		for (Result result : results) {
-			List<ResultFlag> flags = new ArrayList<ResultFlag>();
-			if (result.id()) {
-				flags.add(ResultFlag.ID);
-			}
-			@SuppressWarnings("unchecked")
-			Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) ((result.typeHandler() == UnknownTypeHandler.class) ? null
-					: result.typeHandler());
-			ResultMapping resultMapping = assistant.buildResultMapping(resultType, nullOrEmpty(result.property()),
-					nullOrEmpty(result.column()), result.javaType() == void.class ? null : result.javaType(),
-					result.jdbcType() == JdbcType.UNDEFINED ? null : result.jdbcType(),
-					hasNestedSelect(result) ? nestedSelectId(result) : null, null, null, null, typeHandler, flags, null, null,
-					isLazy(result));
-			resultMappings.add(resultMapping);
-		}
-	}
-
-	private String nestedSelectId(Result result) {
-		String nestedSelect = result.one().select();
-		if (nestedSelect.length() < 1) {
-			nestedSelect = result.many().select();
-		}
-		if (!nestedSelect.contains(".")) {
-			nestedSelect = type.getName() + "." + nestedSelect;
-		}
-		return nestedSelect;
-	}
-
-	private boolean isLazy(Result result) {
-		boolean isLazy = configuration.isLazyLoadingEnabled();
-		if (result.one().select().length() > 0 && FetchType.DEFAULT != result.one().fetchType()) {
-			isLazy = (result.one().fetchType() == FetchType.LAZY);
-		} else if (result.many().select().length() > 0 && FetchType.DEFAULT != result.many().fetchType()) {
-			isLazy = (result.many().fetchType() == FetchType.LAZY);
-		}
-		return isLazy;
-	}
-
-	private boolean hasNestedSelect(Result result) {
-		if (result.one().select().length() > 0 && result.many().select().length() > 0) {
-			throw new BuilderException("Cannot use both @One and @Many annotations in the same @Result");
-		}
-		return result.one().select().length() > 0 || result.many().select().length() > 0;
-	}
-
-	private void applyConstructorArgs(Arg[] args, Class<?> resultType, List<ResultMapping> resultMappings) {
-		for (Arg arg : args) {
-			List<ResultFlag> flags = new ArrayList<ResultFlag>();
-			flags.add(ResultFlag.CONSTRUCTOR);
-			if (arg.id()) {
-				flags.add(ResultFlag.ID);
-			}
-			@SuppressWarnings("unchecked")
-			Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) (arg.typeHandler() == UnknownTypeHandler.class ? null
-					: arg.typeHandler());
-			ResultMapping resultMapping = assistant.buildResultMapping(resultType, null, nullOrEmpty(arg.column()),
-					arg.javaType() == void.class ? null : arg.javaType(),
-					arg.jdbcType() == JdbcType.UNDEFINED ? null : arg.jdbcType(), nullOrEmpty(arg.select()),
-					nullOrEmpty(arg.resultMap()), null, null, typeHandler, flags, null, null, false);
-			resultMappings.add(resultMapping);
-		}
-	}
-
-	private String nullOrEmpty(String value) {
-		return value == null || value.trim().length() == 0 ? null : value;
-	}
-
-	private Result[] resultsIf(Results results) {
-		return results == null ? new Result[0] : results.value();
-	}
-
-	private Arg[] argsIf(ConstructorArgs args) {
-		return args == null ? new Arg[0] : args.value();
-	}
-
-	private KeyGenerator handleSelectKeyAnnotation(SelectKey selectKeyAnnotation, String baseStatementId,
-			Class<?> parameterTypeClass, LanguageDriver languageDriver) {
-		String id = baseStatementId + SelectKeyGenerator.SELECT_KEY_SUFFIX;
-		Class<?> resultTypeClass = selectKeyAnnotation.resultType();
-		StatementType statementType = selectKeyAnnotation.statementType();
-		String keyProperty = selectKeyAnnotation.keyProperty();
-		String keyColumn = selectKeyAnnotation.keyColumn();
-		boolean executeBefore = selectKeyAnnotation.before();
-
-		// defaults
-		boolean useCache = false;
-		KeyGenerator keyGenerator = new NoKeyGenerator();
-		Integer fetchSize = null;
-		Integer timeout = null;
-		boolean flushCache = false;
-		String parameterMap = null;
-		String resultMap = null;
-		ResultSetType resultSetTypeEnum = null;
-
-		SqlSource sqlSource = buildSqlSourceFromStrings(selectKeyAnnotation.statement(), parameterTypeClass, languageDriver);
-		SqlCommandType sqlCommandType = SqlCommandType.SELECT;
-
-		assistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap,
-				parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, false, keyGenerator,
-				keyProperty, keyColumn, null, languageDriver, null);
-
-		id = assistant.applyCurrentNamespace(id, false);
-
-		MappedStatement keyStatement = configuration.getMappedStatement(id, false);
-		SelectKeyGenerator answer = new SelectKeyGenerator(keyStatement, executeBefore);
-		configuration.addKeyGenerator(id, answer);
-		return answer;
-	}
+    private final Set<Class<? extends Annotation>> sqlAnnotationTypes = new HashSet<Class<? extends Annotation>>();
+    private final Set<Class<? extends Annotation>> sqlProviderAnnotationTypes = new HashSet<Class<? extends Annotation>>();
+
+    private Configuration configuration;
+    private MapperBuilderAssistant assistant;
+    private Class<?> type;
+
+    public MybatisMapperAnnotationBuilder(Configuration configuration, Class<?> type) {
+        super(configuration, type);
+        String resource = type.getName().replace('.', '/') + ".java (best guess)";
+        this.assistant = new MapperBuilderAssistant(configuration, resource);
+        this.configuration = configuration;
+        this.type = type;
+        sqlAnnotationTypes.add(Select.class);
+        sqlAnnotationTypes.add(Insert.class);
+        sqlAnnotationTypes.add(Update.class);
+        sqlAnnotationTypes.add(Delete.class);
+        sqlProviderAnnotationTypes.add(SelectProvider.class);
+        sqlProviderAnnotationTypes.add(InsertProvider.class);
+        sqlProviderAnnotationTypes.add(UpdateProvider.class);
+        sqlProviderAnnotationTypes.add(DeleteProvider.class);
+    }
+
+    public void parse() {
+        String resource = type.toString();
+        if (!configuration.isResourceLoaded(resource)) {
+            boolean existXml = loadXmlResource();
+            configuration.addLoadedResource(resource);
+            assistant.setCurrentNamespace(type.getName());
+            parseCache();
+            parseCacheRef();
+            Method[] methods = type.getMethods();
+            // TODO 注入存在 xxMapper.xml CURD (应该在注解之前注入)
+            inspectInject(existXml);
+            for (Method method : methods) {
+                try {
+                    // issue #237
+                    if (!method.isBridge()) {
+                        parseStatement(method);
+                    }
+                } catch (IncompleteElementException e) {
+                    configuration.addIncompleteMethod(new MethodResolver(this, method));
+                }
+            }
+
+        }
+        parsePendingMethods();
+    }
+
+    /*
+     * 注入 CURD 动态 SQL(XML不存在时注入)
+     */
+    private void inspectInject(boolean flag) {
+        if (!flag && BaseMapper.class.isAssignableFrom(type)) {
+            GlobalConfiguration.getSqlInjector(configuration).inspectInject(assistant, type);
+        }
+    }
+
+    private void parsePendingMethods() {
+        Collection<MethodResolver> incompleteMethods = configuration.getIncompleteMethods();
+        synchronized (incompleteMethods) {
+            Iterator<MethodResolver> iter = incompleteMethods.iterator();
+            while (iter.hasNext()) {
+                try {
+                    iter.next().resolve();
+                    iter.remove();
+                } catch (IncompleteElementException e) {
+                    // This method is still missing a resource
+                }
+            }
+        }
+    }
+
+    /**
+     * 是否存在XML(该方法并不能客观的判断resource的路径,只是Mybatis默认认为的xml路径)
+     *
+     * @return boolean ture存在,flase不存在
+     */
+    // TODO 该方法改为返回 boolean 判断是否存在 xxxMapper.xml
+    private boolean loadXmlResource() {
+        boolean flag = true;
+        // Spring may not know the real resource name so we check a flag
+        // to prevent loading again a resource twice
+        // this flag is set at MybatisXMLMapperBuilder#bindMapperForNamespace
+        if (!configuration.isResourceLoaded("namespace:" + type.getName())) {
+            String xmlResource = type.getName().replace('.', '/') + ".xml";
+            InputStream inputStream = null;
+            try {
+                inputStream = Resources.getResourceAsStream(type.getClassLoader(), xmlResource);
+            } catch (IOException e) {
+                // ignore, resource is not required
+                flag = false;
+            }
+            if (inputStream != null) {
+                MybatisXMLMapperBuilder xmlParser = new MybatisXMLMapperBuilder(inputStream, assistant.getConfiguration(),
+                        xmlResource, configuration.getSqlFragments(), type.getName());
+                xmlParser.parse();
+            }
+        }
+        return flag;
+    }
+
+    private void parseCache() {
+        CacheNamespace cacheDomain = type.getAnnotation(CacheNamespace.class);
+        if (cacheDomain != null) {
+            Integer size = cacheDomain.size() == 0 ? null : cacheDomain.size();
+            Long flushInterval = cacheDomain.flushInterval() == 0 ? null : cacheDomain.flushInterval();
+            Properties props = convertToProperties(cacheDomain.properties());
+            assistant.useNewCache(cacheDomain.implementation(), cacheDomain.eviction(), flushInterval, size,
+                    cacheDomain.readWrite(), cacheDomain.blocking(), props);
+        }
+    }
+
+    private Properties convertToProperties(Property[] properties) {
+        if (properties.length == 0) {
+            return null;
+        }
+        Properties props = new Properties();
+        for (Property property : properties) {
+            props.setProperty(property.name(), PropertyParser.parse(property.value(), configuration.getVariables()));
+        }
+        return props;
+    }
+
+    private void parseCacheRef() {
+        CacheNamespaceRef cacheDomainRef = type.getAnnotation(CacheNamespaceRef.class);
+        if (cacheDomainRef != null) {
+            Class<?> refType = cacheDomainRef.value();
+            String refName = cacheDomainRef.name();
+            if (refType == void.class && refName.isEmpty()) {
+                throw new BuilderException("Should be specified either value() or name() attribute in the @CacheNamespaceRef");
+            }
+            if (refType != void.class && !refName.isEmpty()) {
+                throw new BuilderException("Cannot use both value() and name() attribute in the @CacheNamespaceRef");
+            }
+            String namespace = (refType != void.class) ? refType.getName() : refName;
+            assistant.useCacheRef(namespace);
+        }
+    }
+
+    private String parseResultMap(Method method) {
+        Class<?> returnType = getReturnType(method);
+        ConstructorArgs args = method.getAnnotation(ConstructorArgs.class);
+        Results results = method.getAnnotation(Results.class);
+        TypeDiscriminator typeDiscriminator = method.getAnnotation(TypeDiscriminator.class);
+        String resultMapId = generateResultMapName(method);
+        applyResultMap(resultMapId, returnType, argsIf(args), resultsIf(results), typeDiscriminator);
+        return resultMapId;
+    }
+
+    private String generateResultMapName(Method method) {
+        Results results = method.getAnnotation(Results.class);
+        if (results != null && !results.id().isEmpty()) {
+            return type.getName() + "." + results.id();
+        }
+        StringBuilder suffix = new StringBuilder();
+        for (Class<?> c : method.getParameterTypes()) {
+            suffix.append("-");
+            suffix.append(c.getSimpleName());
+        }
+        if (suffix.length() < 1) {
+            suffix.append("-void");
+        }
+        return type.getName() + "." + method.getName() + suffix;
+    }
+
+    private void applyResultMap(String resultMapId, Class<?> returnType, Arg[] args, Result[] results,
+                                TypeDiscriminator discriminator) {
+        List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
+        applyConstructorArgs(args, returnType, resultMappings);
+        applyResults(results, returnType, resultMappings);
+        Discriminator disc = applyDiscriminator(resultMapId, returnType, discriminator);
+        // TODO add AutoMappingBehaviour
+        assistant.addResultMap(resultMapId, returnType, null, disc, resultMappings, null);
+        createDiscriminatorResultMaps(resultMapId, returnType, discriminator);
+    }
+
+    private void createDiscriminatorResultMaps(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
+        if (discriminator != null) {
+            for (Case c : discriminator.cases()) {
+                String caseResultMapId = resultMapId + "-" + c.value();
+                List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
+                // issue #136
+                applyConstructorArgs(c.constructArgs(), resultType, resultMappings);
+                applyResults(c.results(), resultType, resultMappings);
+                // TODO add AutoMappingBehaviour
+                assistant.addResultMap(caseResultMapId, c.type(), resultMapId, null, resultMappings, null);
+            }
+        }
+    }
+
+    private Discriminator applyDiscriminator(String resultMapId, Class<?> resultType, TypeDiscriminator discriminator) {
+        if (discriminator != null) {
+            String column = discriminator.column();
+            Class<?> javaType = discriminator.javaType() == void.class ? String.class : discriminator.javaType();
+            JdbcType jdbcType = discriminator.jdbcType() == JdbcType.UNDEFINED ? null : discriminator.jdbcType();
+            @SuppressWarnings("unchecked")
+            Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) (discriminator.typeHandler() == UnknownTypeHandler.class ? null
+                    : discriminator.typeHandler());
+            Case[] cases = discriminator.cases();
+            Map<String, String> discriminatorMap = new HashMap<String, String>();
+            for (Case c : cases) {
+                String value = c.value();
+                String caseResultMapId = resultMapId + "-" + value;
+                discriminatorMap.put(value, caseResultMapId);
+            }
+            return assistant.buildDiscriminator(resultType, column, javaType, jdbcType, typeHandler, discriminatorMap);
+        }
+        return null;
+    }
+
+    void parseStatement(Method method) {
+        Class<?> parameterTypeClass = getParameterType(method);
+        LanguageDriver languageDriver = getLanguageDriver(method);
+        SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver);
+        if (sqlSource != null) {
+            Options options = method.getAnnotation(Options.class);
+            final String mappedStatementId = type.getName() + "." + method.getName();
+            Integer fetchSize = null;
+            Integer timeout = null;
+            StatementType statementType = StatementType.PREPARED;
+            ResultSetType resultSetType = ResultSetType.FORWARD_ONLY;
+            SqlCommandType sqlCommandType = getSqlCommandType(method);
+            boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
+            boolean flushCache = !isSelect;
+            boolean useCache = isSelect;
+
+            KeyGenerator keyGenerator;
+            String keyProperty = "id";
+            String keyColumn = null;
+            if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) {
+                // first check for SelectKey annotation - that overrides
+                // everything else
+                SelectKey selectKey = method.getAnnotation(SelectKey.class);
+                if (selectKey != null) {
+                    keyGenerator = handleSelectKeyAnnotation(selectKey, mappedStatementId, getParameterType(method),
+                            languageDriver);
+                    keyProperty = selectKey.keyProperty();
+                } else if (options == null) {
+                    keyGenerator = configuration.isUseGeneratedKeys() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
+                } else {
+                    keyGenerator = options.useGeneratedKeys() ? new Jdbc3KeyGenerator() : new NoKeyGenerator();
+                    keyProperty = options.keyProperty();
+                    keyColumn = options.keyColumn();
+                }
+            } else {
+                keyGenerator = new NoKeyGenerator();
+            }
+
+            if (options != null) {
+                if (FlushCachePolicy.TRUE.equals(options.flushCache())) {
+                    flushCache = true;
+                } else if (FlushCachePolicy.FALSE.equals(options.flushCache())) {
+                    flushCache = false;
+                }
+                useCache = options.useCache();
+                fetchSize = options.fetchSize() > -1 || options.fetchSize() == Integer.MIN_VALUE ? options.fetchSize() : null; // issue
+                // #348
+                timeout = options.timeout() > -1 ? options.timeout() : null;
+                statementType = options.statementType();
+                resultSetType = options.resultSetType();
+            }
+
+            String resultMapId = null;
+            ResultMap resultMapAnnotation = method.getAnnotation(ResultMap.class);
+            if (resultMapAnnotation != null) {
+                String[] resultMaps = resultMapAnnotation.value();
+                StringBuilder sb = new StringBuilder();
+                for (String resultMap : resultMaps) {
+                    if (sb.length() > 0) {
+                        sb.append(",");
+                    }
+                    sb.append(resultMap);
+                }
+                resultMapId = sb.toString();
+            } else if (isSelect) {
+                resultMapId = parseResultMap(method);
+            }
+
+            assistant.addMappedStatement(mappedStatementId, sqlSource, statementType, sqlCommandType, fetchSize, timeout,
+                    // ParameterMapID
+                    null, parameterTypeClass, resultMapId, getReturnType(method), resultSetType, flushCache, useCache,
+                    // TODO gcode issue #577
+                    false, keyGenerator, keyProperty, keyColumn,
+                    // DatabaseID
+                    null, languageDriver,
+                    // ResultSets
+                    options != null ? nullOrEmpty(options.resultSets()) : null);
+        }
+    }
+
+    private LanguageDriver getLanguageDriver(Method method) {
+        Lang lang = method.getAnnotation(Lang.class);
+        Class<?> langClass = null;
+        if (lang != null) {
+            langClass = lang.value();
+        }
+        return assistant.getLanguageDriver(langClass);
+    }
+
+    private Class<?> getParameterType(Method method) {
+        Class<?> parameterType = null;
+        Class<?>[] parameterTypes = method.getParameterTypes();
+        for (Class<?> currentParameterType : parameterTypes) {
+            if (!RowBounds.class.isAssignableFrom(currentParameterType)
+                    && !ResultHandler.class.isAssignableFrom(currentParameterType)) {
+                if (parameterType == null) {
+                    parameterType = currentParameterType;
+                } else {
+                    // issue #135
+                    parameterType = ParamMap.class;
+                }
+            }
+        }
+        return parameterType;
+    }
+
+    private Class<?> getReturnType(Method method) {
+        Class<?> returnType = method.getReturnType();
+        Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, type);
+        if (resolvedReturnType instanceof Class) {
+            returnType = (Class<?>) resolvedReturnType;
+            if (returnType.isArray()) {
+                returnType = returnType.getComponentType();
+            }
+            // gcode issue #508
+            if (void.class.equals(returnType)) {
+                ResultType rt = method.getAnnotation(ResultType.class);
+                if (rt != null) {
+                    returnType = rt.value();
+                }
+            }
+        } else if (resolvedReturnType instanceof ParameterizedType) {
+            ParameterizedType parameterizedType = (ParameterizedType) resolvedReturnType;
+            Class<?> rawType = (Class<?>) parameterizedType.getRawType();
+            if (Collection.class.isAssignableFrom(rawType) || Cursor.class.isAssignableFrom(rawType)) {
+                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+                if (actualTypeArguments != null && actualTypeArguments.length == 1) {
+                    Type returnTypeParameter = actualTypeArguments[0];
+                    if (returnTypeParameter instanceof Class<?>) {
+                        returnType = (Class<?>) returnTypeParameter;
+                    } else if (returnTypeParameter instanceof ParameterizedType) {
+                        // (gcode issue #443) actual type can be a also a
+                        // parameterized type
+                        returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
+                    } else if (returnTypeParameter instanceof GenericArrayType) {
+                        Class<?> componentType = (Class<?>) ((GenericArrayType) returnTypeParameter).getGenericComponentType();
+                        // (gcode issue #525) support List<byte[]>
+                        returnType = Array.newInstance(componentType, 0).getClass();
+                    }
+                }
+            } else if (method.isAnnotationPresent(MapKey.class) && Map.class.isAssignableFrom(rawType)) {
+                // (gcode issue 504) Do not look into Maps if there is not
+                // MapKey annotation
+                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+                if (actualTypeArguments != null && actualTypeArguments.length == 2) {
+                    Type returnTypeParameter = actualTypeArguments[1];
+                    if (returnTypeParameter instanceof Class<?>) {
+                        returnType = (Class<?>) returnTypeParameter;
+                    } else if (returnTypeParameter instanceof ParameterizedType) {
+                        // (gcode issue 443) actual type can be a also a
+                        // parameterized type
+                        returnType = (Class<?>) ((ParameterizedType) returnTypeParameter).getRawType();
+                    }
+                }
+            }
+        }
+
+        return returnType;
+    }
+
+    private SqlSource getSqlSourceFromAnnotations(Method method, Class<?> parameterType, LanguageDriver languageDriver) {
+        try {
+            Class<? extends Annotation> sqlAnnotationType = getSqlAnnotationType(method);
+            Class<? extends Annotation> sqlProviderAnnotationType = getSqlProviderAnnotationType(method);
+            if (sqlAnnotationType != null) {
+                if (sqlProviderAnnotationType != null) {
+                    throw new BindingException("You cannot supply both a static SQL and SqlProvider to method named "
+                            + method.getName());
+                }
+                Annotation sqlAnnotation = method.getAnnotation(sqlAnnotationType);
+                final String[] strings = (String[]) sqlAnnotation.getClass().getMethod("value").invoke(sqlAnnotation);
+                return buildSqlSourceFromStrings(strings, parameterType, languageDriver);
+            } else if (sqlProviderAnnotationType != null) {
+                Annotation sqlProviderAnnotation = method.getAnnotation(sqlProviderAnnotationType);
+                return new ProviderSqlSource(assistant.getConfiguration(), sqlProviderAnnotation);
+            }
+            return null;
+        } catch (Exception e) {
+            throw new BuilderException("Could not find value method on SQL annotation.  Cause: " + e, e);
+        }
+    }
+
+    private SqlSource buildSqlSourceFromStrings(String[] strings, Class<?> parameterTypeClass, LanguageDriver languageDriver) {
+        final StringBuilder sql = new StringBuilder();
+        for (String fragment : strings) {
+            sql.append(fragment);
+            sql.append(" ");
+        }
+        return languageDriver.createSqlSource(configuration, sql.toString().trim(), parameterTypeClass);
+    }
+
+    private SqlCommandType getSqlCommandType(Method method) {
+        Class<? extends Annotation> type = getSqlAnnotationType(method);
+
+        if (type == null) {
+            type = getSqlProviderAnnotationType(method);
+
+            if (type == null) {
+                return SqlCommandType.UNKNOWN;
+            }
+
+            if (type == SelectProvider.class) {
+                type = Select.class;
+            } else if (type == InsertProvider.class) {
+                type = Insert.class;
+            } else if (type == UpdateProvider.class) {
+                type = Update.class;
+            } else if (type == DeleteProvider.class) {
+                type = Delete.class;
+            }
+        }
+
+        return SqlCommandType.valueOf(type.getSimpleName().toUpperCase(Locale.ENGLISH));
+    }
+
+    private Class<? extends Annotation> getSqlAnnotationType(Method method) {
+        return chooseAnnotationType(method, sqlAnnotationTypes);
+    }
+
+    private Class<? extends Annotation> getSqlProviderAnnotationType(Method method) {
+        return chooseAnnotationType(method, sqlProviderAnnotationTypes);
+    }
+
+    private Class<? extends Annotation> chooseAnnotationType(Method method, Set<Class<? extends Annotation>> types) {
+        for (Class<? extends Annotation> type : types) {
+            Annotation annotation = method.getAnnotation(type);
+            if (annotation != null) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    private void applyResults(Result[] results, Class<?> resultType, List<ResultMapping> resultMappings) {
+        for (Result result : results) {
+            List<ResultFlag> flags = new ArrayList<ResultFlag>();
+            if (result.id()) {
+                flags.add(ResultFlag.ID);
+            }
+            @SuppressWarnings("unchecked")
+            Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) ((result.typeHandler() == UnknownTypeHandler.class) ? null
+                    : result.typeHandler());
+            ResultMapping resultMapping = assistant.buildResultMapping(resultType, nullOrEmpty(result.property()),
+                    nullOrEmpty(result.column()), result.javaType() == void.class ? null : result.javaType(),
+                    result.jdbcType() == JdbcType.UNDEFINED ? null : result.jdbcType(),
+                    hasNestedSelect(result) ? nestedSelectId(result) : null, null, null, null, typeHandler, flags, null, null,
+                    isLazy(result));
+            resultMappings.add(resultMapping);
+        }
+    }
+
+    private String nestedSelectId(Result result) {
+        String nestedSelect = result.one().select();
+        if (nestedSelect.length() < 1) {
+            nestedSelect = result.many().select();
+        }
+        if (!nestedSelect.contains(".")) {
+            nestedSelect = type.getName() + "." + nestedSelect;
+        }
+        return nestedSelect;
+    }
+
+    private boolean isLazy(Result result) {
+        boolean isLazy = configuration.isLazyLoadingEnabled();
+        if (result.one().select().length() > 0 && FetchType.DEFAULT != result.one().fetchType()) {
+            isLazy = (result.one().fetchType() == FetchType.LAZY);
+        } else if (result.many().select().length() > 0 && FetchType.DEFAULT != result.many().fetchType()) {
+            isLazy = (result.many().fetchType() == FetchType.LAZY);
+        }
+        return isLazy;
+    }
+
+    private boolean hasNestedSelect(Result result) {
+        if (result.one().select().length() > 0 && result.many().select().length() > 0) {
+            throw new BuilderException("Cannot use both @One and @Many annotations in the same @Result");
+        }
+        return result.one().select().length() > 0 || result.many().select().length() > 0;
+    }
+
+    private void applyConstructorArgs(Arg[] args, Class<?> resultType, List<ResultMapping> resultMappings) {
+        for (Arg arg : args) {
+            List<ResultFlag> flags = new ArrayList<ResultFlag>();
+            flags.add(ResultFlag.CONSTRUCTOR);
+            if (arg.id()) {
+                flags.add(ResultFlag.ID);
+            }
+            @SuppressWarnings("unchecked")
+            Class<? extends TypeHandler<?>> typeHandler = (Class<? extends TypeHandler<?>>) (arg.typeHandler() == UnknownTypeHandler.class ? null
+                    : arg.typeHandler());
+            ResultMapping resultMapping = assistant.buildResultMapping(resultType, null, nullOrEmpty(arg.column()),
+                    arg.javaType() == void.class ? null : arg.javaType(),
+                    arg.jdbcType() == JdbcType.UNDEFINED ? null : arg.jdbcType(), nullOrEmpty(arg.select()),
+                    nullOrEmpty(arg.resultMap()), null, null, typeHandler, flags, null, null, false);
+            resultMappings.add(resultMapping);
+        }
+    }
+
+    private String nullOrEmpty(String value) {
+        return value == null || value.trim().length() == 0 ? null : value;
+    }
+
+    private Result[] resultsIf(Results results) {
+        return results == null ? new Result[0] : results.value();
+    }
+
+    private Arg[] argsIf(ConstructorArgs args) {
+        return args == null ? new Arg[0] : args.value();
+    }
+
+    private KeyGenerator handleSelectKeyAnnotation(SelectKey selectKeyAnnotation, String baseStatementId,
+                                                   Class<?> parameterTypeClass, LanguageDriver languageDriver) {
+        String id = baseStatementId + SelectKeyGenerator.SELECT_KEY_SUFFIX;
+        Class<?> resultTypeClass = selectKeyAnnotation.resultType();
+        StatementType statementType = selectKeyAnnotation.statementType();
+        String keyProperty = selectKeyAnnotation.keyProperty();
+        String keyColumn = selectKeyAnnotation.keyColumn();
+        boolean executeBefore = selectKeyAnnotation.before();
+
+        // defaults
+        boolean useCache = false;
+        KeyGenerator keyGenerator = new NoKeyGenerator();
+        Integer fetchSize = null;
+        Integer timeout = null;
+        boolean flushCache = false;
+        String parameterMap = null;
+        String resultMap = null;
+        ResultSetType resultSetTypeEnum = null;
+
+        SqlSource sqlSource = buildSqlSourceFromStrings(selectKeyAnnotation.statement(), parameterTypeClass, languageDriver);
+        SqlCommandType sqlCommandType = SqlCommandType.SELECT;
+
+        assistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap,
+                parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, false, keyGenerator,
+                keyProperty, keyColumn, null, languageDriver, null);
+
+        id = assistant.applyCurrentNamespace(id, false);
+
+        MappedStatement keyStatement = configuration.getMappedStatement(id, false);
+        SelectKeyGenerator answer = new SelectKeyGenerator(keyStatement, executeBefore);
+        configuration.addKeyGenerator(id, answer);
+        return answer;
+    }
 
 }

+ 74 - 73
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisMapperRegistry.java

@@ -1,31 +1,32 @@
 /**
- *    Copyright 2009-2015 the original author or authors.
- *
- *    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
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *    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 License for the specific language governing permissions and
- *    limitations under the License.
+ * Copyright 2009-2015 the original author or authors.
+ * <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 License for the specific language governing permissions and
+ * limitations under the License.
  */
 package com.baomidou.mybatisplus;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
 import org.apache.ibatis.binding.BindingException;
 import org.apache.ibatis.binding.MapperProxyFactory;
 import org.apache.ibatis.binding.MapperRegistry;
 import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.session.SqlSession;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
 
 /**
  * <p>
@@ -37,66 +38,66 @@ import java.util.Map;
  */
 public class MybatisMapperRegistry extends MapperRegistry {
 
-	private final Configuration config;
-	private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
+    private final Configuration config;
+    private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();
 
-	public MybatisMapperRegistry(Configuration config) {
-		super(config);
-		this.config = config;
-		// TODO注入SqlRunner
-		GlobalConfiguration.getSqlInjector(config).injectSqlRunner(config);
-	}
+    public MybatisMapperRegistry(Configuration config) {
+        super(config);
+        this.config = config;
+        // TODO注入SqlRunner
+        GlobalConfiguration.getSqlInjector(config).injectSqlRunner(config);
+    }
 
-	@SuppressWarnings("unchecked")
-	public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
-		final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
-		if (mapperProxyFactory == null) {
-			throw new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry.");
-		}
-		try {
-			return mapperProxyFactory.newInstance(sqlSession);
-		} catch (Exception e) {
-			throw new BindingException("Error getting mapper instance. Cause: " + e, e);
-		}
-	}
+    @SuppressWarnings("unchecked")
+    public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
+        final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
+        if (mapperProxyFactory == null) {
+            throw new BindingException("Type " + type + " is not known to the MybatisPlusMapperRegistry.");
+        }
+        try {
+            return mapperProxyFactory.newInstance(sqlSession);
+        } catch (Exception e) {
+            throw new BindingException("Error getting mapper instance. Cause: " + e, e);
+        }
+    }
 
-	public <T> boolean hasMapper(Class<T> type) {
-		return knownMappers.containsKey(type);
-	}
+    public <T> boolean hasMapper(Class<T> type) {
+        return knownMappers.containsKey(type);
+    }
 
-	public <T> void addMapper(Class<T> type) {
-		if (type.isInterface()) {
-			if (hasMapper(type)) {
-				// TODO 如果之前注入 直接返回
-				return;
-				// throw new BindingException("Type " + type +
-				// " is already known to the MybatisPlusMapperRegistry.");
-			}
-			boolean loadCompleted = false;
-			try {
-				knownMappers.put(type, new MapperProxyFactory<T>(type));
-				// It's important that the type is added before the parser is
-				// run
-				// otherwise the binding may automatically be attempted by the
-				// mapper parser. If the type is already known, it won't try.
+    public <T> void addMapper(Class<T> type) {
+        if (type.isInterface()) {
+            if (hasMapper(type)) {
+                // TODO 如果之前注入 直接返回
+                return;
+                // throw new BindingException("Type " + type +
+                // " is already known to the MybatisPlusMapperRegistry.");
+            }
+            boolean loadCompleted = false;
+            try {
+                knownMappers.put(type, new MapperProxyFactory<T>(type));
+                // It's important that the type is added before the parser is
+                // run
+                // otherwise the binding may automatically be attempted by the
+                // mapper parser. If the type is already known, it won't try.
 
-				// TODO 自定义无 XML 注入
-				MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
-				parser.parse();
-				loadCompleted = true;
-			} finally {
-				if (!loadCompleted) {
-					knownMappers.remove(type);
-				}
-			}
-		}
-	}
+                // TODO 自定义无 XML 注入
+                MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
+                parser.parse();
+                loadCompleted = true;
+            } finally {
+                if (!loadCompleted) {
+                    knownMappers.remove(type);
+                }
+            }
+        }
+    }
 
-	/**
-	 * @since 3.2.2
-	 */
-	public Collection<Class<?>> getMappers() {
-		return Collections.unmodifiableCollection(knownMappers.keySet());
-	}
+    /**
+     * @since 3.2.2
+     */
+    public Collection<Class<?>> getMappers() {
+        return Collections.unmodifiableCollection(knownMappers.keySet());
+    }
 
 }

+ 33 - 33
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisSessionFactoryBuilder.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
@@ -31,43 +31,43 @@ import com.baomidou.mybatisplus.toolkit.IOUtils;
  * <p>
  * replace default SqlSessionFactoryBuilder class
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class MybatisSessionFactoryBuilder extends SqlSessionFactoryBuilder {
 
-	private GlobalConfiguration globalConfig = GlobalConfiguration.defaults();
+    private GlobalConfiguration globalConfig = GlobalConfiguration.defaults();
 
-	@Override
-	public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
-		try {
-			MybatisXMLConfigBuilder parser = new MybatisXMLConfigBuilder(reader, environment, properties);
-			return globalConfig.signGlobalConfig(build(parser.parse()));
-		} catch (Exception e) {
-			throw ExceptionFactory.wrapException("Error building SqlSession.", e);
-		} finally {
-			ErrorContext.instance().reset();
-			IOUtils.closeQuietly(reader);
-		}
-	}
+    @Override
+    public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
+        try {
+            MybatisXMLConfigBuilder parser = new MybatisXMLConfigBuilder(reader, environment, properties);
+            return globalConfig.signGlobalConfig(build(parser.parse()));
+        } catch (Exception e) {
+            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
+        } finally {
+            ErrorContext.instance().reset();
+            IOUtils.closeQuietly(reader);
+        }
+    }
 
-	@Override
-	public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
-		try {
-			MybatisXMLConfigBuilder parser = new MybatisXMLConfigBuilder(inputStream, environment, properties);
-			return globalConfig.signGlobalConfig(build(parser.parse()));
-		} catch (Exception e) {
-			throw ExceptionFactory.wrapException("Error building SqlSession.", e);
-		} finally {
-			ErrorContext.instance().reset();
-			IOUtils.closeQuietly(inputStream);
-		}
-	}
+    @Override
+    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
+        try {
+            MybatisXMLConfigBuilder parser = new MybatisXMLConfigBuilder(inputStream, environment, properties);
+            return globalConfig.signGlobalConfig(build(parser.parse()));
+        } catch (Exception e) {
+            throw ExceptionFactory.wrapException("Error building SqlSession.", e);
+        } finally {
+            ErrorContext.instance().reset();
+            IOUtils.closeQuietly(inputStream);
+        }
+    }
 
-	// TODO 注入全局配置
-	public void setGlobalConfig(GlobalConfiguration globalConfig) {
-		this.globalConfig = globalConfig;
-	}
+    // TODO 注入全局配置
+    public void setGlobalConfig(GlobalConfiguration globalConfig) {
+        this.globalConfig = globalConfig;
+    }
 
 }

+ 383 - 382
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisSqlSessionTemplate.java

@@ -1,21 +1,29 @@
 /**
- *    Copyright 2010-2016 the original author or authors.
- *
- *    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
- *
- *       http://www.apache.org/licenses/LICENSE-2.0
- *
- *    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 License for the specific language governing permissions and
- *    limitations under the License.
+ * Copyright 2010-2016 the original author or authors.
+ * <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 License for the specific language governing permissions and
+ * limitations under the License.
  */
 package com.baomidou.mybatisplus;
 
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import static java.lang.reflect.Proxy.newProxyInstance;
+import static org.springframework.util.Assert.notNull;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.sql.Connection;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.ibatis.cursor.Cursor;
 import org.apache.ibatis.executor.BatchResult;
 import org.apache.ibatis.session.Configuration;
@@ -28,387 +36,380 @@ import org.mybatis.spring.MyBatisExceptionTranslator;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.dao.support.PersistenceExceptionTranslator;
 
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.sql.Connection;
-import java.util.List;
-import java.util.Map;
-
-import static java.lang.reflect.Proxy.newProxyInstance;
-import static org.springframework.util.Assert.notNull;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 
 /**
  * Copy SqlSessionTemplate
- * 
+ *
  * @see org.mybatis.spring.SqlSessionTemplate
  */
 public class MybatisSqlSessionTemplate implements SqlSession, DisposableBean {
 
-	private final SqlSessionFactory sqlSessionFactory;
-
-	private final ExecutorType executorType;
-
-	private final SqlSession sqlSessionProxy;
-
-	private final PersistenceExceptionTranslator exceptionTranslator;
-
-	/**
-	 * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
-	 * provided as an argument.
-	 *
-	 * @param sqlSessionFactory
-	 */
-	public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
-		this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
-	}
-
-	/**
-	 * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
-	 * provided as an argument and the given {@code ExecutorType}
-	 * {@code ExecutorType} cannot be changed once the
-	 * {@code SqlSessionTemplate} is constructed.
-	 *
-	 * @param sqlSessionFactory
-	 * @param executorType
-	 */
-	public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
-		this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration()
-				.getEnvironment().getDataSource(), true));
-	}
-
-	/**
-	 * Constructs a Spring managed {@code SqlSession} with the given
-	 * {@code SqlSessionFactory} and {@code ExecutorType}. A custom
-	 * {@code SQLExceptionTranslator} can be provided as an argument so any
-	 * {@code PersistenceException} thrown by MyBatis can be custom translated
-	 * to a {@code RuntimeException} The {@code SQLExceptionTranslator} can also
-	 * be null and thus no exception translation will be done and MyBatis
-	 * exceptions will be thrown
-	 *
-	 * @param sqlSessionFactory
-	 * @param executorType
-	 * @param exceptionTranslator
-	 */
-	public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
-			PersistenceExceptionTranslator exceptionTranslator) {
-
-		notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
-		notNull(executorType, "Property 'executorType' is required");
-
-		this.sqlSessionFactory = sqlSessionFactory;
-		this.executorType = executorType;
-		this.exceptionTranslator = exceptionTranslator;
-		this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
-				new Class[] { SqlSession.class }, new SqlSessionInterceptor());
-	}
-
-	public SqlSessionFactory getSqlSessionFactory() {
-		return this.sqlSessionFactory;
-	}
-
-	public ExecutorType getExecutorType() {
-		return this.executorType;
-	}
-
-	public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
-		return this.exceptionTranslator;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <T> T selectOne(String statement) {
-		return this.sqlSessionProxy.<T> selectOne(statement);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <T> T selectOne(String statement, Object parameter) {
-		return this.sqlSessionProxy.<T> selectOne(statement, parameter);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
-		return this.sqlSessionProxy.<K, V> selectMap(statement, mapKey);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
-		return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
-		return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey, rowBounds);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <T> Cursor<T> selectCursor(String statement) {
-		return this.sqlSessionProxy.selectCursor(statement);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <T> Cursor<T> selectCursor(String statement, Object parameter) {
-		return this.sqlSessionProxy.selectCursor(statement, parameter);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
-		return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <E> List<E> selectList(String statement) {
-		return this.sqlSessionProxy.<E> selectList(statement);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <E> List<E> selectList(String statement, Object parameter) {
-		return this.sqlSessionProxy.<E> selectList(statement, parameter);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
-		return this.sqlSessionProxy.<E> selectList(statement, parameter, rowBounds);
-	}
+    private final SqlSessionFactory sqlSessionFactory;
+
+    private final ExecutorType executorType;
+
+    private final SqlSession sqlSessionProxy;
+
+    private final PersistenceExceptionTranslator exceptionTranslator;
+
+    /**
+     * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
+     * provided as an argument.
+     *
+     * @param sqlSessionFactory
+     */
+    public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
+        this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
+    }
+
+    /**
+     * Constructs a Spring managed SqlSession with the {@code SqlSessionFactory}
+     * provided as an argument and the given {@code ExecutorType}
+     * {@code ExecutorType} cannot be changed once the
+     * {@code SqlSessionTemplate} is constructed.
+     *
+     * @param sqlSessionFactory
+     * @param executorType
+     */
+    public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
+        this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration()
+                .getEnvironment().getDataSource(), true));
+    }
+
+    /**
+     * Constructs a Spring managed {@code SqlSession} with the given
+     * {@code SqlSessionFactory} and {@code ExecutorType}. A custom
+     * {@code SQLExceptionTranslator} can be provided as an argument so any
+     * {@code PersistenceException} thrown by MyBatis can be custom translated
+     * to a {@code RuntimeException} The {@code SQLExceptionTranslator} can also
+     * be null and thus no exception translation will be done and MyBatis
+     * exceptions will be thrown
+     *
+     * @param sqlSessionFactory
+     * @param executorType
+     * @param exceptionTranslator
+     */
+    public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
+                                     PersistenceExceptionTranslator exceptionTranslator) {
+
+        notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
+        notNull(executorType, "Property 'executorType' is required");
+
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.executorType = executorType;
+        this.exceptionTranslator = exceptionTranslator;
+        this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),
+                new Class[]{SqlSession.class}, new SqlSessionInterceptor());
+    }
+
+    public SqlSessionFactory getSqlSessionFactory() {
+        return this.sqlSessionFactory;
+    }
+
+    public ExecutorType getExecutorType() {
+        return this.executorType;
+    }
+
+    public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
+        return this.exceptionTranslator;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <T> T selectOne(String statement) {
+        return this.sqlSessionProxy.<T>selectOne(statement);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <T> T selectOne(String statement, Object parameter) {
+        return this.sqlSessionProxy.<T>selectOne(statement, parameter);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
+        return this.sqlSessionProxy.<K, V>selectMap(statement, mapKey);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
+        return this.sqlSessionProxy.<K, V>selectMap(statement, parameter, mapKey);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
+        return this.sqlSessionProxy.<K, V>selectMap(statement, parameter, mapKey, rowBounds);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <T> Cursor<T> selectCursor(String statement) {
+        return this.sqlSessionProxy.selectCursor(statement);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <T> Cursor<T> selectCursor(String statement, Object parameter) {
+        return this.sqlSessionProxy.selectCursor(statement, parameter);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
+        return this.sqlSessionProxy.selectCursor(statement, parameter, rowBounds);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <E> List<E> selectList(String statement) {
+        return this.sqlSessionProxy.<E>selectList(statement);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <E> List<E> selectList(String statement, Object parameter) {
+        return this.sqlSessionProxy.<E>selectList(statement, parameter);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
+        return this.sqlSessionProxy.<E>selectList(statement, parameter, rowBounds);
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
+    /**
+     * {@inheritDoc}
+     */
 
-	@SuppressWarnings("rawtypes")
-	public void select(String statement, ResultHandler handler) {
-		this.sqlSessionProxy.select(statement, handler);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	@SuppressWarnings("rawtypes")
-	public void select(String statement, Object parameter, ResultHandler handler) {
-		this.sqlSessionProxy.select(statement, parameter, handler);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	@SuppressWarnings("rawtypes")
-	public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
-		this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
-	}
+    @SuppressWarnings("rawtypes")
+    public void select(String statement, ResultHandler handler) {
+        this.sqlSessionProxy.select(statement, handler);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    @SuppressWarnings("rawtypes")
+    public void select(String statement, Object parameter, ResultHandler handler) {
+        this.sqlSessionProxy.select(statement, parameter, handler);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    @SuppressWarnings("rawtypes")
+    public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
+        this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
+    /**
+     * {@inheritDoc}
+     */
 
-	public int insert(String statement) {
-		return this.sqlSessionProxy.insert(statement);
-	}
+    public int insert(String statement) {
+        return this.sqlSessionProxy.insert(statement);
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
+    /**
+     * {@inheritDoc}
+     */
 
-	public int insert(String statement, Object parameter) {
-		return this.sqlSessionProxy.insert(statement, parameter);
-	}
+    public int insert(String statement, Object parameter) {
+        return this.sqlSessionProxy.insert(statement, parameter);
+    }
 
-	/**
-	 * {@inheritDoc}
-	 */
+    /**
+     * {@inheritDoc}
+     */
 
-	public int update(String statement) {
-		return this.sqlSessionProxy.update(statement);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public int update(String statement, Object parameter) {
-		return this.sqlSessionProxy.update(statement, parameter);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public int delete(String statement) {
-		return this.sqlSessionProxy.delete(statement);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public int delete(String statement, Object parameter) {
-		return this.sqlSessionProxy.delete(statement, parameter);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public <T> T getMapper(Class<T> type) {
-		return getConfiguration().getMapper(type, this);
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public void commit() {
-		throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public void commit(boolean force) {
-		throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public void rollback() {
-		throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public void rollback(boolean force) {
-		throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public void close() {
-		throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public void clearCache() {
-		this.sqlSessionProxy.clearCache();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public Configuration getConfiguration() {
-		return this.sqlSessionFactory.getConfiguration();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-
-	public Connection getConnection() {
-		return this.sqlSessionProxy.getConnection();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 *
-	 * @since 1.0.2
-	 */
-
-	public List<BatchResult> flushStatements() {
-		return this.sqlSessionProxy.flushStatements();
-	}
-
-	/**
-	 * Allow gently dispose bean:
-	 * <p>
-	 * 
-	 * <pre>
-	 * {@code
-	 * 
-	 * <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
-	 *  <constructor-arg index="0" ref="sqlSessionFactory" />
-	 * </bean>
-	 * }
-	 * </pre>
-	 * <p>
-	 * The implementation of {@link DisposableBean} forces spring context to use
-	 * {@link DisposableBean#destroy()} method instead of
-	 * {@link MybatisSqlSessionTemplate#close()} to shutdown gently.
-	 *
-	 * @see MybatisSqlSessionTemplate#close()
-	 * @see org.springframework.beans.factory.support.DisposableBeanAdapter#inferDestroyMethodIfNecessary
-	 * @see org.springframework.beans.factory.support.DisposableBeanAdapter#CLOSE_METHOD_NAME
-	 */
-
-	public void destroy() throws Exception {
-		// This method forces spring disposer to avoid call of
-		// SqlSessionTemplate.close() which gives UnsupportedOperationException
-	}
-
-	/**
-	 * Proxy needed to route MyBatis method calls to the proper SqlSession got
-	 * from Spring's Transaction Manager It also unwraps exceptions thrown by
-	 * {@code Method#invoke(Object, Object...)} to pass a
-	 * {@code PersistenceException} to the
-	 * {@code PersistenceExceptionTranslator}.
-	 */
-	private class SqlSessionInterceptor implements InvocationHandler {
-
-		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-			SqlSession sqlSession = MybatisSqlSessionTemplate.this.sqlSessionFactory
-					.openSession(MybatisSqlSessionTemplate.this.executorType);
-			try {
-				Object result = method.invoke(sqlSession, args);
-				sqlSession.commit(true);
-				return result;
-			} catch (Throwable t) {
-				throw new MybatisPlusException(t);
-			} finally {
-				if (sqlSession != null) {
-					sqlSession.close();
-				}
-			}
-		}
-	}
+    public int update(String statement) {
+        return this.sqlSessionProxy.update(statement);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public int update(String statement, Object parameter) {
+        return this.sqlSessionProxy.update(statement, parameter);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public int delete(String statement) {
+        return this.sqlSessionProxy.delete(statement);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public int delete(String statement, Object parameter) {
+        return this.sqlSessionProxy.delete(statement, parameter);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public <T> T getMapper(Class<T> type) {
+        return getConfiguration().getMapper(type, this);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public void commit() {
+        throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public void commit(boolean force) {
+        throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public void rollback() {
+        throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public void rollback(boolean force) {
+        throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public void close() {
+        throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public void clearCache() {
+        this.sqlSessionProxy.clearCache();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public Configuration getConfiguration() {
+        return this.sqlSessionFactory.getConfiguration();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+
+    public Connection getConnection() {
+        return this.sqlSessionProxy.getConnection();
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 1.0.2
+     */
+
+    public List<BatchResult> flushStatements() {
+        return this.sqlSessionProxy.flushStatements();
+    }
+
+    /**
+     * Allow gently dispose bean:
+     * <p>
+     *
+     * <pre>
+     * {@code
+     *
+     * <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
+     *  <constructor-arg index="0" ref="sqlSessionFactory" />
+     * </bean>
+     * }
+     * </pre>
+     * <p>
+     * The implementation of {@link DisposableBean} forces spring context to use
+     * {@link DisposableBean#destroy()} method instead of
+     * {@link MybatisSqlSessionTemplate#close()} to shutdown gently.
+     *
+     * @see MybatisSqlSessionTemplate#close()
+     * @see org.springframework.beans.factory.support.DisposableBeanAdapter#inferDestroyMethodIfNecessary
+     * @see org.springframework.beans.factory.support.DisposableBeanAdapter#CLOSE_METHOD_NAME
+     */
+
+    public void destroy() throws Exception {
+        // This method forces spring disposer to avoid call of
+        // SqlSessionTemplate.close() which gives UnsupportedOperationException
+    }
+
+    /**
+     * Proxy needed to route MyBatis method calls to the proper SqlSession got
+     * from Spring's Transaction Manager It also unwraps exceptions thrown by
+     * {@code Method#invoke(Object, Object...)} to pass a
+     * {@code PersistenceException} to the
+     * {@code PersistenceExceptionTranslator}.
+     */
+    private class SqlSessionInterceptor implements InvocationHandler {
+
+        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+            SqlSession sqlSession = MybatisSqlSessionTemplate.this.sqlSessionFactory
+                    .openSession(MybatisSqlSessionTemplate.this.executorType);
+            try {
+                Object result = method.invoke(sqlSession, args);
+                sqlSession.commit(true);
+                return result;
+            } catch (Throwable t) {
+                throw new MybatisPlusException(t);
+            } finally {
+                if (sqlSession != null) {
+                    sqlSession.close();
+                }
+            }
+        }
+    }
 }

+ 12 - 13
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisXMLConfigBuilder.java

@@ -15,6 +15,14 @@
  */
 package com.baomidou.mybatisplus;
 
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.sql.DataSource;
+
 import org.apache.ibatis.builder.BaseBuilder;
 import org.apache.ibatis.builder.BuilderException;
 import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
@@ -43,13 +51,6 @@ import org.apache.ibatis.session.LocalCacheScope;
 import org.apache.ibatis.transaction.TransactionFactory;
 import org.apache.ibatis.type.JdbcType;
 
-import javax.sql.DataSource;
-import java.io.InputStream;
-import java.io.Reader;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-
 /**
  * <p>
  * Copy from XMLConfigBuilder in Mybatis and replace default Configuration class
@@ -153,7 +154,7 @@ public class MybatisXMLConfigBuilder extends BaseBuilder {
             for (String clazz : clazzes) {
                 if (!clazz.isEmpty()) {
                     @SuppressWarnings("unchecked")
-                    Class<? extends VFS> vfsImpl = (Class<? extends VFS>)Resources.classForName(clazz);
+                    Class<? extends VFS> vfsImpl = (Class<? extends VFS>) Resources.classForName(clazz);
                     configuration.setVfsImpl(vfsImpl);
                 }
             }
@@ -269,7 +270,7 @@ public class MybatisXMLConfigBuilder extends BaseBuilder {
         configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
         configuration.setLogPrefix(props.getProperty("logPrefix"));
         @SuppressWarnings("unchecked")
-        Class<? extends Log> logImpl = (Class<? extends Log>)resolveClass(props.getProperty("logImpl"));
+        Class<? extends Log> logImpl = (Class<? extends Log>) resolveClass(props.getProperty("logImpl"));
         configuration.setLogImpl(logImpl);
         configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
     }
@@ -391,7 +392,7 @@ public class MybatisXMLConfigBuilder extends BaseBuilder {
     /**
      * 查找mybatis配置文件填充至Set集合
      *
-     * @param parent 节点
+     * @param parent    节点
      * @param resources
      * @param mapper
      * @throws ClassNotFoundException
@@ -403,9 +404,7 @@ public class MybatisXMLConfigBuilder extends BaseBuilder {
                 ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
                 resolverUtil.find(new ResolverUtil.IsA(Object.class), mapperPackage);
                 Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
-                for (Class<?> mapperClass : mapperSet) {
-                    mapper.add(mapperClass);
-                }
+                mapper.addAll(mapperSet);
             } else {
                 String resource = child.getStringAttribute("resource");
                 String url = child.getStringAttribute("url");

+ 10 - 10
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisXMLLanguageDriver.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
@@ -24,16 +24,16 @@ import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
  * <p>
  * 继承 XMLLanguageDriver 重装构造函数,使用自定义 ParameterHandler
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-03-11
  */
 public class MybatisXMLLanguageDriver extends XMLLanguageDriver {
 
-	@Override
-	public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject,
-			BoundSql boundSql) {
-		/* 使用自定义 ParameterHandler */
-		return new MybatisDefaultParameterHandler(mappedStatement, parameterObject, boundSql);
-	}
+    @Override
+    public ParameterHandler createParameterHandler(MappedStatement mappedStatement, Object parameterObject,
+                                                   BoundSql boundSql) {
+        /* 使用自定义 ParameterHandler */
+        return new MybatisDefaultParameterHandler(mappedStatement, parameterObject, boundSql);
+    }
 }

+ 383 - 383
mybatis-plus/src/main/java/com/baomidou/mybatisplus/MybatisXMLMapperBuilder.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
@@ -60,390 +60,390 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * <p>
  * injector curdSql
  * </p>
- * 
+ *
  * @author Clinton Begin hubin
  * @Date 2016-06-13
  */
 public class MybatisXMLMapperBuilder extends BaseBuilder {
 
-	private XPathParser parser;
-	private MapperBuilderAssistant builderAssistant;
-	private Map<String, XNode> sqlFragments;
-	private String resource;
-
-	@Deprecated
-	public MybatisXMLMapperBuilder(Reader reader, Configuration configuration, String resource,
-								   Map<String, XNode> sqlFragments, String namespace) {
-		this(reader, configuration, resource, sqlFragments);
-		this.builderAssistant.setCurrentNamespace(namespace);
-	}
-
-	@Deprecated
-	public MybatisXMLMapperBuilder(Reader reader, Configuration configuration, String resource,
-			Map<String, XNode> sqlFragments) {
-		this(new XPathParser(reader, true, configuration.getVariables(), new XMLMapperEntityResolver()), configuration,
-				resource, sqlFragments);
-	}
-
-	public MybatisXMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource,
-			Map<String, XNode> sqlFragments, String namespace) {
-		this(inputStream, configuration, resource, sqlFragments);
-		this.builderAssistant.setCurrentNamespace(namespace);
-	}
-
-	public MybatisXMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource,
-			Map<String, XNode> sqlFragments) {
-		this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()),
-				configuration, resource, sqlFragments);
-	}
-
-	private MybatisXMLMapperBuilder(XPathParser parser, Configuration configuration, String resource,
-			Map<String, XNode> sqlFragments) {
-		super(configuration);
-		this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
-		this.parser = parser;
-		this.sqlFragments = sqlFragments;
-		this.resource = resource;
-	}
-
-	public void parse() {
-		if (!configuration.isResourceLoaded(resource)) {
-			configurationElement(parser.evalNode("/mapper"));
-			configuration.addLoadedResource(resource);
-			bindMapperForNamespace();
-		}
-		parsePendingResultMaps();
-		parsePendingChacheRefs();
-		parsePendingStatements();
-	}
-
-	public XNode getSqlFragment(String refid) {
-		return sqlFragments.get(refid);
-	}
-
-	private void configurationElement(XNode context) {
-		try {
-			String namespace = context.getStringAttribute("namespace");
-			if (StringUtils.isEmpty(namespace)) {
-				throw new BuilderException("Mapper's namespace cannot be empty");
-			}
-			builderAssistant.setCurrentNamespace(namespace);
-			cacheRefElement(context.evalNode("cache-ref"));
-			cacheElement(context.evalNode("cache"));
-			parameterMapElement(context.evalNodes("/mapper/parameterMap"));
-			resultMapElements(context.evalNodes("/mapper/resultMap"));
-			sqlElement(context.evalNodes("/mapper/sql"));
-			buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
-		} catch (Exception e) {
-			throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
-		}
-	}
-
-	private void buildStatementFromContext(List<XNode> list) {
-		if (configuration.getDatabaseId() != null) {
-			buildStatementFromContext(list, configuration.getDatabaseId());
-		}
-		buildStatementFromContext(list, null);
-	}
-
-	private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
-		for (XNode context : list) {
-			final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant,
-					context, requiredDatabaseId);
-			try {
-				statementParser.parseStatementNode();
-			} catch (IncompleteElementException e) {
-				configuration.addIncompleteStatement(statementParser);
-			}
-		}
-	}
-
-	private void parsePendingResultMaps() {
-		Collection<ResultMapResolver> incompleteResultMaps = configuration.getIncompleteResultMaps();
-		synchronized (incompleteResultMaps) {
-			Iterator<ResultMapResolver> iter = incompleteResultMaps.iterator();
-			while (iter.hasNext()) {
-				try {
-					iter.next().resolve();
-					iter.remove();
-				} catch (IncompleteElementException e) {
-					// ResultMap is still missing a resource...
-				}
-			}
-		}
-	}
-
-	private void parsePendingChacheRefs() {
-		Collection<CacheRefResolver> incompleteCacheRefs = configuration.getIncompleteCacheRefs();
-		synchronized (incompleteCacheRefs) {
-			Iterator<CacheRefResolver> iter = incompleteCacheRefs.iterator();
-			while (iter.hasNext()) {
-				try {
-					iter.next().resolveCacheRef();
-					iter.remove();
-				} catch (IncompleteElementException e) {
-					// Cache ref is still missing a resource...
-				}
-			}
-		}
-	}
-
-	private void parsePendingStatements() {
-		Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();
-		synchronized (incompleteStatements) {
-			Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();
-			while (iter.hasNext()) {
-				try {
-					iter.next().parseStatementNode();
-					iter.remove();
-				} catch (IncompleteElementException e) {
-					// Statement is still missing a resource...
-				}
-			}
-		}
-	}
-
-	private void cacheRefElement(XNode context) {
-		if (context != null) {
-			configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
-			CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant,
-					context.getStringAttribute("namespace"));
-			try {
-				cacheRefResolver.resolveCacheRef();
-			} catch (IncompleteElementException e) {
-				configuration.addIncompleteCacheRef(cacheRefResolver);
-			}
-		}
-	}
-
-	private void cacheElement(XNode context) throws Exception {
-		if (context != null) {
-			String type = context.getStringAttribute("type", "PERPETUAL");
-			Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
-			String eviction = context.getStringAttribute("eviction", "LRU");
-			Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
-			Long flushInterval = context.getLongAttribute("flushInterval");
-			Integer size = context.getIntAttribute("size");
-			boolean readWrite = !context.getBooleanAttribute("readOnly", false);
-			boolean blocking = context.getBooleanAttribute("blocking", false);
-			Properties props = context.getChildrenAsProperties();
-			builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
-		}
-	}
-
-	private void parameterMapElement(List<XNode> list) throws Exception {
-		for (XNode parameterMapNode : list) {
-			String id = parameterMapNode.getStringAttribute("id");
-			String type = parameterMapNode.getStringAttribute("type");
-			Class<?> parameterClass = resolveClass(type);
-			List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
-			List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
-			for (XNode parameterNode : parameterNodes) {
-				String property = parameterNode.getStringAttribute("property");
-				String javaType = parameterNode.getStringAttribute("javaType");
-				String jdbcType = parameterNode.getStringAttribute("jdbcType");
-				String resultMap = parameterNode.getStringAttribute("resultMap");
-				String mode = parameterNode.getStringAttribute("mode");
-				String typeHandler = parameterNode.getStringAttribute("typeHandler");
-				Integer numericScale = parameterNode.getIntAttribute("numericScale");
-				ParameterMode modeEnum = resolveParameterMode(mode);
-				Class<?> javaTypeClass = resolveClass(javaType);
-				JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
-				@SuppressWarnings("unchecked")
-				Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(
-						typeHandler);
-				ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property,
-						javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
-				parameterMappings.add(parameterMapping);
-			}
-			builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
-		}
-	}
-
-	private void resultMapElements(List<XNode> list) throws Exception {
-		for (XNode resultMapNode : list) {
-			try {
-				resultMapElement(resultMapNode);
-			} catch (IncompleteElementException e) {
-				// ignore, it will be retried
-			}
-		}
-	}
-
-	private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
-		return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList());
-	}
-
-	private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings)
-			throws Exception {
-		ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
-		String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
-		String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType",
-				resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType"))));
-		String extend = resultMapNode.getStringAttribute("extends");
-		Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
-		Class<?> typeClass = resolveClass(type);
-		Discriminator discriminator = null;
-		List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
-		resultMappings.addAll(additionalResultMappings);
-		List<XNode> resultChildren = resultMapNode.getChildren();
-		for (XNode resultChild : resultChildren) {
-			if ("constructor".equals(resultChild.getName())) {
-				processConstructorElement(resultChild, typeClass, resultMappings);
-			} else if ("discriminator".equals(resultChild.getName())) {
-				discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
-			} else {
-				List<ResultFlag> flags = new ArrayList<ResultFlag>();
-				if ("id".equals(resultChild.getName())) {
-					flags.add(ResultFlag.ID);
-				}
-				resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
-			}
-		}
-		ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend,
-				discriminator, resultMappings, autoMapping);
-		try {
-			return resultMapResolver.resolve();
-		} catch (IncompleteElementException e) {
-			configuration.addIncompleteResultMap(resultMapResolver);
-			throw e;
-		}
-	}
-
-	private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings)
-			throws Exception {
-		List<XNode> argChildren = resultChild.getChildren();
-		for (XNode argChild : argChildren) {
-			List<ResultFlag> flags = new ArrayList<ResultFlag>();
-			flags.add(ResultFlag.CONSTRUCTOR);
-			if ("idArg".equals(argChild.getName())) {
-				flags.add(ResultFlag.ID);
-			}
-			resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
-		}
-	}
-
-	private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType,
-			List<ResultMapping> resultMappings) throws Exception {
-		String column = context.getStringAttribute("column");
-		String javaType = context.getStringAttribute("javaType");
-		String jdbcType = context.getStringAttribute("jdbcType");
-		String typeHandler = context.getStringAttribute("typeHandler");
-		Class<?> javaTypeClass = resolveClass(javaType);
-		@SuppressWarnings("unchecked")
-		Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
-		JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
-		Map<String, String> discriminatorMap = new HashMap<String, String>();
-		for (XNode caseChild : context.getChildren()) {
-			String value = caseChild.getStringAttribute("value");
-			String resultMap = caseChild.getStringAttribute("resultMap",
-					processNestedResultMappings(caseChild, resultMappings));
-			discriminatorMap.put(value, resultMap);
-		}
-		return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass,
-				discriminatorMap);
-	}
-
-	private void sqlElement(List<XNode> list) throws Exception {
-		if (configuration.getDatabaseId() != null) {
-			sqlElement(list, configuration.getDatabaseId());
-		}
-		sqlElement(list, null);
-	}
-
-	private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {
-		for (XNode context : list) {
-			String databaseId = context.getStringAttribute("databaseId");
-			String id = context.getStringAttribute("id");
-			id = builderAssistant.applyCurrentNamespace(id, false);
-			if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
-				sqlFragments.put(id, context);
-			}
-		}
-	}
-
-	private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {
-		if (requiredDatabaseId != null) {
-			if (!requiredDatabaseId.equals(databaseId)) {
-				return false;
-			}
-		} else {
-			if (databaseId != null) {
-				return false;
-			}
-			// skip this fragment if there is a previous one with a not null
-			// databaseId
-			if (this.sqlFragments.containsKey(id)) {
-				XNode context = this.sqlFragments.get(id);
-				if (context.getStringAttribute("databaseId") != null) {
-					return false;
-				}
-			}
-		}
-		return true;
-	}
-
-	private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags)
-			throws Exception {
-		String property = context.getStringAttribute("property");
-		String column = context.getStringAttribute("column");
-		String javaType = context.getStringAttribute("javaType");
-		String jdbcType = context.getStringAttribute("jdbcType");
-		String nestedSelect = context.getStringAttribute("select");
-		String nestedResultMap = context.getStringAttribute("resultMap",
-				processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));
-		String notNullColumn = context.getStringAttribute("notNullColumn");
-		String columnPrefix = context.getStringAttribute("columnPrefix");
-		String typeHandler = context.getStringAttribute("typeHandler");
-		String resultSet = context.getStringAttribute("resultSet");
-		String foreignColumn = context.getStringAttribute("foreignColumn");
-		boolean lazy = "lazy".equals(
-				context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
-		Class<?> javaTypeClass = resolveClass(javaType);
-		@SuppressWarnings("unchecked")
-		Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
-		JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
-		return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum,
-				nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet,
-				foreignColumn, lazy);
-	}
-
-	private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings) throws Exception {
-		if ("association".equals(context.getName()) || "collection".equals(context.getName())
-				|| "case".equals(context.getName())) {
-			if (context.getStringAttribute("select") == null) {
-				ResultMap resultMap = resultMapElement(context, resultMappings);
-				return resultMap.getId();
-			}
-		}
-		return null;
-	}
-
-	private void bindMapperForNamespace() {
-		String namespace = builderAssistant.getCurrentNamespace();
-		if (namespace != null) {
-			Class<?> boundType = null;
-			try {
-				boundType = Resources.classForName(namespace);
-			} catch (ClassNotFoundException e) {
-				// ignore, bound type is not required
-			}
-			if (boundType != null) {
-				if (!configuration.hasMapper(boundType)) {
-					// Spring may not know the real resource name so we set a
-					// flag
-					// to prevent loading again this resource from the mapper
-					// interface
-					// look at MapperAnnotationBuilder#loadXmlResource
-					configuration.addLoadedResource("namespace:" + namespace);
-					configuration.addMapper(boundType);
-				}
-				//TODO 注入 CURD 动态 SQL
-				if (BaseMapper.class.isAssignableFrom(boundType)) {
-					GlobalConfiguration.getSqlInjector(configuration).inspectInject(builderAssistant, boundType);
-				}
-			}
-		}
-	}
+    private XPathParser parser;
+    private MapperBuilderAssistant builderAssistant;
+    private Map<String, XNode> sqlFragments;
+    private String resource;
+
+    @Deprecated
+    public MybatisXMLMapperBuilder(Reader reader, Configuration configuration, String resource,
+                                   Map<String, XNode> sqlFragments, String namespace) {
+        this(reader, configuration, resource, sqlFragments);
+        this.builderAssistant.setCurrentNamespace(namespace);
+    }
+
+    @Deprecated
+    public MybatisXMLMapperBuilder(Reader reader, Configuration configuration, String resource,
+                                   Map<String, XNode> sqlFragments) {
+        this(new XPathParser(reader, true, configuration.getVariables(), new XMLMapperEntityResolver()), configuration,
+                resource, sqlFragments);
+    }
+
+    public MybatisXMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource,
+                                   Map<String, XNode> sqlFragments, String namespace) {
+        this(inputStream, configuration, resource, sqlFragments);
+        this.builderAssistant.setCurrentNamespace(namespace);
+    }
+
+    public MybatisXMLMapperBuilder(InputStream inputStream, Configuration configuration, String resource,
+                                   Map<String, XNode> sqlFragments) {
+        this(new XPathParser(inputStream, true, configuration.getVariables(), new XMLMapperEntityResolver()),
+                configuration, resource, sqlFragments);
+    }
+
+    private MybatisXMLMapperBuilder(XPathParser parser, Configuration configuration, String resource,
+                                    Map<String, XNode> sqlFragments) {
+        super(configuration);
+        this.builderAssistant = new MapperBuilderAssistant(configuration, resource);
+        this.parser = parser;
+        this.sqlFragments = sqlFragments;
+        this.resource = resource;
+    }
+
+    public void parse() {
+        if (!configuration.isResourceLoaded(resource)) {
+            configurationElement(parser.evalNode("/mapper"));
+            configuration.addLoadedResource(resource);
+            bindMapperForNamespace();
+        }
+        parsePendingResultMaps();
+        parsePendingChacheRefs();
+        parsePendingStatements();
+    }
+
+    public XNode getSqlFragment(String refid) {
+        return sqlFragments.get(refid);
+    }
+
+    private void configurationElement(XNode context) {
+        try {
+            String namespace = context.getStringAttribute("namespace");
+            if (StringUtils.isEmpty(namespace)) {
+                throw new BuilderException("Mapper's namespace cannot be empty");
+            }
+            builderAssistant.setCurrentNamespace(namespace);
+            cacheRefElement(context.evalNode("cache-ref"));
+            cacheElement(context.evalNode("cache"));
+            parameterMapElement(context.evalNodes("/mapper/parameterMap"));
+            resultMapElements(context.evalNodes("/mapper/resultMap"));
+            sqlElement(context.evalNodes("/mapper/sql"));
+            buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
+        } catch (Exception e) {
+            throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
+        }
+    }
+
+    private void buildStatementFromContext(List<XNode> list) {
+        if (configuration.getDatabaseId() != null) {
+            buildStatementFromContext(list, configuration.getDatabaseId());
+        }
+        buildStatementFromContext(list, null);
+    }
+
+    private void buildStatementFromContext(List<XNode> list, String requiredDatabaseId) {
+        for (XNode context : list) {
+            final XMLStatementBuilder statementParser = new XMLStatementBuilder(configuration, builderAssistant,
+                    context, requiredDatabaseId);
+            try {
+                statementParser.parseStatementNode();
+            } catch (IncompleteElementException e) {
+                configuration.addIncompleteStatement(statementParser);
+            }
+        }
+    }
+
+    private void parsePendingResultMaps() {
+        Collection<ResultMapResolver> incompleteResultMaps = configuration.getIncompleteResultMaps();
+        synchronized (incompleteResultMaps) {
+            Iterator<ResultMapResolver> iter = incompleteResultMaps.iterator();
+            while (iter.hasNext()) {
+                try {
+                    iter.next().resolve();
+                    iter.remove();
+                } catch (IncompleteElementException e) {
+                    // ResultMap is still missing a resource...
+                }
+            }
+        }
+    }
+
+    private void parsePendingChacheRefs() {
+        Collection<CacheRefResolver> incompleteCacheRefs = configuration.getIncompleteCacheRefs();
+        synchronized (incompleteCacheRefs) {
+            Iterator<CacheRefResolver> iter = incompleteCacheRefs.iterator();
+            while (iter.hasNext()) {
+                try {
+                    iter.next().resolveCacheRef();
+                    iter.remove();
+                } catch (IncompleteElementException e) {
+                    // Cache ref is still missing a resource...
+                }
+            }
+        }
+    }
+
+    private void parsePendingStatements() {
+        Collection<XMLStatementBuilder> incompleteStatements = configuration.getIncompleteStatements();
+        synchronized (incompleteStatements) {
+            Iterator<XMLStatementBuilder> iter = incompleteStatements.iterator();
+            while (iter.hasNext()) {
+                try {
+                    iter.next().parseStatementNode();
+                    iter.remove();
+                } catch (IncompleteElementException e) {
+                    // Statement is still missing a resource...
+                }
+            }
+        }
+    }
+
+    private void cacheRefElement(XNode context) {
+        if (context != null) {
+            configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
+            CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant,
+                    context.getStringAttribute("namespace"));
+            try {
+                cacheRefResolver.resolveCacheRef();
+            } catch (IncompleteElementException e) {
+                configuration.addIncompleteCacheRef(cacheRefResolver);
+            }
+        }
+    }
+
+    private void cacheElement(XNode context) throws Exception {
+        if (context != null) {
+            String type = context.getStringAttribute("type", "PERPETUAL");
+            Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
+            String eviction = context.getStringAttribute("eviction", "LRU");
+            Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
+            Long flushInterval = context.getLongAttribute("flushInterval");
+            Integer size = context.getIntAttribute("size");
+            boolean readWrite = !context.getBooleanAttribute("readOnly", false);
+            boolean blocking = context.getBooleanAttribute("blocking", false);
+            Properties props = context.getChildrenAsProperties();
+            builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
+        }
+    }
+
+    private void parameterMapElement(List<XNode> list) throws Exception {
+        for (XNode parameterMapNode : list) {
+            String id = parameterMapNode.getStringAttribute("id");
+            String type = parameterMapNode.getStringAttribute("type");
+            Class<?> parameterClass = resolveClass(type);
+            List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
+            List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
+            for (XNode parameterNode : parameterNodes) {
+                String property = parameterNode.getStringAttribute("property");
+                String javaType = parameterNode.getStringAttribute("javaType");
+                String jdbcType = parameterNode.getStringAttribute("jdbcType");
+                String resultMap = parameterNode.getStringAttribute("resultMap");
+                String mode = parameterNode.getStringAttribute("mode");
+                String typeHandler = parameterNode.getStringAttribute("typeHandler");
+                Integer numericScale = parameterNode.getIntAttribute("numericScale");
+                ParameterMode modeEnum = resolveParameterMode(mode);
+                Class<?> javaTypeClass = resolveClass(javaType);
+                JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
+                @SuppressWarnings("unchecked")
+                Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(
+                        typeHandler);
+                ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property,
+                        javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
+                parameterMappings.add(parameterMapping);
+            }
+            builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
+        }
+    }
+
+    private void resultMapElements(List<XNode> list) throws Exception {
+        for (XNode resultMapNode : list) {
+            try {
+                resultMapElement(resultMapNode);
+            } catch (IncompleteElementException e) {
+                // ignore, it will be retried
+            }
+        }
+    }
+
+    private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
+        return resultMapElement(resultMapNode, Collections.<ResultMapping>emptyList());
+    }
+
+    private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings)
+            throws Exception {
+        ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
+        String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
+        String type = resultMapNode.getStringAttribute("type", resultMapNode.getStringAttribute("ofType",
+                resultMapNode.getStringAttribute("resultType", resultMapNode.getStringAttribute("javaType"))));
+        String extend = resultMapNode.getStringAttribute("extends");
+        Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
+        Class<?> typeClass = resolveClass(type);
+        Discriminator discriminator = null;
+        List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
+        resultMappings.addAll(additionalResultMappings);
+        List<XNode> resultChildren = resultMapNode.getChildren();
+        for (XNode resultChild : resultChildren) {
+            if ("constructor".equals(resultChild.getName())) {
+                processConstructorElement(resultChild, typeClass, resultMappings);
+            } else if ("discriminator".equals(resultChild.getName())) {
+                discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
+            } else {
+                List<ResultFlag> flags = new ArrayList<ResultFlag>();
+                if ("id".equals(resultChild.getName())) {
+                    flags.add(ResultFlag.ID);
+                }
+                resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
+            }
+        }
+        ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend,
+                discriminator, resultMappings, autoMapping);
+        try {
+            return resultMapResolver.resolve();
+        } catch (IncompleteElementException e) {
+            configuration.addIncompleteResultMap(resultMapResolver);
+            throw e;
+        }
+    }
+
+    private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings)
+            throws Exception {
+        List<XNode> argChildren = resultChild.getChildren();
+        for (XNode argChild : argChildren) {
+            List<ResultFlag> flags = new ArrayList<ResultFlag>();
+            flags.add(ResultFlag.CONSTRUCTOR);
+            if ("idArg".equals(argChild.getName())) {
+                flags.add(ResultFlag.ID);
+            }
+            resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
+        }
+    }
+
+    private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType,
+                                                      List<ResultMapping> resultMappings) throws Exception {
+        String column = context.getStringAttribute("column");
+        String javaType = context.getStringAttribute("javaType");
+        String jdbcType = context.getStringAttribute("jdbcType");
+        String typeHandler = context.getStringAttribute("typeHandler");
+        Class<?> javaTypeClass = resolveClass(javaType);
+        @SuppressWarnings("unchecked")
+        Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
+        JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
+        Map<String, String> discriminatorMap = new HashMap<String, String>();
+        for (XNode caseChild : context.getChildren()) {
+            String value = caseChild.getStringAttribute("value");
+            String resultMap = caseChild.getStringAttribute("resultMap",
+                    processNestedResultMappings(caseChild, resultMappings));
+            discriminatorMap.put(value, resultMap);
+        }
+        return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass,
+                discriminatorMap);
+    }
+
+    private void sqlElement(List<XNode> list) throws Exception {
+        if (configuration.getDatabaseId() != null) {
+            sqlElement(list, configuration.getDatabaseId());
+        }
+        sqlElement(list, null);
+    }
+
+    private void sqlElement(List<XNode> list, String requiredDatabaseId) throws Exception {
+        for (XNode context : list) {
+            String databaseId = context.getStringAttribute("databaseId");
+            String id = context.getStringAttribute("id");
+            id = builderAssistant.applyCurrentNamespace(id, false);
+            if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
+                sqlFragments.put(id, context);
+            }
+        }
+    }
+
+    private boolean databaseIdMatchesCurrent(String id, String databaseId, String requiredDatabaseId) {
+        if (requiredDatabaseId != null) {
+            if (!requiredDatabaseId.equals(databaseId)) {
+                return false;
+            }
+        } else {
+            if (databaseId != null) {
+                return false;
+            }
+            // skip this fragment if there is a previous one with a not null
+            // databaseId
+            if (this.sqlFragments.containsKey(id)) {
+                XNode context = this.sqlFragments.get(id);
+                if (context.getStringAttribute("databaseId") != null) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags)
+            throws Exception {
+        String property = context.getStringAttribute("property");
+        String column = context.getStringAttribute("column");
+        String javaType = context.getStringAttribute("javaType");
+        String jdbcType = context.getStringAttribute("jdbcType");
+        String nestedSelect = context.getStringAttribute("select");
+        String nestedResultMap = context.getStringAttribute("resultMap",
+                processNestedResultMappings(context, Collections.<ResultMapping>emptyList()));
+        String notNullColumn = context.getStringAttribute("notNullColumn");
+        String columnPrefix = context.getStringAttribute("columnPrefix");
+        String typeHandler = context.getStringAttribute("typeHandler");
+        String resultSet = context.getStringAttribute("resultSet");
+        String foreignColumn = context.getStringAttribute("foreignColumn");
+        boolean lazy = "lazy".equals(
+                context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
+        Class<?> javaTypeClass = resolveClass(javaType);
+        @SuppressWarnings("unchecked")
+        Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
+        JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
+        return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum,
+                nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet,
+                foreignColumn, lazy);
+    }
+
+    private String processNestedResultMappings(XNode context, List<ResultMapping> resultMappings) throws Exception {
+        if ("association".equals(context.getName()) || "collection".equals(context.getName())
+                || "case".equals(context.getName())) {
+            if (context.getStringAttribute("select") == null) {
+                ResultMap resultMap = resultMapElement(context, resultMappings);
+                return resultMap.getId();
+            }
+        }
+        return null;
+    }
+
+    private void bindMapperForNamespace() {
+        String namespace = builderAssistant.getCurrentNamespace();
+        if (namespace != null) {
+            Class<?> boundType = null;
+            try {
+                boundType = Resources.classForName(namespace);
+            } catch (ClassNotFoundException e) {
+                // ignore, bound type is not required
+            }
+            if (boundType != null) {
+                if (!configuration.hasMapper(boundType)) {
+                    // Spring may not know the real resource name so we set a
+                    // flag
+                    // to prevent loading again this resource from the mapper
+                    // interface
+                    // look at MapperAnnotationBuilder#loadXmlResource
+                    configuration.addLoadedResource("namespace:" + namespace);
+                    configuration.addMapper(boundType);
+                }
+                //TODO 注入 CURD 动态 SQL
+                if (BaseMapper.class.isAssignableFrom(boundType)) {
+                    GlobalConfiguration.getSqlInjector(configuration).inspectInject(builderAssistant, boundType);
+                }
+            }
+        }
+    }
 
 }

+ 337 - 336
mybatis-plus/src/main/java/com/baomidou/mybatisplus/activerecord/Model.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,6 +15,13 @@
  */
 package com.baomidou.mybatisplus.activerecord;
 
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.ibatis.session.SqlSession;
+
 import com.baomidou.mybatisplus.enums.SqlMethod;
 import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.mapper.Condition;
@@ -23,12 +30,6 @@ import com.baomidou.mybatisplus.mapper.SqlRunner;
 import com.baomidou.mybatisplus.mapper.Wrapper;
 import com.baomidou.mybatisplus.plugins.Page;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
-import org.apache.ibatis.session.SqlSession;
-
-import java.io.Serializable;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 
 /**
  * <p>
@@ -39,336 +40,336 @@ import java.util.Map;
  * @param <T>
  * @Date 2016-11-06
  */
-@SuppressWarnings({ "rawtypes" })
+@SuppressWarnings({"rawtypes"})
 public abstract class Model<T extends Model> implements Serializable {
 
-	private static final long serialVersionUID = 1L;
-
-	/**
-	 * <p>
-	 * 插入
-	 * </p>
-	 */
-	public boolean insert() {
-		return SqlHelper.retBool(sqlSession().insert(sqlStatement(SqlMethod.INSERT_ONE), this));
-	}
-
-	/**
-	 * <p>
-	 * 插入 OR 更新
-	 * </p>
-	 */
-	public boolean insertOrUpdate() {
-		if (StringUtils.checkValNull(pkVal())) {
-			// insert
-			return insert();
-		} else {
-			/*
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * <p>
+     * 插入
+     * </p>
+     */
+    public boolean insert() {
+        return SqlHelper.retBool(sqlSession().insert(sqlStatement(SqlMethod.INSERT_ONE), this));
+    }
+
+    /**
+     * <p>
+     * 插入 OR 更新
+     * </p>
+     */
+    public boolean insertOrUpdate() {
+        if (StringUtils.checkValNull(pkVal())) {
+            // insert
+            return insert();
+        } else {
+            /*
 			 * 更新成功直接返回,失败执行插入逻辑
 			 */
-			return updateById() || insert();
-		}
-	}
-
-	/**
-	 * <p>
-	 * 根据 ID 删除
-	 * </p>
-	 *
-	 * @param id
-	 *            主键ID
-	 * @return
-	 */
-	public boolean deleteById(Serializable id) {
-		return SqlHelper.retBool(sqlSession().delete(sqlStatement(SqlMethod.DELETE_BY_ID), id));
-	}
-
-	/**
-	 * <p>
-	 * 根据主键删除
-	 * </p>
-	 *
-	 * @return
-	 */
-	public boolean deleteById() {
-		if (StringUtils.checkValNull(pkVal())) {
-			throw new MybatisPlusException("deleteById primaryKey is null.");
-		}
-		return deleteById(this.pkVal());
-	}
-
-	/**
-	 * <p>
-	 * 删除记录
-	 * </p>
-	 *
-	 * @param whereClause
-	 *            查询条件
-	 * @param args
-	 *            查询条件值
-	 * @return
-	 */
-	public boolean delete(String whereClause, Object... args) {
-		return delete(Condition.instance().where(whereClause, args));
-	}
-
-	/**
-	 * <p>
-	 * 删除记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 * @return
-	 */
-	public boolean delete(Wrapper wrapper) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		// delete
-		map.put("ew", wrapper);
-		return SqlHelper.retBool(sqlSession().delete(sqlStatement(SqlMethod.DELETE), map));
-	}
-
-	/**
-	 * <p>
-	 * 更新
-	 * </p>
-	 *
-	 * @return
-	 */
-	public boolean updateById() {
-		if (StringUtils.checkValNull(pkVal())) {
-			throw new MybatisPlusException("updateById primaryKey is null.");
-		}
-		// updateById
-		return SqlHelper.retBool(sqlSession().update(sqlStatement(SqlMethod.UPDATE_BY_ID), this));
-	}
-
-	/**
-	 * <p>
-	 * 执行 SQL 更新
-	 * </p>
-	 *
-	 * @param whereClause
-	 *            查询条件
-	 * @param args
-	 *            查询条件值
-	 * @return
-	 */
-	public boolean update(String whereClause, Object... args) {
-		// update
-		return update(Condition.instance().where(whereClause, args));
-	}
-
-	/**
-	 * <p>
-	 * 执行 SQL 更新
-	 * </p>
-	 *
-	 * @param wrapper
-	 * @return
-	 */
-	public boolean update(Wrapper wrapper) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("et", this);
-		map.put("ew", wrapper);
-		// update
-		return SqlHelper.retBool(sqlSession().update(sqlStatement(SqlMethod.UPDATE), map));
-	}
-
-	/**
-	 * <p>
-	 * 查询所有
-	 * </p>
-	 *
-	 * @return
-	 */
-	public List<T> selectAll() {
-		return sqlSession().selectList(sqlStatement(SqlMethod.SELECT_LIST));
-	}
-
-	/**
-	 * <p>
-	 * 根据 ID 查询
-	 * </p>
-	 *
-	 * @param id
-	 *            主键ID
-	 * @return
-	 */
-	public T selectById(Serializable id) {
-		return sqlSession().selectOne(sqlStatement(SqlMethod.SELECT_BY_ID), id);
-	}
-
-	/**
-	 * <p>
-	 * 根据主键查询
-	 * </p>
-	 *
-	 * @return
-	 */
-	public T selectById() {
-		if (StringUtils.checkValNull(pkVal())) {
-			throw new MybatisPlusException("selectById primaryKey is null.");
-		}
-		return selectById(this.pkVal());
-	}
-
-	/**
-	 * <p>
-	 * 查询总记录数
-	 * </p>
-	 *
-	 * @param wrapper
-	 * @return
-	 */
-
-	public List<T> selectList(Wrapper wrapper) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("ew", wrapper);
-		return sqlSession().selectList(sqlStatement(SqlMethod.SELECT_LIST), map);
-	}
-
-	/**
-	 * <p>
-	 * 查询所有
-	 * </p>
-	 *
-	 * @param whereClause
-	 * @param args
-	 * @return
-	 */
-	public List<T> selectList(String whereClause, Object... args) {
-		return selectList(Condition.instance().where(whereClause, args));
-	}
-
-	/**
-	 * <p>
-	 * 查询一条记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 * @return
-	 */
-	public T selectOne(Wrapper wrapper) {
-		return SqlHelper.getObject(selectList(wrapper));
-	}
-
-	/**
-	 * <p>
-	 * 查询一条记录
-	 * </p>
-	 *
-	 * @param whereClause
-	 * @param args
-	 * @return
-	 */
-	public T selectOne(String whereClause, Object... args) {
-		return selectOne(Condition.instance().where(whereClause, args));
-	}
-
-	/**
-	 * <p>
-	 * 翻页查询
-	 * </p>
-	 *
-	 * @param page
-	 *            翻页查询条件
-	 * @param wrapper
-	 * @return
-	 */
-	public Page<T> selectPage(Page<T> page, Wrapper<T> wrapper) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		SqlHelper.fillWrapper(page, wrapper);
-		map.put("ew", wrapper);
-		List<T> tl = sqlSession().selectList(sqlStatement(SqlMethod.SELECT_PAGE), map, page);
-		page.setRecords(tl);
-		return page;
-	}
-
-	/**
-	 * <p>
-	 * 查询所有(分页)
-	 * </p>
-	 *
-	 * @param page
-	 * @param whereClause
-	 * @param args
-	 * @return
-	 */
-	@SuppressWarnings("unchecked")
-	public Page<T> selectPage(Page<T> page, String whereClause, Object... args) {
-		return selectPage(page, Condition.instance().where(whereClause, args));
-	}
-
-	/**
-	 * <p>
-	 * 查询总数
-	 * </p>
-	 *
-	 * @param whereClause
-	 *            查询条件
-	 * @param args
-	 *            查询条件值
-	 * @return
-	 */
-	public int selectCount(String whereClause, Object... args) {
-		return selectCount(Condition.instance().where(whereClause, args));
-	}
-
-	/**
-	 * <p>
-	 * 查询总数
-	 * </p>
-	 *
-	 * @param wrapper
-	 * @return
-	 */
-	public int selectCount(Wrapper wrapper) {
-		Map<String, Object> map = new HashMap<String, Object>();
-		map.put("ew", wrapper);
-		return SqlHelper.retCount(sqlSession().<Integer>selectOne(sqlStatement(SqlMethod.SELECT_COUNT), map));
-	}
-
-	/**
-	 * <p>
-	 * 执行 SQL
-	 * </p>
-	 */
-	public SqlRunner sql() {
-		return new SqlRunner(getClass());
-	}
-
-	/**
-	 * <p>
-	 * 获取Session 默认自动提交
-	 * <p/>
-	 */
-	protected SqlSession sqlSession() {
-		return SqlHelper.sqlSession(getClass());
-	}
-
-	/**
-	 * 获取SqlStatement
-	 *
-	 * @param sqlMethod
-	 * @return
-	 */
-	protected String sqlStatement(SqlMethod sqlMethod) {
-		return sqlStatement(sqlMethod.getMethod());
-	}
-
-	/**
-	 * 获取SqlStatement
-	 *
-	 * @param sqlMethod
-	 * @return
-	 */
-	protected String sqlStatement(String sqlMethod) {
-		return SqlHelper.table(getClass()).getSqlStatement(sqlMethod);
-	}
-
-	/**
-	 * 主键值
-	 */
-	protected abstract Serializable pkVal();
+            return updateById() || insert();
+        }
+    }
+
+    /**
+     * <p>
+     * 根据 ID 删除
+     * </p>
+     *
+     * @param id
+     *            主键ID
+     * @return
+     */
+    public boolean deleteById(Serializable id) {
+        return SqlHelper.retBool(sqlSession().delete(sqlStatement(SqlMethod.DELETE_BY_ID), id));
+    }
+
+    /**
+     * <p>
+     * 根据主键删除
+     * </p>
+     *
+     * @return
+     */
+    public boolean deleteById() {
+        if (StringUtils.checkValNull(pkVal())) {
+            throw new MybatisPlusException("deleteById primaryKey is null.");
+        }
+        return deleteById(this.pkVal());
+    }
+
+    /**
+     * <p>
+     * 删除记录
+     * </p>
+     *
+     * @param whereClause
+     *            查询条件
+     * @param args
+     *            查询条件值
+     * @return
+     */
+    public boolean delete(String whereClause, Object... args) {
+        return delete(Condition.instance().where(whereClause, args));
+    }
+
+    /**
+     * <p>
+     * 删除记录
+     * </p>
+     *
+     * @param wrapper
+     * @return
+     */
+    public boolean delete(Wrapper wrapper) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        // delete
+        map.put("ew", wrapper);
+        return SqlHelper.retBool(sqlSession().delete(sqlStatement(SqlMethod.DELETE), map));
+    }
+
+    /**
+     * <p>
+     * 更新
+     * </p>
+     *
+     * @return
+     */
+    public boolean updateById() {
+        if (StringUtils.checkValNull(pkVal())) {
+            throw new MybatisPlusException("updateById primaryKey is null.");
+        }
+        // updateById
+        return SqlHelper.retBool(sqlSession().update(sqlStatement(SqlMethod.UPDATE_BY_ID), this));
+    }
+
+    /**
+     * <p>
+     * 执行 SQL 更新
+     * </p>
+     *
+     * @param whereClause
+     *            查询条件
+     * @param args
+     *            查询条件值
+     * @return
+     */
+    public boolean update(String whereClause, Object... args) {
+        // update
+        return update(Condition.instance().where(whereClause, args));
+    }
+
+    /**
+     * <p>
+     * 执行 SQL 更新
+     * </p>
+     *
+     * @param wrapper
+     * @return
+     */
+    public boolean update(Wrapper wrapper) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("et", this);
+        map.put("ew", wrapper);
+        // update
+        return SqlHelper.retBool(sqlSession().update(sqlStatement(SqlMethod.UPDATE), map));
+    }
+
+    /**
+     * <p>
+     * 查询所有
+     * </p>
+     *
+     * @return
+     */
+    public List<T> selectAll() {
+        return sqlSession().selectList(sqlStatement(SqlMethod.SELECT_LIST));
+    }
+
+    /**
+     * <p>
+     * 根据 ID 查询
+     * </p>
+     *
+     * @param id
+     *            主键ID
+     * @return
+     */
+    public T selectById(Serializable id) {
+        return sqlSession().selectOne(sqlStatement(SqlMethod.SELECT_BY_ID), id);
+    }
+
+    /**
+     * <p>
+     * 根据主键查询
+     * </p>
+     *
+     * @return
+     */
+    public T selectById() {
+        if (StringUtils.checkValNull(pkVal())) {
+            throw new MybatisPlusException("selectById primaryKey is null.");
+        }
+        return selectById(this.pkVal());
+    }
+
+    /**
+     * <p>
+     * 查询总记录数
+     * </p>
+     *
+     * @param wrapper
+     * @return
+     */
+
+    public List<T> selectList(Wrapper wrapper) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("ew", wrapper);
+        return sqlSession().selectList(sqlStatement(SqlMethod.SELECT_LIST), map);
+    }
+
+    /**
+     * <p>
+     * 查询所有
+     * </p>
+     *
+     * @param whereClause
+     * @param args
+     * @return
+     */
+    public List<T> selectList(String whereClause, Object... args) {
+        return selectList(Condition.instance().where(whereClause, args));
+    }
+
+    /**
+     * <p>
+     * 查询一条记录
+     * </p>
+     *
+     * @param wrapper
+     * @return
+     */
+    public T selectOne(Wrapper wrapper) {
+        return SqlHelper.getObject(selectList(wrapper));
+    }
+
+    /**
+     * <p>
+     * 查询一条记录
+     * </p>
+     *
+     * @param whereClause
+     * @param args
+     * @return
+     */
+    public T selectOne(String whereClause, Object... args) {
+        return selectOne(Condition.instance().where(whereClause, args));
+    }
+
+    /**
+     * <p>
+     * 翻页查询
+     * </p>
+     *
+     * @param page
+     *            翻页查询条件
+     * @param wrapper
+     * @return
+     */
+    public Page<T> selectPage(Page<T> page, Wrapper<T> wrapper) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        SqlHelper.fillWrapper(page, wrapper);
+        map.put("ew", wrapper);
+        List<T> tl = sqlSession().selectList(sqlStatement(SqlMethod.SELECT_PAGE), map, page);
+        page.setRecords(tl);
+        return page;
+    }
+
+    /**
+     * <p>
+     * 查询所有(分页)
+     * </p>
+     *
+     * @param page
+     * @param whereClause
+     * @param args
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public Page<T> selectPage(Page<T> page, String whereClause, Object... args) {
+        return selectPage(page, Condition.instance().where(whereClause, args));
+    }
+
+    /**
+     * <p>
+     * 查询总数
+     * </p>
+     *
+     * @param whereClause
+     *            查询条件
+     * @param args
+     *            查询条件值
+     * @return
+     */
+    public int selectCount(String whereClause, Object... args) {
+        return selectCount(Condition.instance().where(whereClause, args));
+    }
+
+    /**
+     * <p>
+     * 查询总数
+     * </p>
+     *
+     * @param wrapper
+     * @return
+     */
+    public int selectCount(Wrapper wrapper) {
+        Map<String, Object> map = new HashMap<String, Object>();
+        map.put("ew", wrapper);
+        return SqlHelper.retCount(sqlSession().<Integer>selectOne(sqlStatement(SqlMethod.SELECT_COUNT), map));
+    }
+
+    /**
+     * <p>
+     * 执行 SQL
+     * </p>
+     */
+    public SqlRunner sql() {
+        return new SqlRunner(getClass());
+    }
+
+    /**
+     * <p>
+     * 获取Session 默认自动提交
+     * <p/>
+     */
+    protected SqlSession sqlSession() {
+        return SqlHelper.sqlSession(getClass());
+    }
+
+    /**
+     * 获取SqlStatement
+     *
+     * @param sqlMethod
+     * @return
+     */
+    protected String sqlStatement(SqlMethod sqlMethod) {
+        return sqlStatement(sqlMethod.getMethod());
+    }
+
+    /**
+     * 获取SqlStatement
+     *
+     * @param sqlMethod
+     * @return
+     */
+    protected String sqlStatement(String sqlMethod) {
+        return SqlHelper.table(getClass()).getSqlStatement(sqlMethod);
+    }
+
+    /**
+     * 主键值
+     */
+    protected abstract Serializable pkVal();
 
 }

+ 38 - 38
mybatis-plus/src/main/java/com/baomidou/mybatisplus/annotations/TableField.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
@@ -26,7 +26,7 @@ import com.baomidou.mybatisplus.enums.FieldStrategy;
  * <p>
  * 表字段标识
  * </p>
- * 
+ *
  * @author hubin sjy
  * @Date 2016-09-09
  */
@@ -34,42 +34,42 @@ import com.baomidou.mybatisplus.enums.FieldStrategy;
 @Target(ElementType.FIELD)
 public @interface TableField {
 
-	/**
-	 * <p>
-	 * 字段值(驼峰命名方式,该值可无)
-	 * </p>
-	 */
-	String value() default "";
+    /**
+     * <p>
+     * 字段值(驼峰命名方式,该值可无)
+     * </p>
+     */
+    String value() default "";
 
-	/**
-	 * <p>
-	 * 当该Field为类对象时, 可使用#{对象.属性}来映射到数据表.
-	 * </p>
-	 * <p>
-	 * 支持:@TableField(el = "role, jdbcType=BIGINT)<br>
-	 * 支持:@TableField(el = "role, typeHandler=com.baomidou.xx.typehandler.PhoneTypeHandler")
-	 * </p>
-	 */
-	String el() default "";
+    /**
+     * <p>
+     * 当该Field为类对象时, 可使用#{对象.属性}来映射到数据表.
+     * </p>
+     * <p>
+     * 支持:@TableField(el = "role, jdbcType=BIGINT)<br>
+     * 支持:@TableField(el = "role, typeHandler=com.baomidou.xx.typehandler.PhoneTypeHandler")
+     * </p>
+     */
+    String el() default "";
 
-	/**
-	 * <p>
-	 * 是否为数据库表字段
-	 * </p>
-	 * <p>
-	 * 默认 true 存在,false 不存在
-	 * </p>
-	 */
-	boolean exist() default true;
+    /**
+     * <p>
+     * 是否为数据库表字段
+     * </p>
+     * <p>
+     * 默认 true 存在,false 不存在
+     * </p>
+     */
+    boolean exist() default true;
 
-	/**
-	 * <p>
-	 * 字段验证
-	 * </p>
-	 * <p>
-	 * 默认 非 null 判断
-	 * </p>
-	 */
-	FieldStrategy validate() default FieldStrategy.NOT_NULL;
+    /**
+     * <p>
+     * 字段验证
+     * </p>
+     * <p>
+     * 默认 非 null 判断
+     * </p>
+     */
+    FieldStrategy validate() default FieldStrategy.NOT_NULL;
 
 }

+ 16 - 16
mybatis-plus/src/main/java/com/baomidou/mybatisplus/annotations/TableName.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
@@ -24,7 +24,7 @@ import java.lang.annotation.Target;
  * <p>
  * 数据库表相关
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
@@ -32,18 +32,18 @@ import java.lang.annotation.Target;
 @Target(ElementType.TYPE)
 public @interface TableName {
 
-	/*
-	 * <p>
-	 * 实体对应的表名
-	 * </p>
-	 */
-	String value() default "";
+    /*
+     * <p>
+     * 实体对应的表名
+     * </p>
+     */
+    String value() default "";
 
-	/*
-	 * <p>
-	 * 实体映射结果集
-	 * </p>
-	 */
-	String resultMap() default "";
+    /*
+     * <p>
+     * 实体映射结果集
+     * </p>
+     */
+    String resultMap() default "";
 
 }

+ 2 - 2
mybatis-plus/src/main/java/com/baomidou/mybatisplus/annotations/Version.java

@@ -8,11 +8,11 @@ import java.lang.annotation.Target;
 
 /**
  * 标记在verison字段上
- * 
+ *
  * @author TaoYu
  */
 @Retention(RetentionPolicy.RUNTIME)
-@Target({ ElementType.FIELD })
+@Target({ElementType.FIELD})
 @Documented
 public @interface Version {
 

+ 29 - 28
mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/CountOptimize.java

@@ -9,33 +9,34 @@ package com.baomidou.mybatisplus.entity;
  * @Date 2016-11-13
  */
 public class CountOptimize {
-	/**
-	 * 是否排序
-	 */
-	private boolean orderBy = true;
-	/**
-	 * 优化后计算Count的SQL
-	 */
-	private String countSQL;
-
-	public boolean isOrderBy() {
-		return orderBy;
-	}
-
-	public void setOrderBy(boolean orderBy) {
-		this.orderBy = orderBy;
-	}
-
-	public String getCountSQL() {
-		return countSQL;
-	}
-
-	public void setCountSQL(String countSQL) {
-		this.countSQL = countSQL;
-	}
-
-	public static CountOptimize newInstance() {
-		return new CountOptimize();
-	}
+
+    /**
+     * 是否排序
+     */
+    private boolean orderBy = true;
+    /**
+     * 优化后计算Count的SQL
+     */
+    private String countSQL;
+
+    public static CountOptimize newInstance() {
+        return new CountOptimize();
+    }
+
+    public boolean isOrderBy() {
+        return orderBy;
+    }
+
+    public void setOrderBy(boolean orderBy) {
+        this.orderBy = orderBy;
+    }
+
+    public String getCountSQL() {
+        return countSQL;
+    }
+
+    public void setCountSQL(String countSQL) {
+        this.countSQL = countSQL;
+    }
 
 }

+ 344 - 343
mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/GlobalConfiguration.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
@@ -15,6 +15,22 @@
  */
 package com.baomidou.mybatisplus.entity;
 
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+
+import javax.sql.DataSource;
+
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
+import org.apache.ibatis.session.Configuration;
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+
 import com.baomidou.mybatisplus.MybatisSqlSessionTemplate;
 import com.baomidou.mybatisplus.enums.DBType;
 import com.baomidou.mybatisplus.enums.FieldStrategy;
@@ -28,20 +44,6 @@ import com.baomidou.mybatisplus.toolkit.JdbcUtils;
 import com.baomidou.mybatisplus.toolkit.SqlReservedWords;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 import com.baomidou.mybatisplus.toolkit.TableInfoHelper;
-import org.apache.ibatis.logging.Log;
-import org.apache.ibatis.logging.LogFactory;
-import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.session.SqlSession;
-import org.apache.ibatis.session.SqlSessionFactory;
-
-import javax.sql.DataSource;
-import java.io.Serializable;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListSet;
 
 /**
  * <p>
@@ -54,330 +56,329 @@ import java.util.concurrent.ConcurrentSkipListSet;
 @SuppressWarnings("serial")
 public class GlobalConfiguration implements Cloneable, Serializable {
 
-	// 日志
-	private static final Log logger = LogFactory.getLog(GlobalConfiguration.class);
-	/**
-	 * 缓存全局信息
-	 */
-	private static final Map<String, GlobalConfiguration> GLOBAL_CONFIG = new ConcurrentHashMap<String, GlobalConfiguration>();
-	/**
-	 * 默认参数
-	 */
-	public static final GlobalConfiguration DEFAULT = new GlobalConfiguration();
-
-	// 数据库类型(默认 MySql)
-	private DBType dbType = DBType.MYSQL;
-	// 主键类型(默认 ID_WORKER)
-	private IdType idType = IdType.ID_WORKER;
-	// 表名、字段名、是否使用下划线命名(默认 false)
-	private boolean dbColumnUnderline = false;
-	// SQL注入器
-	private ISqlInjector sqlInjector;
-	// 元对象字段填充控制器
-	private IMetaObjectHandler metaObjectHandler = null;
-	// 字段验证策略
-	private FieldStrategy fieldStrategy = FieldStrategy.NOT_NULL;
-	// 是否刷新mapper
-	private boolean isRefresh = false;
-	// 是否自动获取DBType
-	private boolean isAutoSetDbType = true;
-	// 是否大写命名
-	private boolean isCapitalMode = false;
-	// 标识符
-	private String identifierQuote;
-	// 缓存当前Configuration的SqlSessionFactory
-	private SqlSessionFactory sqlSessionFactory;
-	// 缓存已注入CRUD的Mapper信息
-	private Set<String> mapperRegistryCache = new ConcurrentSkipListSet<String>();
-	// 单例重用SqlSession
-	private SqlSession sqlSession;
-
-	public GlobalConfiguration() {
-		// 构造方法
-	}
-
-	public GlobalConfiguration(ISqlInjector sqlInjector) {
-		this.sqlInjector = sqlInjector;
-	}
-
-	public DBType getDbType() {
-		return dbType;
-	}
-
-	public void setDbType(String dbType) {
-		this.dbType = DBType.getDBType(dbType);
-		this.isAutoSetDbType = false;
-	}
-
-	public void setDbTypeByJdbcUrl(String jdbcUrl) {
-		this.dbType = JdbcUtils.getDbType(jdbcUrl);
-	}
-
-	public IdType getIdType() {
-		return idType;
-	}
-
-	public void setIdType(int idType) {
-		this.idType = IdType.getIdType(idType);
-	}
-
-	public boolean isDbColumnUnderline() {
-		return dbColumnUnderline;
-	}
-
-	public void setDbColumnUnderline(boolean dbColumnUnderline) {
-		this.dbColumnUnderline = dbColumnUnderline;
-	}
-
-	public ISqlInjector getSqlInjector() {
-		return sqlInjector;
-	}
-
-	public void setSqlInjector(ISqlInjector sqlInjector) {
-		this.sqlInjector = sqlInjector;
-	}
-
-	public IMetaObjectHandler getMetaObjectHandler() {
-		return metaObjectHandler;
-	}
-
-	public void setMetaObjectHandler(IMetaObjectHandler metaObjectHandler) {
-		this.metaObjectHandler = metaObjectHandler;
-	}
-
-	public FieldStrategy getFieldStrategy() {
-		return fieldStrategy;
-	}
-
-	public void setFieldStrategy(int fieldStrategy) {
-		this.fieldStrategy = FieldStrategy.getFieldStrategy(fieldStrategy);
-	}
-
-	public boolean isRefresh() {
-		return isRefresh;
-	}
-
-	public void setRefresh(boolean refresh) {
-		this.isRefresh = refresh;
-	}
-
-	public boolean isAutoSetDbType() {
-		return isAutoSetDbType;
-	}
-
-	public void setAutoSetDbType(boolean autoSetDbType) {
-		this.isAutoSetDbType = autoSetDbType;
-	}
-
-	public Set<String> getMapperRegistryCache() {
-		return mapperRegistryCache;
-	}
-
-	public void setMapperRegistryCache(Set<String> mapperRegistryCache) {
-		this.mapperRegistryCache = mapperRegistryCache;
-	}
-
-	public SqlSessionFactory getSqlSessionFactory() {
-		return sqlSessionFactory;
-	}
-
-	public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
-		this.sqlSessionFactory = sqlSessionFactory;
-		this.sqlSession = new MybatisSqlSessionTemplate(sqlSessionFactory);
-	}
-
-	public boolean isCapitalMode() {
-		return isCapitalMode;
-	}
-
-	public void setCapitalMode(boolean isCapitalMode) {
-		this.isCapitalMode = isCapitalMode;
-	}
-
-	public String getIdentifierQuote() {
-		return identifierQuote;
-	}
-
-	public void setIdentifierQuote(String identifierQuote) {
-		this.identifierQuote = identifierQuote;
-	}
-
-	public void setSqlKeywords(String sqlKeywords) {
-		if (StringUtils.isNotEmpty(sqlKeywords)) {
-			SqlReservedWords.RESERVED_WORDS.addAll(StringUtils.splitWorker(sqlKeywords.toUpperCase(), ",", -1, false));
-		}
-	}
-
-	public SqlSession getSqlSession() {
-		return sqlSession;
-	}
-
-	@Override
-	protected GlobalConfiguration clone() throws CloneNotSupportedException {
-		return (GlobalConfiguration) super.clone();
-	}
-
-	/**
-	 * 获取当前的SqlSessionFactory
-	 *
-	 * @param clazz
-	 * @return
-	 */
-	public static SqlSessionFactory currentSessionFactory(Class<?> clazz) {
-		String configMark = TableInfoHelper.getTableInfo(clazz).getConfigMark();
-		GlobalConfiguration mybatisGlobalConfig = GlobalConfiguration.getGlobalConfig(configMark);
-		return mybatisGlobalConfig.getSqlSessionFactory();
-	}
-
-	/**
-	 * 获取默认MybatisGlobalConfig
-	 *
-	 * @return
-	 */
-	public static GlobalConfiguration defaults() {
-		try {
-			GlobalConfiguration clone = DEFAULT.clone();
-			clone.setSqlInjector(new AutoSqlInjector());
-			return clone;
-		} catch (CloneNotSupportedException e) {
-			throw new MybatisPlusException("ERROR: CLONE MybatisGlobalConfig DEFAULT FAIL !  Cause:" + e);
-		}
-	}
-
-	/**
-	 * <p>
-	 * 设置全局设置(以configuration地址值作为Key)
-	 * <p/>
-	 *
-	 * @param configuration
-	 * @param mybatisGlobalConfig
-	 * @return
-	 */
-	public static void setGlobalConfig(Configuration configuration, GlobalConfiguration mybatisGlobalConfig) {
-		if (configuration == null || mybatisGlobalConfig == null) {
-			throw new MybatisPlusException("Error: Could not setGlobalConfig");
-		}
-		// 设置全局设置
-		GLOBAL_CONFIG.put(configuration.toString(), mybatisGlobalConfig);
-	}
-
-	/**
-	 * <p>
-	 * 标记全局设置 (统一所有入口)
-	 * </p>
-	 *
-	 * @param sqlSessionFactory
-	 * @return
-	 */
-	public SqlSessionFactory signGlobalConfig(SqlSessionFactory sqlSessionFactory) {
-		if (null != sqlSessionFactory) {
-			setGlobalConfig(sqlSessionFactory.getConfiguration(), this);
-		}
-		return sqlSessionFactory;
-	}
-
-	/**
-	 * 获取MybatisGlobalConfig (统一所有入口)
-	 *
-	 * @param configuration
-	 * @return
-	 */
-	public static GlobalConfiguration getGlobalConfig(Configuration configuration) {
-		if (configuration == null) {
-			throw new MybatisPlusException("Error: You need Initialize MybatisConfiguration !");
-		}
-		return getGlobalConfig(configuration.toString());
-	}
-
-	/**
-	 * 获取MybatisGlobalConfig (统一所有入口)
-	 *
-	 * @param configMark
-	 * @return
-	 */
-	public static GlobalConfiguration getGlobalConfig(String configMark) {
-		GlobalConfiguration cache = GLOBAL_CONFIG.get(configMark);
-		if (cache == null) {
-			// 没有获取全局配置初始全局配置
-			logger.debug("DeBug: MyBatis Plus Global configuration Initializing !");
-			GLOBAL_CONFIG.put(configMark, DEFAULT);
-			return DEFAULT;
-		}
-		return cache;
-	}
-
-	public static DBType getDbType(Configuration configuration) {
-		return getGlobalConfig(configuration).getDbType();
-	}
-
-	public static IdType getIdType(Configuration configuration) {
-		return getGlobalConfig(configuration).getIdType();
-	}
-
-	public static boolean isDbColumnUnderline(Configuration configuration) {
-		return getGlobalConfig(configuration).isDbColumnUnderline();
-	}
-
-	public static ISqlInjector getSqlInjector(Configuration configuration) {
-		// fix #140
-		GlobalConfiguration globalConfiguration = getGlobalConfig(configuration);
-		ISqlInjector sqlInjector = globalConfiguration.getSqlInjector();
-		if (sqlInjector == null) {
-			sqlInjector = new AutoSqlInjector();
-			globalConfiguration.setSqlInjector(sqlInjector);
-		}
-		return sqlInjector;
-	}
-
-	public static IMetaObjectHandler getMetaObjectHandler(Configuration configuration) {
-		return getGlobalConfig(configuration).getMetaObjectHandler();
-	}
-
-	public static FieldStrategy getFieldStrategy(Configuration configuration) {
-		return getGlobalConfig(configuration).getFieldStrategy();
-	}
-
-	public static boolean isRefresh(Configuration configuration) {
-		return getGlobalConfig(configuration).isRefresh();
-	}
-
-	public static boolean isAutoSetDbType(Configuration configuration) {
-		return getGlobalConfig(configuration).isAutoSetDbType();
-	}
-
-	public static Set<String> getMapperRegistryCache(Configuration configuration) {
-		return getGlobalConfig(configuration).getMapperRegistryCache();
-	}
-
-	public static String getIdentifierQuote(Configuration configuration) {
-		return getGlobalConfig(configuration).getIdentifierQuote();
-	}
-
-	public static SqlSession getSqlSession(Configuration configuration) {
-		return getGlobalConfig(configuration).getSqlSession();
-	}
-
-	/**
-	 * 设置元数据相关属性
-	 *
-	 * @param dataSource
-	 * @param globalConfig
-	 */
-	public static void setMetaData(DataSource dataSource, GlobalConfiguration globalConfig) {
-		Connection connection = null;
-		try {
-			connection = dataSource.getConnection();
-			String jdbcUrl = connection.getMetaData().getURL();
-			// 设置全局关键字
-			globalConfig.setSqlKeywords(connection.getMetaData().getSQLKeywords());
-			// 自动设置数据库类型
-			if (globalConfig.isAutoSetDbType()) {
-				globalConfig.setDbTypeByJdbcUrl(jdbcUrl);
-			}
-		} catch (SQLException e) {
-			logger.warn("Warn: GlobalConfiguration setMetaData Fail !  Cause:" + e);
-		} finally {
-			IOUtils.closeQuietly(connection);
-		}
-	}
+    /**
+     * 默认参数
+     */
+    public static final GlobalConfiguration DEFAULT = new GlobalConfiguration();
+    // 日志
+    private static final Log logger = LogFactory.getLog(GlobalConfiguration.class);
+    /**
+     * 缓存全局信息
+     */
+    private static final Map<String, GlobalConfiguration> GLOBAL_CONFIG = new ConcurrentHashMap<String, GlobalConfiguration>();
+    // 数据库类型(默认 MySql)
+    private DBType dbType = DBType.MYSQL;
+    // 主键类型(默认 ID_WORKER)
+    private IdType idType = IdType.ID_WORKER;
+    // 表名、字段名、是否使用下划线命名(默认 false)
+    private boolean dbColumnUnderline = false;
+    // SQL注入器
+    private ISqlInjector sqlInjector;
+    // 元对象字段填充控制器
+    private IMetaObjectHandler metaObjectHandler = null;
+    // 字段验证策略
+    private FieldStrategy fieldStrategy = FieldStrategy.NOT_NULL;
+    // 是否刷新mapper
+    private boolean isRefresh = false;
+    // 是否自动获取DBType
+    private boolean isAutoSetDbType = true;
+    // 是否大写命名
+    private boolean isCapitalMode = false;
+    // 标识符
+    private String identifierQuote;
+    // 缓存当前Configuration的SqlSessionFactory
+    private SqlSessionFactory sqlSessionFactory;
+    // 缓存已注入CRUD的Mapper信息
+    private Set<String> mapperRegistryCache = new ConcurrentSkipListSet<String>();
+    // 单例重用SqlSession
+    private SqlSession sqlSession;
+
+    public GlobalConfiguration() {
+        // 构造方法
+    }
+
+    public GlobalConfiguration(ISqlInjector sqlInjector) {
+        this.sqlInjector = sqlInjector;
+    }
+
+    /**
+     * 获取当前的SqlSessionFactory
+     *
+     * @param clazz
+     * @return
+     */
+    public static SqlSessionFactory currentSessionFactory(Class<?> clazz) {
+        String configMark = TableInfoHelper.getTableInfo(clazz).getConfigMark();
+        GlobalConfiguration mybatisGlobalConfig = GlobalConfiguration.getGlobalConfig(configMark);
+        return mybatisGlobalConfig.getSqlSessionFactory();
+    }
+
+    /**
+     * 获取默认MybatisGlobalConfig
+     *
+     * @return
+     */
+    public static GlobalConfiguration defaults() {
+        try {
+            GlobalConfiguration clone = DEFAULT.clone();
+            clone.setSqlInjector(new AutoSqlInjector());
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            throw new MybatisPlusException("ERROR: CLONE MybatisGlobalConfig DEFAULT FAIL !  Cause:" + e);
+        }
+    }
+
+    /**
+     * <p>
+     * 设置全局设置(以configuration地址值作为Key)
+     * <p/>
+     *
+     * @param configuration
+     * @param mybatisGlobalConfig
+     * @return
+     */
+    public static void setGlobalConfig(Configuration configuration, GlobalConfiguration mybatisGlobalConfig) {
+        if (configuration == null || mybatisGlobalConfig == null) {
+            throw new MybatisPlusException("Error: Could not setGlobalConfig");
+        }
+        // 设置全局设置
+        GLOBAL_CONFIG.put(configuration.toString(), mybatisGlobalConfig);
+    }
+
+    /**
+     * 获取MybatisGlobalConfig (统一所有入口)
+     *
+     * @param configuration
+     * @return
+     */
+    public static GlobalConfiguration getGlobalConfig(Configuration configuration) {
+        if (configuration == null) {
+            throw new MybatisPlusException("Error: You need Initialize MybatisConfiguration !");
+        }
+        return getGlobalConfig(configuration.toString());
+    }
+
+    /**
+     * 获取MybatisGlobalConfig (统一所有入口)
+     *
+     * @param configMark
+     * @return
+     */
+    public static GlobalConfiguration getGlobalConfig(String configMark) {
+        GlobalConfiguration cache = GLOBAL_CONFIG.get(configMark);
+        if (cache == null) {
+            // 没有获取全局配置初始全局配置
+            logger.debug("DeBug: MyBatis Plus Global configuration Initializing !");
+            GLOBAL_CONFIG.put(configMark, DEFAULT);
+            return DEFAULT;
+        }
+        return cache;
+    }
+
+    public static DBType getDbType(Configuration configuration) {
+        return getGlobalConfig(configuration).getDbType();
+    }
+
+    public static IdType getIdType(Configuration configuration) {
+        return getGlobalConfig(configuration).getIdType();
+    }
+
+    public static boolean isDbColumnUnderline(Configuration configuration) {
+        return getGlobalConfig(configuration).isDbColumnUnderline();
+    }
+
+    public static ISqlInjector getSqlInjector(Configuration configuration) {
+        // fix #140
+        GlobalConfiguration globalConfiguration = getGlobalConfig(configuration);
+        ISqlInjector sqlInjector = globalConfiguration.getSqlInjector();
+        if (sqlInjector == null) {
+            sqlInjector = new AutoSqlInjector();
+            globalConfiguration.setSqlInjector(sqlInjector);
+        }
+        return sqlInjector;
+    }
+
+    public static IMetaObjectHandler getMetaObjectHandler(Configuration configuration) {
+        return getGlobalConfig(configuration).getMetaObjectHandler();
+    }
+
+    public static FieldStrategy getFieldStrategy(Configuration configuration) {
+        return getGlobalConfig(configuration).getFieldStrategy();
+    }
+
+    public static boolean isRefresh(Configuration configuration) {
+        return getGlobalConfig(configuration).isRefresh();
+    }
+
+    public static boolean isAutoSetDbType(Configuration configuration) {
+        return getGlobalConfig(configuration).isAutoSetDbType();
+    }
+
+    public static Set<String> getMapperRegistryCache(Configuration configuration) {
+        return getGlobalConfig(configuration).getMapperRegistryCache();
+    }
+
+    public static String getIdentifierQuote(Configuration configuration) {
+        return getGlobalConfig(configuration).getIdentifierQuote();
+    }
+
+    public static SqlSession getSqlSession(Configuration configuration) {
+        return getGlobalConfig(configuration).getSqlSession();
+    }
+
+    /**
+     * 设置元数据相关属性
+     *
+     * @param dataSource
+     * @param globalConfig
+     */
+    public static void setMetaData(DataSource dataSource, GlobalConfiguration globalConfig) {
+        Connection connection = null;
+        try {
+            connection = dataSource.getConnection();
+            String jdbcUrl = connection.getMetaData().getURL();
+            // 设置全局关键字
+            globalConfig.setSqlKeywords(connection.getMetaData().getSQLKeywords());
+            // 自动设置数据库类型
+            if (globalConfig.isAutoSetDbType()) {
+                globalConfig.setDbTypeByJdbcUrl(jdbcUrl);
+            }
+        } catch (SQLException e) {
+            logger.warn("Warn: GlobalConfiguration setMetaData Fail !  Cause:" + e);
+        } finally {
+            IOUtils.closeQuietly(connection);
+        }
+    }
+
+    public DBType getDbType() {
+        return dbType;
+    }
+
+    public void setDbType(String dbType) {
+        this.dbType = DBType.getDBType(dbType);
+        this.isAutoSetDbType = false;
+    }
+
+    public void setDbTypeByJdbcUrl(String jdbcUrl) {
+        this.dbType = JdbcUtils.getDbType(jdbcUrl);
+    }
+
+    public IdType getIdType() {
+        return idType;
+    }
+
+    public void setIdType(int idType) {
+        this.idType = IdType.getIdType(idType);
+    }
+
+    public boolean isDbColumnUnderline() {
+        return dbColumnUnderline;
+    }
+
+    public void setDbColumnUnderline(boolean dbColumnUnderline) {
+        this.dbColumnUnderline = dbColumnUnderline;
+    }
+
+    public ISqlInjector getSqlInjector() {
+        return sqlInjector;
+    }
+
+    public void setSqlInjector(ISqlInjector sqlInjector) {
+        this.sqlInjector = sqlInjector;
+    }
+
+    public IMetaObjectHandler getMetaObjectHandler() {
+        return metaObjectHandler;
+    }
+
+    public void setMetaObjectHandler(IMetaObjectHandler metaObjectHandler) {
+        this.metaObjectHandler = metaObjectHandler;
+    }
+
+    public FieldStrategy getFieldStrategy() {
+        return fieldStrategy;
+    }
+
+    public void setFieldStrategy(int fieldStrategy) {
+        this.fieldStrategy = FieldStrategy.getFieldStrategy(fieldStrategy);
+    }
+
+    public boolean isRefresh() {
+        return isRefresh;
+    }
+
+    public void setRefresh(boolean refresh) {
+        this.isRefresh = refresh;
+    }
+
+    public boolean isAutoSetDbType() {
+        return isAutoSetDbType;
+    }
+
+    public void setAutoSetDbType(boolean autoSetDbType) {
+        this.isAutoSetDbType = autoSetDbType;
+    }
+
+    public Set<String> getMapperRegistryCache() {
+        return mapperRegistryCache;
+    }
+
+    public void setMapperRegistryCache(Set<String> mapperRegistryCache) {
+        this.mapperRegistryCache = mapperRegistryCache;
+    }
+
+    public SqlSessionFactory getSqlSessionFactory() {
+        return sqlSessionFactory;
+    }
+
+    public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.sqlSession = new MybatisSqlSessionTemplate(sqlSessionFactory);
+    }
+
+    public boolean isCapitalMode() {
+        return isCapitalMode;
+    }
+
+    public void setCapitalMode(boolean isCapitalMode) {
+        this.isCapitalMode = isCapitalMode;
+    }
+
+    public String getIdentifierQuote() {
+        return identifierQuote;
+    }
+
+    public void setIdentifierQuote(String identifierQuote) {
+        this.identifierQuote = identifierQuote;
+    }
+
+    public void setSqlKeywords(String sqlKeywords) {
+        if (StringUtils.isNotEmpty(sqlKeywords)) {
+            SqlReservedWords.RESERVED_WORDS.addAll(StringUtils.splitWorker(sqlKeywords.toUpperCase(), ",", -1, false));
+        }
+    }
+
+    public SqlSession getSqlSession() {
+        return sqlSession;
+    }
+
+    @Override
+    protected GlobalConfiguration clone() throws CloneNotSupportedException {
+        return (GlobalConfiguration) super.clone();
+    }
+
+    /**
+     * <p>
+     * 标记全局设置 (统一所有入口)
+     * </p>
+     *
+     * @param sqlSessionFactory
+     * @return
+     */
+    public SqlSessionFactory signGlobalConfig(SqlSessionFactory sqlSessionFactory) {
+        if (null != sqlSessionFactory) {
+            setGlobalConfig(sqlSessionFactory.getConfiguration(), this);
+        }
+        return sqlSessionFactory;
+    }
 }

+ 124 - 124
mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/TableFieldInfo.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
@@ -29,130 +29,130 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  */
 public class TableFieldInfo {
 
-	/**
-	 * <p>
-	 * 是否有存在字段名与属性名关联
-	 * </p>
-	 * true , false
-	 */
-	private boolean related = false;
-
-	/**
-	 * 字段名
-	 */
-	private String column;
-
-	/**
-	 * 属性名
-	 */
-	private String property;
-
-	/**
-	 * 属性表达式#{property}, 可以指定jdbcType, typeHandler等
-	 */
-	private String el;
-	/**
-	 * 属性类型
-	 */
-	private String propertyType;
-
-	/**
-	 * 字段策略【 默认,自判断 null 】
-	 */
-	private FieldStrategy fieldStrategy = FieldStrategy.NOT_NULL;
-
-	/**
-	 * <p>
-	 * 存在 TableField 注解构造函数
-	 * </p>
-	 */
-	public TableFieldInfo(GlobalConfiguration globalConfig, String column, String property, String el,
-			FieldStrategy fieldStrategy, String propertyType) {
-		if (globalConfig.isDbColumnUnderline()) {
-			/* 开启字段下划线申明 */
-			this.related = true;
-		} else if (!column.equals(property)) {
+    /**
+     * <p>
+     * 是否有存在字段名与属性名关联
+     * </p>
+     * true , false
+     */
+    private boolean related = false;
+
+    /**
+     * 字段名
+     */
+    private String column;
+
+    /**
+     * 属性名
+     */
+    private String property;
+
+    /**
+     * 属性表达式#{property}, 可以指定jdbcType, typeHandler等
+     */
+    private String el;
+    /**
+     * 属性类型
+     */
+    private String propertyType;
+
+    /**
+     * 字段策略【 默认,自判断 null 】
+     */
+    private FieldStrategy fieldStrategy = FieldStrategy.NOT_NULL;
+
+    /**
+     * <p>
+     * 存在 TableField 注解构造函数
+     * </p>
+     */
+    public TableFieldInfo(GlobalConfiguration globalConfig, String column, String property, String el,
+                          FieldStrategy fieldStrategy, String propertyType) {
+        if (globalConfig.isDbColumnUnderline()) {
+            /* 开启字段下划线申明 */
+            this.related = true;
+        } else if (!column.equals(property)) {
 			/* 没有开启下划线申明 但是column与property不等的情况下设置related为true */
-			this.related = true;
-		}
-		this.setColumn(globalConfig, column);
-		this.property = property;
-		this.el = el;
+            this.related = true;
+        }
+        this.setColumn(globalConfig, column);
+        this.property = property;
+        this.el = el;
 		/*
 		 * 优先使用单个字段注解,否则使用全局配置
 		 */
-		if (fieldStrategy != FieldStrategy.NOT_NULL) {
-			this.fieldStrategy = fieldStrategy;
-		} else {
-			this.fieldStrategy = globalConfig.getFieldStrategy();
-		}
-		this.propertyType = propertyType;
-	}
-
-	public TableFieldInfo(GlobalConfiguration globalConfig, String column, String propertyType) {
-		if (globalConfig.isDbColumnUnderline()) {
+        if (fieldStrategy != FieldStrategy.NOT_NULL) {
+            this.fieldStrategy = fieldStrategy;
+        } else {
+            this.fieldStrategy = globalConfig.getFieldStrategy();
+        }
+        this.propertyType = propertyType;
+    }
+
+    public TableFieldInfo(GlobalConfiguration globalConfig, String column, String propertyType) {
+        if (globalConfig.isDbColumnUnderline()) {
 			/* 开启字段下划线申明 */
-			this.related = true;
-			this.setColumn(globalConfig, StringUtils.camelToUnderline(column));
-		} else {
-			this.setColumn(globalConfig, column);
-		}
-		this.property = column;
-		this.el = column;
-		this.fieldStrategy = globalConfig.getFieldStrategy();
-		this.propertyType = propertyType;
-	}
-
-	public boolean isRelated() {
-		return related;
-	}
-
-	public void setRelated(boolean related) {
-		this.related = related;
-	}
-
-	public String getColumn() {
-		return column;
-	}
-
-	public void setColumn(GlobalConfiguration globalConfig, String column) {
-		String temp = SqlReservedWords.convert(globalConfig, column);
-		if (globalConfig.isCapitalMode() && !isRelated()) {
-			// 全局大写,非注解指定
-			temp = temp.toUpperCase();
-		}
-		this.column = temp;
-	}
-
-	public String getProperty() {
-		return property;
-	}
-
-	public void setProperty(String property) {
-		this.property = property;
-	}
-
-	public String getEl() {
-		return el;
-	}
-
-	public void setEl(String el) {
-		this.el = el;
-	}
-
-	public FieldStrategy getFieldStrategy() {
-		return fieldStrategy;
-	}
-
-	public void setFieldStrategy(FieldStrategy fieldStrategy) {
-		this.fieldStrategy = fieldStrategy;
-	}
-
-	public String getPropertyType() {
-		return propertyType;
-	}
-
-	public void setPropertyType(String propertyType) {
-		this.propertyType = propertyType;
-	}
+            this.related = true;
+            this.setColumn(globalConfig, StringUtils.camelToUnderline(column));
+        } else {
+            this.setColumn(globalConfig, column);
+        }
+        this.property = column;
+        this.el = column;
+        this.fieldStrategy = globalConfig.getFieldStrategy();
+        this.propertyType = propertyType;
+    }
+
+    public boolean isRelated() {
+        return related;
+    }
+
+    public void setRelated(boolean related) {
+        this.related = related;
+    }
+
+    public String getColumn() {
+        return column;
+    }
+
+    public void setColumn(GlobalConfiguration globalConfig, String column) {
+        String temp = SqlReservedWords.convert(globalConfig, column);
+        if (globalConfig.isCapitalMode() && !isRelated()) {
+            // 全局大写,非注解指定
+            temp = temp.toUpperCase();
+        }
+        this.column = temp;
+    }
+
+    public String getProperty() {
+        return property;
+    }
+
+    public void setProperty(String property) {
+        this.property = property;
+    }
+
+    public String getEl() {
+        return el;
+    }
+
+    public void setEl(String el) {
+        this.el = el;
+    }
+
+    public FieldStrategy getFieldStrategy() {
+        return fieldStrategy;
+    }
+
+    public void setFieldStrategy(FieldStrategy fieldStrategy) {
+        this.fieldStrategy = fieldStrategy;
+    }
+
+    public String getPropertyType() {
+        return propertyType;
+    }
+
+    public void setPropertyType(String propertyType) {
+        this.propertyType = propertyType;
+    }
 }

+ 146 - 145
mybatis-plus/src/main/java/com/baomidou/mybatisplus/entity/TableInfo.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
@@ -15,159 +15,160 @@
  */
 package com.baomidou.mybatisplus.entity;
 
-import com.baomidou.mybatisplus.enums.IdType;
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import java.util.List;
+
 import org.apache.ibatis.session.Configuration;
 
-import java.util.List;
+import com.baomidou.mybatisplus.enums.IdType;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 
 /**
  * <p>
  * 数据库表反射信息
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class TableInfo {
 
-	/**
-	 * 表主键ID 类型
-	 */
-	private IdType idType;
-
-	/**
-	 * 表名称
-	 */
-	private String tableName;
-
-	/**
-	 * 表映射结果集
-	 */
-	private String resultMap;
-
-	/**
-	 * <p>
-	 * 主键是否有存在字段名与属性名关联
-	 * </p>
-	 * true , false
-	 */
-	private boolean keyRelated = false;
-
-	/**
-	 * 表主键ID 属性名
-	 */
-	private String keyProperty;
-
-	/**
-	 * 表主键ID 字段名
-	 */
-	private String keyColumn;
-
-	/**
-	 * 表字段信息列表
-	 */
-	private List<TableFieldInfo> fieldList;
-
-	/**
-	 * 命名空间
-	 */
-	private String currentNamespace;
-	/**
-	 * MybatisConfiguration 标记 (Configuration内存地址值)
-	 */
-	private String configMark;
-
-	/**
-	 * <p>
-	 * 获得注入的 SQL Statement
-	 * </p>
-	 * 
-	 * @param sqlMethod
-	 *            MybatisPlus 支持 SQL 方法
-	 * @return
-	 */
-	public String getSqlStatement(String sqlMethod) {
-		StringBuilder statement = new StringBuilder();
-		statement.append(currentNamespace);
-		statement.append(".");
-		statement.append(sqlMethod);
-		return statement.toString();
-	}
-
-	public IdType getIdType() {
-		return idType;
-	}
-
-	public void setIdType(IdType idType) {
-		this.idType = idType;
-	}
-
-	public String getTableName() {
-		return tableName;
-	}
-
-	public void setTableName(String tableName) {
-		this.tableName = tableName;
-	}
-
-	public String getResultMap() {
-		return resultMap;
-	}
-
-	public void setResultMap(String resultMap) {
-		this.resultMap = resultMap;
-	}
-
-	public boolean isKeyRelated() {
-		return keyRelated;
-	}
-
-	public void setKeyRelated(boolean keyRelated) {
-		this.keyRelated = keyRelated;
-	}
-
-	public String getKeyProperty() {
-		return keyProperty;
-	}
-
-	public void setKeyProperty(String keyProperty) {
-		this.keyProperty = keyProperty;
-	}
-
-	public String getKeyColumn() {
-		return keyColumn;
-	}
-
-	public void setKeyColumn(String keyColumn) {
-		this.keyColumn = keyColumn;
-	}
-
-	public List<TableFieldInfo> getFieldList() {
-		return fieldList;
-	}
-
-	public void setFieldList(List<TableFieldInfo> fieldList) {
-		this.fieldList = fieldList;
-	}
-
-	public String getCurrentNamespace() {
-		return currentNamespace;
-	}
-
-	public void setCurrentNamespace(String currentNamespace) {
-		this.currentNamespace = currentNamespace;
-	}
-
-	public String getConfigMark() {
-		return configMark;
-	}
-
-	public void setConfigMark(Configuration configuration) {
-		if (configuration == null) {
-			throw new MybatisPlusException("Error: You need Initialize MybatisConfiguration !");
-		}
-		this.configMark = configuration.toString();
-	}
+    /**
+     * 表主键ID 类型
+     */
+    private IdType idType;
+
+    /**
+     * 表名称
+     */
+    private String tableName;
+
+    /**
+     * 表映射结果集
+     */
+    private String resultMap;
+
+    /**
+     * <p>
+     * 主键是否有存在字段名与属性名关联
+     * </p>
+     * true , false
+     */
+    private boolean keyRelated = false;
+
+    /**
+     * 表主键ID 属性名
+     */
+    private String keyProperty;
+
+    /**
+     * 表主键ID 字段名
+     */
+    private String keyColumn;
+
+    /**
+     * 表字段信息列表
+     */
+    private List<TableFieldInfo> fieldList;
+
+    /**
+     * 命名空间
+     */
+    private String currentNamespace;
+    /**
+     * MybatisConfiguration 标记 (Configuration内存地址值)
+     */
+    private String configMark;
+
+    /**
+     * <p>
+     * 获得注入的 SQL Statement
+     * </p>
+     *
+     * @param sqlMethod
+     *            MybatisPlus 支持 SQL 方法
+     * @return
+     */
+    public String getSqlStatement(String sqlMethod) {
+        StringBuilder statement = new StringBuilder();
+        statement.append(currentNamespace);
+        statement.append(".");
+        statement.append(sqlMethod);
+        return statement.toString();
+    }
+
+    public IdType getIdType() {
+        return idType;
+    }
+
+    public void setIdType(IdType idType) {
+        this.idType = idType;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public void setTableName(String tableName) {
+        this.tableName = tableName;
+    }
+
+    public String getResultMap() {
+        return resultMap;
+    }
+
+    public void setResultMap(String resultMap) {
+        this.resultMap = resultMap;
+    }
+
+    public boolean isKeyRelated() {
+        return keyRelated;
+    }
+
+    public void setKeyRelated(boolean keyRelated) {
+        this.keyRelated = keyRelated;
+    }
+
+    public String getKeyProperty() {
+        return keyProperty;
+    }
+
+    public void setKeyProperty(String keyProperty) {
+        this.keyProperty = keyProperty;
+    }
+
+    public String getKeyColumn() {
+        return keyColumn;
+    }
+
+    public void setKeyColumn(String keyColumn) {
+        this.keyColumn = keyColumn;
+    }
+
+    public List<TableFieldInfo> getFieldList() {
+        return fieldList;
+    }
+
+    public void setFieldList(List<TableFieldInfo> fieldList) {
+        this.fieldList = fieldList;
+    }
+
+    public String getCurrentNamespace() {
+        return currentNamespace;
+    }
+
+    public void setCurrentNamespace(String currentNamespace) {
+        this.currentNamespace = currentNamespace;
+    }
+
+    public String getConfigMark() {
+        return configMark;
+    }
+
+    public void setConfigMark(Configuration configuration) {
+        if (configuration == null) {
+            throw new MybatisPlusException("Error: You need Initialize MybatisConfiguration !");
+        }
+        this.configMark = configuration.toString();
+    }
 
 }

+ 78 - 78
mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/DBType.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
@@ -24,88 +24,88 @@ package com.baomidou.mybatisplus.enums;
  * @Date 2016-04-15
  */
 public enum DBType {
-	/**
-	 * MYSQL
-	 */
-	MYSQL("mysql", "`%s`", "MySql数据库"),
-	/**
-	 * ORACLE
-	 */
-	ORACLE("oracle", "", "Oracle数据库"),
-	/**
-	 * DB2
-	 */
-	DB2("db2", "", "DB2数据库"),
-	/**
-	 * H2
-	 */
-	H2("h2", "", "H2数据库"),
-	/**
-	 * HSQL
-	 */
-	HSQL("hsql", "", "HSQL数据库"),
-	/**
-	 * SQLITE
-	 */
-	SQLITE("sqlite", "`%s`", "SQLite数据库"),
-	/**
-	 * POSTGRE
-	 */
-	POSTGRE("postgresql", "", "Postgre数据库"),
-	/**
-	 * SQLSERVER2005
-	 */
-	SQLSERVER2005("sqlserver2005", "[%s]", "SQLServer2005数据库"),
-	/**
-	 * SQLSERVER
-	 */
-	SQLSERVER("sqlserver", "[%s]", "SQLServer数据库"),
-	/**
-	 * UNKONWN DB
-	 */
-	OTHER("other", "", "其他数据库");
+    /**
+     * MYSQL
+     */
+    MYSQL("mysql", "`%s`", "MySql数据库"),
+    /**
+     * ORACLE
+     */
+    ORACLE("oracle", "", "Oracle数据库"),
+    /**
+     * DB2
+     */
+    DB2("db2", "", "DB2数据库"),
+    /**
+     * H2
+     */
+    H2("h2", "", "H2数据库"),
+    /**
+     * HSQL
+     */
+    HSQL("hsql", "", "HSQL数据库"),
+    /**
+     * SQLITE
+     */
+    SQLITE("sqlite", "`%s`", "SQLite数据库"),
+    /**
+     * POSTGRE
+     */
+    POSTGRE("postgresql", "", "Postgre数据库"),
+    /**
+     * SQLSERVER2005
+     */
+    SQLSERVER2005("sqlserver2005", "[%s]", "SQLServer2005数据库"),
+    /**
+     * SQLSERVER
+     */
+    SQLSERVER("sqlserver", "[%s]", "SQLServer数据库"),
+    /**
+     * UNKONWN DB
+     */
+    OTHER("other", "", "其他数据库");
 
-	private final String db;
+    private final String db;
 
-	private final String quote;
+    private final String quote;
 
-	private final String desc;
+    private final String desc;
 
-	DBType(final String db, final String quote, final String desc) {
-		this.db = db;
-		this.quote = quote;
-		this.desc = desc;
-	}
+    DBType(final String db, final String quote, final String desc) {
+        this.db = db;
+        this.quote = quote;
+        this.desc = desc;
+    }
 
-	/**
-	 * <p>
-	 * 获取数据库类型(默认 MySql)
-	 * </p>
-	 *
-	 * @param dbType
-	 *            数据库类型字符串
-	 * @return
-	 */
-	public static DBType getDBType(String dbType) {
-		DBType[] dts = DBType.values();
-		for (DBType dt : dts) {
-			if (dt.getDb().equalsIgnoreCase(dbType)) {
-				return dt;
-			}
-		}
-		return MYSQL;
-	}
+    /**
+     * <p>
+     * 获取数据库类型(默认 MySql)
+     * </p>
+     *
+     * @param dbType
+     *            数据库类型字符串
+     * @return
+     */
+    public static DBType getDBType(String dbType) {
+        DBType[] dts = DBType.values();
+        for (DBType dt : dts) {
+            if (dt.getDb().equalsIgnoreCase(dbType)) {
+                return dt;
+            }
+        }
+        return MYSQL;
+    }
 
-	public String getDb() {
-		return this.db;
-	}
+    public String getDb() {
+        return this.db;
+    }
 
-	public String getQuote() {
-		return this.quote;
-	}
+    public String getQuote() {
+        return this.quote;
+    }
 
-	public String getDesc() {
-		return this.desc;
-	}
+    public String getDesc() {
+        return this.desc;
+    }
 
 }

+ 35 - 35
mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/FieldStrategy.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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <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.
@@ -19,40 +19,40 @@ package com.baomidou.mybatisplus.enums;
  * <p>
  * 字段策略枚举类
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-09-09
  */
 public enum FieldStrategy {
-	IGNORED(0, "ignored"), NOT_NULL(1, "not null"), NOT_EMPTY(2, "not empty");
-
-	/** 主键 */
-	private final int key;
-
-	/** 描述 */
-	private final String desc;
-
-	FieldStrategy(final int key, final String desc) {
-		this.key = key;
-		this.desc = desc;
-	}
-
-	public int getKey() {
-		return this.key;
-	}
-
-	public String getDesc() {
-		return this.desc;
-	}
-
-	public static FieldStrategy getFieldStrategy(int key) {
-		FieldStrategy[] fss = FieldStrategy.values();
-		for (FieldStrategy fs : fss) {
-			if (fs.getKey() == key) {
-				return fs;
-			}
-		}
-		return FieldStrategy.NOT_NULL;
-	}
+    IGNORED(0, "ignored"), NOT_NULL(1, "not null"), NOT_EMPTY(2, "not empty");
+
+    /** 主键 */
+    private final int key;
+
+    /** 描述 */
+    private final String desc;
+
+    FieldStrategy(final int key, final String desc) {
+        this.key = key;
+        this.desc = desc;
+    }
+
+    public static FieldStrategy getFieldStrategy(int key) {
+        FieldStrategy[] fss = FieldStrategy.values();
+        for (FieldStrategy fs : fss) {
+            if (fs.getKey() == key) {
+                return fs;
+            }
+        }
+        return FieldStrategy.NOT_NULL;
+    }
+
+    public int getKey() {
+        return this.key;
+    }
+
+    public String getDesc() {
+        return this.desc;
+    }
 
 }

+ 40 - 40
mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/IdType.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
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <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.
@@ -19,52 +19,52 @@ package com.baomidou.mybatisplus.enums;
  * <p>
  * 生成ID类型枚举类
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2015-11-10
  */
 public enum IdType {
-	AUTO(0, "数据库ID自增"), INPUT(1, "用户输入ID"),
+    AUTO(0, "数据库ID自增"), INPUT(1, "用户输入ID"),
 
-	/* 以下2种类型、只有当插入对象ID 为空,才自动填充。 */
-	ID_WORKER(2, "全局唯一ID"), UUID(3, "全局唯一ID"),NONE(4, "该类型为未设置主键类型");
+    /* 以下2种类型、只有当插入对象ID 为空,才自动填充。 */
+    ID_WORKER(2, "全局唯一ID"), UUID(3, "全局唯一ID"), NONE(4, "该类型为未设置主键类型");
 
-	/** 主键 */
-	private final int key;
+    /** 主键 */
+    private final int key;
 
-	/** 描述 */
-	private final String desc;
+    /** 描述 */
+    private final String desc;
 
-	IdType(final int key, final String desc) {
-		this.key = key;
-		this.desc = desc;
-	}
+    IdType(final int key, final String desc) {
+        this.key = key;
+        this.desc = desc;
+    }
 
-	/**
-	 * <p>
-	 * 主键策略 (默认 ID_WORKER)
-	 * </p>
-	 * 
-	 * @param idType
-	 *            ID 策略类型
-	 * @return
-	 */
-	public static IdType getIdType(int idType) {
-		IdType[] its = IdType.values();
-		for (IdType it : its) {
-			if (it.getKey() == idType) {
-				return it;
-			}
-		}
-		return ID_WORKER;
-	}
+    /**
+     * <p>
+     * 主键策略 (默认 ID_WORKER)
+     * </p>
+     *
+     * @param idType
+     *            ID 策略类型
+     * @return
+     */
+    public static IdType getIdType(int idType) {
+        IdType[] its = IdType.values();
+        for (IdType it : its) {
+            if (it.getKey() == idType) {
+                return it;
+            }
+        }
+        return ID_WORKER;
+    }
 
-	public int getKey() {
-		return this.key;
-	}
+    public int getKey() {
+        return this.key;
+    }
 
-	public String getDesc() {
-		return this.desc;
-	}
+    public String getDesc() {
+        return this.desc;
+    }
 
 }

+ 45 - 45
mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/Optimize.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
@@ -19,57 +19,57 @@ package com.baomidou.mybatisplus.enums;
  * <p>
  * Count优化枚举
  * </p>
- * 
+ *
  * @author Caratacus
  * @Date 2016-11-30
  */
 public enum Optimize {
-	/**
-	 * 默认支持方式
-	 */
-	DEFAULT("default", "默认方式"),
-	/**
-	 * aliDruid,需添加相关依赖jar包
-	 */
-	ALI_DRUID("aliDruid", "依赖aliDruid模式"),
-	/**
-	 * jsqlparser方式,需添加相关依赖jar包
-	 */
-	JSQLPARSER("jsqlparser", "jsqlparser方式");
+    /**
+     * 默认支持方式
+     */
+    DEFAULT("default", "默认方式"),
+    /**
+     * aliDruid,需添加相关依赖jar包
+     */
+    ALI_DRUID("aliDruid", "依赖aliDruid模式"),
+    /**
+     * jsqlparser方式,需添加相关依赖jar包
+     */
+    JSQLPARSER("jsqlparser", "jsqlparser方式");
 
-	private final String optimize;
+    private final String optimize;
 
-	private final String desc;
+    private final String desc;
 
-	Optimize(final String optimize, final String desc) {
-		this.optimize = optimize;
-		this.desc = desc;
-	}
+    Optimize(final String optimize, final String desc) {
+        this.optimize = optimize;
+        this.desc = desc;
+    }
 
-	/**
-	 * <p>
-	 * 获取优化类型.如果没有找到默认DEFAULT
-	 * </p>
-	 * 
-	 * @param optimizeType
-	 *            优化方式
-	 * @return
-	 */
-	public static Optimize getOptimizeType(String optimizeType) {
-		for (Optimize optimize : Optimize.values()) {
-			if (optimize.getOptimize().equalsIgnoreCase(optimizeType)) {
-				return optimize;
-			}
-		}
-		return DEFAULT;
-	}
+    /**
+     * <p>
+     * 获取优化类型.如果没有找到默认DEFAULT
+     * </p>
+     *
+     * @param optimizeType
+     *            优化方式
+     * @return
+     */
+    public static Optimize getOptimizeType(String optimizeType) {
+        for (Optimize optimize : Optimize.values()) {
+            if (optimize.getOptimize().equalsIgnoreCase(optimizeType)) {
+                return optimize;
+            }
+        }
+        return DEFAULT;
+    }
 
-	public String getOptimize() {
-		return this.optimize;
-	}
+    public String getOptimize() {
+        return this.optimize;
+    }
 
-	public String getDesc() {
-		return this.desc;
-	}
+    public String getDesc() {
+        return this.desc;
+    }
 
 }

+ 34 - 34
mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/SqlLike.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
@@ -19,45 +19,45 @@ package com.baomidou.mybatisplus.enums;
  * <p>
  * SQL like 枚举
  * </p>
- * 
+ *
  * @author Caratacus
  * @Date 2016-12-4
  */
 public enum SqlLike {
-	/**
-	 * LEFT
-	 */
-	LEFT("left", "左边%"),
-	/**
-	 * RIGHT
-	 */
-	RIGHT("right", "右边%"),
-	/**
-	 * CUSTOM
-	 */
-	CUSTOM("custom", "定制"),
-	/**
-	 * DEFAULT
-	 */
-	DEFAULT("default", "两边%");
+    /**
+     * LEFT
+     */
+    LEFT("left", "左边%"),
+    /**
+     * RIGHT
+     */
+    RIGHT("right", "右边%"),
+    /**
+     * CUSTOM
+     */
+    CUSTOM("custom", "定制"),
+    /**
+     * DEFAULT
+     */
+    DEFAULT("default", "两边%");
 
-	/** 主键 */
-	private final String type;
+    /** 主键 */
+    private final String type;
 
-	/** 描述 */
-	private final String desc;
+    /** 描述 */
+    private final String desc;
 
-	SqlLike(final String type, final String desc) {
-		this.type = type;
-		this.desc = desc;
-	}
+    SqlLike(final String type, final String desc) {
+        this.type = type;
+        this.desc = desc;
+    }
 
-	public String getType() {
-		return type;
-	}
+    public String getType() {
+        return type;
+    }
 
-	public String getDesc() {
-		return desc;
-	}
+    public String getDesc() {
+        return desc;
+    }
 
 }

+ 51 - 51
mybatis-plus/src/main/java/com/baomidou/mybatisplus/enums/SqlMethod.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
@@ -25,67 +25,67 @@ package com.baomidou.mybatisplus.enums;
  */
 public enum SqlMethod {
 
-	/**
-	 * 插入
-	 */
-	INSERT_ONE("insert", "插入一条数据", "<script>INSERT INTO %s %s VALUES %s</script>"),
-	INSERT_ONE_ALL_COLUMN("insertAllColumn", "插入一条数据(选择字段, null 字段不插入)", "<script>INSERT INTO %s %s VALUES %s</script>"),
+    /**
+     * 插入
+     */
+    INSERT_ONE("insert", "插入一条数据", "<script>INSERT INTO %s %s VALUES %s</script>"),
+    INSERT_ONE_ALL_COLUMN("insertAllColumn", "插入一条数据(选择字段, null 字段不插入)", "<script>INSERT INTO %s %s VALUES %s</script>"),
 
-	/**
-	 * 删除
-	 */
-	DELETE_BY_ID("deleteById", "根据ID 删除一条数据", "DELETE FROM %s WHERE %s=#{%s}"),
-	DELETE_BY_MAP("deleteByMap", "根据columnMap 条件删除记录", "<script>DELETE FROM %s %s</script>"),
-	DELETE("delete", "根据 entity 条件删除记录", "<script>DELETE FROM %s %s</script>"),
-	DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合,批量删除数据", "<script>DELETE FROM %s WHERE %s IN (%s)</script>"),
+    /**
+     * 删除
+     */
+    DELETE_BY_ID("deleteById", "根据ID 删除一条数据", "DELETE FROM %s WHERE %s=#{%s}"),
+    DELETE_BY_MAP("deleteByMap", "根据columnMap 条件删除记录", "<script>DELETE FROM %s %s</script>"),
+    DELETE("delete", "根据 entity 条件删除记录", "<script>DELETE FROM %s %s</script>"),
+    DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合,批量删除数据", "<script>DELETE FROM %s WHERE %s IN (%s)</script>"),
 
-	/**
-	 * 修改
-	 */
-	UPDATE_BY_ID("updateById", "根据ID 修改数据", "<script>UPDATE %s %s WHERE %s=#{%s}</script>"),
-	UPDATE_ALL_COLUMN_BY_ID("updateAllColumnById", "根据ID 选择修改数据", "<script>UPDATE %s %s WHERE %s=#{%s}</script>"),
-	UPDATE("update", "根据 whereEntity 条件,更新记录", "<script>UPDATE %s %s %s</script>"),
+    /**
+     * 修改
+     */
+    UPDATE_BY_ID("updateById", "根据ID 修改数据", "<script>UPDATE %s %s WHERE %s=#{%s}</script>"),
+    UPDATE_ALL_COLUMN_BY_ID("updateAllColumnById", "根据ID 选择修改数据", "<script>UPDATE %s %s WHERE %s=#{%s}</script>"),
+    UPDATE("update", "根据 whereEntity 条件,更新记录", "<script>UPDATE %s %s %s</script>"),
 
-	/**
-	 * 查询
-	 */
-	SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s}"),
-	SELECT_BY_MAP("selectByMap", "根据columnMap 查询一条数据", "<script>SELECT %s FROM %s %s</script>"),
-	SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合,批量查询数据", "<script>SELECT %s FROM %s WHERE %s IN (%s)</script>"),
-	SELECT_ONE("selectOne", "查询满足条件一条数据", "<script>SELECT %s FROM %s %s</script>"),
-	SELECT_COUNT("selectCount", "查询满足条件总记录数", "<script>SELECT COUNT(1) FROM %s %s</script>"),
-	SELECT_LIST("selectList", "查询满足条件所有数据", "<script>SELECT %s FROM %s %s</script>"),
-	SELECT_PAGE("selectPage", "查询满足条件所有数据(并翻页)", "<script>SELECT %s FROM %s %s</script>"),
-	SELECT_MAPS("selectMaps", "查询满足条件所有数据", "<script>SELECT %s FROM %s %s</script>"),
-	SELECT_MAPS_PAGE("selectMapsPage", "查询满足条件所有数据(并翻页)", "<script>SELECT %s FROM %s %s</script>"),
-	SELECT_OBJS("selectObjs", "查询满足条件所有数据", "<script>SELECT %s FROM %s %s</script>");
+    /**
+     * 查询
+     */
+    SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s}"),
+    SELECT_BY_MAP("selectByMap", "根据columnMap 查询一条数据", "<script>SELECT %s FROM %s %s</script>"),
+    SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合,批量查询数据", "<script>SELECT %s FROM %s WHERE %s IN (%s)</script>"),
+    SELECT_ONE("selectOne", "查询满足条件一条数据", "<script>SELECT %s FROM %s %s</script>"),
+    SELECT_COUNT("selectCount", "查询满足条件总记录数", "<script>SELECT COUNT(1) FROM %s %s</script>"),
+    SELECT_LIST("selectList", "查询满足条件所有数据", "<script>SELECT %s FROM %s %s</script>"),
+    SELECT_PAGE("selectPage", "查询满足条件所有数据(并翻页)", "<script>SELECT %s FROM %s %s</script>"),
+    SELECT_MAPS("selectMaps", "查询满足条件所有数据", "<script>SELECT %s FROM %s %s</script>"),
+    SELECT_MAPS_PAGE("selectMapsPage", "查询满足条件所有数据(并翻页)", "<script>SELECT %s FROM %s %s</script>"),
+    SELECT_OBJS("selectObjs", "查询满足条件所有数据", "<script>SELECT %s FROM %s %s</script>");
 
-	private final String method;
+    private final String method;
 
-	private final String desc;
+    private final String desc;
 
-	private final String sql;
+    private final String sql;
 
 
-	SqlMethod( final String method, final String desc, final String sql ) {
-		this.method = method;
-		this.desc = desc;
-		this.sql = sql;
-	}
+    SqlMethod(final String method, final String desc, final String sql) {
+        this.method = method;
+        this.desc = desc;
+        this.sql = sql;
+    }
 
 
-	public String getMethod() {
-		return this.method;
-	}
+    public String getMethod() {
+        return this.method;
+    }
 
 
-	public String getDesc() {
-		return this.desc;
-	}
+    public String getDesc() {
+        return this.desc;
+    }
 
 
-	public String getSql() {
-		return this.sql;
-	}
+    public String getSql() {
+        return this.sql;
+    }
 
 }

+ 14 - 14
mybatis-plus/src/main/java/com/baomidou/mybatisplus/exceptions/MybatisPlusException.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
@@ -19,24 +19,24 @@ package com.baomidou.mybatisplus.exceptions;
  * <p>
  * MybatisPlus 异常类
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class MybatisPlusException extends RuntimeException {
 
-	private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
-	public MybatisPlusException(String message) {
-		super(message);
-	}
+    public MybatisPlusException(String message) {
+        super(message);
+    }
 
-	public MybatisPlusException(Throwable throwable) {
-		super(throwable);
-	}
+    public MybatisPlusException(Throwable throwable) {
+        super(throwable);
+    }
 
-	public MybatisPlusException(String message, Throwable throwable) {
-		super(message, throwable);
-	}
+    public MybatisPlusException(String message, Throwable throwable) {
+        super(message, throwable);
+    }
 
 }

+ 90 - 96
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/AbstractGenerator.java

@@ -32,101 +32,95 @@ import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
  */
 public abstract class AbstractGenerator {
 
-	/**
-	 * 数据源配置
-	 */
-	private DataSourceConfig dataSource;
-
-	/**
-	 * 数据库表配置
-	 */
-	private StrategyConfig strategy;
-
-	/**
-	 * 包 相关配置
-	 */
-	private PackageConfig packageInfo;
-
-	/**
-	 * 模板 相关配置
-	 */
-	private TemplateConfig template;
-
-	/**
-	 * 全局 相关配置
-	 */
-	private GlobalConfig globalConfig;
-
-	protected ConfigBuilder config;
-
-	protected InjectionConfig injectionConfig;
-
-	/**
-	 * 初始化配置
-	 */
-	protected void initConfig() {
-		if (null == config) {
-			config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig);
-			if (null != injectionConfig) {
-				injectionConfig.setConfig(config);
-			}
-		}
-	}
-
-	public DataSourceConfig getDataSource() {
-		return dataSource;
-	}
-
-	public void setDataSource(DataSourceConfig dataSource) {
-		this.dataSource = dataSource;
-	}
-
-	public StrategyConfig getStrategy() {
-		return strategy;
-	}
-
-	public void setStrategy(StrategyConfig strategy) {
-		this.strategy = strategy;
-	}
-
-	public PackageConfig getPackageInfo() {
-		return packageInfo;
-	}
-
-	public void setPackageInfo(PackageConfig packageInfo) {
-		this.packageInfo = packageInfo;
-	}
-
-	public TemplateConfig getTemplate() {
-		return template;
-	}
-
-	public void setTemplate(TemplateConfig template) {
-		this.template = template;
-	}
-
-	public ConfigBuilder getConfig() {
-		return config;
-	}
-
-	public void setConfig(ConfigBuilder config) {
-		this.config = config;
-	}
-
-	public GlobalConfig getGlobalConfig() {
-		return globalConfig;
-	}
-
-	public void setGlobalConfig(GlobalConfig globalConfig) {
-		this.globalConfig = globalConfig;
-	}
-
-	public InjectionConfig getCfg() {
-		return injectionConfig;
-	}
-
-	public void setCfg(InjectionConfig injectionConfig) {
-		this.injectionConfig = injectionConfig;
-	}
+    protected ConfigBuilder config;
+    protected InjectionConfig injectionConfig;
+    /**
+     * 数据源配置
+     */
+    private DataSourceConfig dataSource;
+    /**
+     * 数据库表配置
+     */
+    private StrategyConfig strategy;
+    /**
+     * 包 相关配置
+     */
+    private PackageConfig packageInfo;
+    /**
+     * 模板 相关配置
+     */
+    private TemplateConfig template;
+    /**
+     * 全局 相关配置
+     */
+    private GlobalConfig globalConfig;
+
+    /**
+     * 初始化配置
+     */
+    protected void initConfig() {
+        if (null == config) {
+            config = new ConfigBuilder(packageInfo, dataSource, strategy, template, globalConfig);
+            if (null != injectionConfig) {
+                injectionConfig.setConfig(config);
+            }
+        }
+    }
+
+    public DataSourceConfig getDataSource() {
+        return dataSource;
+    }
+
+    public void setDataSource(DataSourceConfig dataSource) {
+        this.dataSource = dataSource;
+    }
+
+    public StrategyConfig getStrategy() {
+        return strategy;
+    }
+
+    public void setStrategy(StrategyConfig strategy) {
+        this.strategy = strategy;
+    }
+
+    public PackageConfig getPackageInfo() {
+        return packageInfo;
+    }
+
+    public void setPackageInfo(PackageConfig packageInfo) {
+        this.packageInfo = packageInfo;
+    }
+
+    public TemplateConfig getTemplate() {
+        return template;
+    }
+
+    public void setTemplate(TemplateConfig template) {
+        this.template = template;
+    }
+
+    public ConfigBuilder getConfig() {
+        return config;
+    }
+
+    public void setConfig(ConfigBuilder config) {
+        this.config = config;
+    }
+
+    public GlobalConfig getGlobalConfig() {
+        return globalConfig;
+    }
+
+    public void setGlobalConfig(GlobalConfig globalConfig) {
+        this.globalConfig = globalConfig;
+    }
+
+    public InjectionConfig getCfg() {
+        return injectionConfig;
+    }
+
+    public void setCfg(InjectionConfig injectionConfig) {
+        this.injectionConfig = injectionConfig;
+    }
 
 }

+ 253 - 250
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/AutoGenerator.java

@@ -15,13 +15,18 @@
  */
 package com.baomidou.mybatisplus.generator;
 
-import com.baomidou.mybatisplus.generator.config.ConstVal;
-import com.baomidou.mybatisplus.generator.config.FileOutConfig;
-import com.baomidou.mybatisplus.generator.config.TemplateConfig;
-import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
-import com.baomidou.mybatisplus.generator.config.po.TableInfo;
-import com.baomidou.mybatisplus.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.toolkit.StringUtils;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
 import org.apache.ibatis.logging.Log;
 import org.apache.ibatis.logging.LogFactory;
 import org.apache.velocity.Template;
@@ -29,268 +34,266 @@ import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.Velocity;
 import org.apache.velocity.app.VelocityEngine;
 
-import java.io.*;
-import java.text.SimpleDateFormat;
-import java.util.*;
+import com.baomidou.mybatisplus.generator.config.ConstVal;
+import com.baomidou.mybatisplus.generator.config.FileOutConfig;
+import com.baomidou.mybatisplus.generator.config.TemplateConfig;
+import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
+import com.baomidou.mybatisplus.generator.config.po.TableInfo;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
 
 /**
  * 生成文件
- * 
+ *
  * @author YangHu, tangguo
  * @since 2016-08-30
  */
 public class AutoGenerator extends AbstractGenerator {
 
-	private static final Log logger = LogFactory.getLog(AutoGenerator.class);
+    private static final Log logger = LogFactory.getLog(AutoGenerator.class);
 
-	/**
-	 * velocity引擎
-	 */
-	private VelocityEngine engine;
+    /**
+     * velocity引擎
+     */
+    private VelocityEngine engine;
 
-	/**
-	 * 生成代码
-	 */
-	public void execute() {
-		logger.debug("==========================准备生成文件...==========================");
-		// 初始化配置
-		initConfig();
-		// 创建输出文件路径
-		mkdirs(config.getPathInfo());
-		// 获取上下文
-		Map<String, VelocityContext> ctxData = analyzeData(config);
-		// 循环生成文件
-		for (Map.Entry<String, VelocityContext> ctx : ctxData.entrySet()) {
-			batchOutput(ctx.getKey(), ctx.getValue());
-		}
-		// 打开输出目录
-		if (config.getGlobalConfig().isOpen()) {
-			try {
-				String osName = System.getProperty("os.name");
-				if (osName != null) {
-					if (osName.contains("Mac")) {
-						Runtime.getRuntime().exec("open " + config.getGlobalConfig().getOutputDir());
-					} else if (osName.contains("Windows")) {
-						Runtime.getRuntime().exec("cmd /c start " + config.getGlobalConfig().getOutputDir());
-					} else {
-						logger.debug("文件输出目录:" + config.getGlobalConfig().getOutputDir());
-					}
-				}
-			} catch (IOException e) {
-				e.printStackTrace();
-			}
-		}
-		logger.debug("==========================文件生成完成!!!==========================");
-	}
+    /**
+     * 生成代码
+     */
+    public void execute() {
+        logger.debug("==========================准备生成文件...==========================");
+        // 初始化配置
+        initConfig();
+        // 创建输出文件路径
+        mkdirs(config.getPathInfo());
+        // 获取上下文
+        Map<String, VelocityContext> ctxData = analyzeData(config);
+        // 循环生成文件
+        for (Map.Entry<String, VelocityContext> ctx : ctxData.entrySet()) {
+            batchOutput(ctx.getKey(), ctx.getValue());
+        }
+        // 打开输出目录
+        if (config.getGlobalConfig().isOpen()) {
+            try {
+                String osName = System.getProperty("os.name");
+                if (osName != null) {
+                    if (osName.contains("Mac")) {
+                        Runtime.getRuntime().exec("open " + config.getGlobalConfig().getOutputDir());
+                    } else if (osName.contains("Windows")) {
+                        Runtime.getRuntime().exec("cmd /c start " + config.getGlobalConfig().getOutputDir());
+                    } else {
+                        logger.debug("文件输出目录:" + config.getGlobalConfig().getOutputDir());
+                    }
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        logger.debug("==========================文件生成完成!!!==========================");
+    }
 
-	/**
-	 * 分析数据
-	 *
-	 * @param config
-	 *            总配置信息
-	 * @return 解析数据结果集
-	 */
-	private Map<String, VelocityContext> analyzeData(ConfigBuilder config) {
-		List<TableInfo> tableList = config.getTableInfoList();
-		Map<String, String> packageInfo = config.getPackageInfo();
-		Map<String, VelocityContext> ctxData = new HashMap<String, VelocityContext>();
-		String superEntityClass = getSuperClassName(config.getSuperEntityClass());
-		String superMapperClass = getSuperClassName(config.getSuperMapperClass());
-		String superServiceClass = getSuperClassName(config.getSuperServiceClass());
-		String superServiceImplClass = getSuperClassName(config.getSuperServiceImplClass());
-		String superControllerClass = getSuperClassName(config.getSuperControllerClass());
-		String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
-		VelocityContext ctx;
-		for (TableInfo tableInfo : tableList) {
-			ctx = new VelocityContext();
-			if (null != injectionConfig) {
-				/**
-				 * 注入自定义配置
-				 */
-				injectionConfig.initMap();
-				ctx.put("cfg", injectionConfig.getMap());
-			}
-			/* ---------- 添加导入包 ---------- */
-			if (config.getGlobalConfig().isActiveRecord()) {
-				// 开启 ActiveRecord 模式
-				tableInfo.setImportPackages("com.baomidou.mybatisplus.activerecord.Model");
-			}
-			if (tableInfo.isConvert()) {
-				// 表注解
-				tableInfo.setImportPackages("com.baomidou.mybatisplus.annotations.TableName");
-			}
-			if (StringUtils.isNotEmpty(config.getSuperEntityClass())) {
-				// 父实体
-				tableInfo.setImportPackages(config.getSuperEntityClass());
-			} else {
-				tableInfo.setImportPackages("java.io.Serializable");
-			}
-			ctx.put("package", packageInfo);
-			ctx.put("author", config.getGlobalConfig().getAuthor());
-			ctx.put("activeRecord", config.getGlobalConfig().isActiveRecord());
-			ctx.put("date", date);
-			ctx.put("table", tableInfo);
-			ctx.put("enableCache", config.getGlobalConfig().isEnableCache());
-			ctx.put("baseResultMap", config.getGlobalConfig().isBaseResultMap());
-			ctx.put("baseColumnList", config.getGlobalConfig().isBaseColumnList());
-			ctx.put("entity", tableInfo.getEntityName());
-			ctx.put("entityColumnConstant", config.getStrategyConfig().isEntityColumnConstant());
-			ctx.put("entityBuilderModel", config.getStrategyConfig().isEntityBuilderModel());
-			ctx.put("superEntityClass", superEntityClass);
-			ctx.put("superMapperClassPackage", config.getSuperMapperClass());
-			ctx.put("superMapperClass", superMapperClass);
-			ctx.put("superServiceClassPackage", config.getSuperServiceClass());
-			ctx.put("superServiceClass", superServiceClass);
-			ctx.put("superServiceImplClassPackage", config.getSuperServiceImplClass());
-			ctx.put("superServiceImplClass", superServiceImplClass);
-			ctx.put("superControllerClassPackage", config.getSuperControllerClass());
-			ctx.put("superControllerClass", superControllerClass);
-			ctxData.put(tableInfo.getEntityName(), ctx);
-		}
-		return ctxData;
-	}
+    /**
+     * 分析数据
+     *
+     * @param config 总配置信息
+     * @return 解析数据结果集
+     */
+    private Map<String, VelocityContext> analyzeData(ConfigBuilder config) {
+        List<TableInfo> tableList = config.getTableInfoList();
+        Map<String, String> packageInfo = config.getPackageInfo();
+        Map<String, VelocityContext> ctxData = new HashMap<String, VelocityContext>();
+        String superEntityClass = getSuperClassName(config.getSuperEntityClass());
+        String superMapperClass = getSuperClassName(config.getSuperMapperClass());
+        String superServiceClass = getSuperClassName(config.getSuperServiceClass());
+        String superServiceImplClass = getSuperClassName(config.getSuperServiceImplClass());
+        String superControllerClass = getSuperClassName(config.getSuperControllerClass());
+        String date = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
+        VelocityContext ctx;
+        for (TableInfo tableInfo : tableList) {
+            ctx = new VelocityContext();
+            if (null != injectionConfig) {
+                /**
+                 * 注入自定义配置
+                 */
+                injectionConfig.initMap();
+                ctx.put("cfg", injectionConfig.getMap());
+            }
+            /* ---------- 添加导入包 ---------- */
+            if (config.getGlobalConfig().isActiveRecord()) {
+                // 开启 ActiveRecord 模式
+                tableInfo.setImportPackages("com.baomidou.mybatisplus.activerecord.Model");
+            }
+            if (tableInfo.isConvert()) {
+                // 表注解
+                tableInfo.setImportPackages("com.baomidou.mybatisplus.annotations.TableName");
+            }
+            if (StringUtils.isNotEmpty(config.getSuperEntityClass())) {
+                // 父实体
+                tableInfo.setImportPackages(config.getSuperEntityClass());
+            } else {
+                tableInfo.setImportPackages("java.io.Serializable");
+            }
+            ctx.put("package", packageInfo);
+            ctx.put("author", config.getGlobalConfig().getAuthor());
+            ctx.put("activeRecord", config.getGlobalConfig().isActiveRecord());
+            ctx.put("date", date);
+            ctx.put("table", tableInfo);
+            ctx.put("enableCache", config.getGlobalConfig().isEnableCache());
+            ctx.put("baseResultMap", config.getGlobalConfig().isBaseResultMap());
+            ctx.put("baseColumnList", config.getGlobalConfig().isBaseColumnList());
+            ctx.put("entity", tableInfo.getEntityName());
+            ctx.put("entityColumnConstant", config.getStrategyConfig().isEntityColumnConstant());
+            ctx.put("entityBuilderModel", config.getStrategyConfig().isEntityBuilderModel());
+            ctx.put("superEntityClass", superEntityClass);
+            ctx.put("superMapperClassPackage", config.getSuperMapperClass());
+            ctx.put("superMapperClass", superMapperClass);
+            ctx.put("superServiceClassPackage", config.getSuperServiceClass());
+            ctx.put("superServiceClass", superServiceClass);
+            ctx.put("superServiceImplClassPackage", config.getSuperServiceImplClass());
+            ctx.put("superServiceImplClass", superServiceImplClass);
+            ctx.put("superControllerClassPackage", config.getSuperControllerClass());
+            ctx.put("superControllerClass", superControllerClass);
+            ctxData.put(tableInfo.getEntityName(), ctx);
+        }
+        return ctxData;
+    }
 
-	/**
-	 * 获取类名
-	 * 
-	 * @param classPath
-	 * @return
-	 */
-	private String getSuperClassName(String classPath) {
-		if (StringUtils.isEmpty(classPath))
-			return null;
-		return classPath.substring(classPath.lastIndexOf(".") + 1);
-	}
+    /**
+     * 获取类名
+     *
+     * @param classPath
+     * @return
+     */
+    private String getSuperClassName(String classPath) {
+        if (StringUtils.isEmpty(classPath))
+            return null;
+        return classPath.substring(classPath.lastIndexOf(".") + 1);
+    }
 
-	/**
-	 * 处理输出目录
-	 *
-	 * @param pathInfo
-	 *            路径信息
-	 */
-	private void mkdirs(Map<String, String> pathInfo) {
-		for (Map.Entry<String, String> entry : pathInfo.entrySet()) {
-			File dir = new File(entry.getValue());
-			if (!dir.exists()) {
-				boolean result = dir.mkdirs();
-				if (result) {
-					logger.debug("创建目录: [" + entry.getValue() + "]");
-				}
-			}
-		}
-	}
+    /**
+     * 处理输出目录
+     *
+     * @param pathInfo 路径信息
+     */
+    private void mkdirs(Map<String, String> pathInfo) {
+        for (Map.Entry<String, String> entry : pathInfo.entrySet()) {
+            File dir = new File(entry.getValue());
+            if (!dir.exists()) {
+                boolean result = dir.mkdirs();
+                if (result) {
+                    logger.debug("创建目录: [" + entry.getValue() + "]");
+                }
+            }
+        }
+    }
 
-	/**
-	 * 合成上下文与模板
-	 *
-	 * @param context
-	 *            vm上下文
-	 */
-	private void batchOutput(String entityName, VelocityContext context) {
-		try {
-			TableInfo tableInfo = (TableInfo) context.get("table");
-			Map<String, String> pathInfo = config.getPathInfo();
-			String entityFile = String.format((pathInfo.get(ConstVal.ENTITY_PATH) + ConstVal.ENTITY_NAME), entityName);
-			String mapperFile = String.format((pathInfo.get(ConstVal.MAPPER_PATH) + File.separator + tableInfo.getMapperName() + ConstVal.JAVA_SUFFIX), entityName);
-			String xmlFile = String.format((pathInfo.get(ConstVal.XML_PATH) + File.separator + tableInfo.getXmlName() + ConstVal.XML_SUFFIX), entityName);
-			String serviceFile = String.format((pathInfo.get(ConstVal.SERIVCE_PATH) + File.separator + tableInfo.getServiceName() + ConstVal.JAVA_SUFFIX), entityName);
-			String implFile = String.format((pathInfo.get(ConstVal.SERVICEIMPL_PATH) + File.separator + tableInfo.getServiceImplName() + ConstVal.JAVA_SUFFIX), entityName);
-			String controllerFile = String.format((pathInfo.get(ConstVal.CONTROLLER_PATH) + File.separator + tableInfo.getControllerName() + ConstVal.JAVA_SUFFIX), entityName);
+    /**
+     * 合成上下文与模板
+     *
+     * @param context vm上下文
+     */
+    private void batchOutput(String entityName, VelocityContext context) {
+        try {
+            TableInfo tableInfo = (TableInfo) context.get("table");
+            Map<String, String> pathInfo = config.getPathInfo();
+            String entityFile = String.format((pathInfo.get(ConstVal.ENTITY_PATH) + ConstVal.ENTITY_NAME), entityName);
+            String mapperFile = String.format((pathInfo.get(ConstVal.MAPPER_PATH) + File.separator + tableInfo.getMapperName() + ConstVal.JAVA_SUFFIX), entityName);
+            String xmlFile = String.format((pathInfo.get(ConstVal.XML_PATH) + File.separator + tableInfo.getXmlName() + ConstVal.XML_SUFFIX), entityName);
+            String serviceFile = String.format((pathInfo.get(ConstVal.SERIVCE_PATH) + File.separator + tableInfo.getServiceName() + ConstVal.JAVA_SUFFIX), entityName);
+            String implFile = String.format((pathInfo.get(ConstVal.SERVICEIMPL_PATH) + File.separator + tableInfo.getServiceImplName() + ConstVal.JAVA_SUFFIX), entityName);
+            String controllerFile = String.format((pathInfo.get(ConstVal.CONTROLLER_PATH) + File.separator + tableInfo.getControllerName() + ConstVal.JAVA_SUFFIX), entityName);
 
-			TemplateConfig template = config.getTemplate();
+            TemplateConfig template = config.getTemplate();
 
-			// 根据override标识来判断是否需要创建文件
-			if (isCreate(entityFile)) {
-				vmToFile(context, template.getEntity(), entityFile);
-			}
-			if (isCreate(mapperFile)) {
-				vmToFile(context, template.getMapper(), mapperFile);
-			}
-			if (isCreate(xmlFile)) {
-				vmToFile(context, template.getXml(), xmlFile);
-			}
-			if (isCreate(serviceFile)) {
-				vmToFile(context, template.getService(), serviceFile);
-			}
-			if (isCreate(implFile)) {
-				vmToFile(context, template.getServiceImpl(), implFile);
-			}
-			if (isCreate(controllerFile)) {
-				vmToFile(context, template.getController(), controllerFile);
-			}
-			if (injectionConfig != null) {
-				/**
-				 * 输出自定义文件内容
-				 */
-				List<FileOutConfig> focList = injectionConfig.getFileOutConfigList();
-				if (CollectionUtils.isNotEmpty(focList)) {
-					for (FileOutConfig foc : focList) {
-						vmToFile(context, foc.getTemplatePath(), foc.outputFile(tableInfo));
-					}
-				}
-			}
+            // 根据override标识来判断是否需要创建文件
+            if (isCreate(entityFile)) {
+                vmToFile(context, template.getEntity(), entityFile);
+            }
+            if (isCreate(mapperFile)) {
+                vmToFile(context, template.getMapper(), mapperFile);
+            }
+            if (isCreate(xmlFile)) {
+                vmToFile(context, template.getXml(), xmlFile);
+            }
+            if (isCreate(serviceFile)) {
+                vmToFile(context, template.getService(), serviceFile);
+            }
+            if (isCreate(implFile)) {
+                vmToFile(context, template.getServiceImpl(), implFile);
+            }
+            if (isCreate(controllerFile)) {
+                vmToFile(context, template.getController(), controllerFile);
+            }
+            if (injectionConfig != null) {
+                /**
+                 * 输出自定义文件内容
+                 */
+                List<FileOutConfig> focList = injectionConfig.getFileOutConfigList();
+                if (CollectionUtils.isNotEmpty(focList)) {
+                    for (FileOutConfig foc : focList) {
+                        vmToFile(context, foc.getTemplatePath(), foc.outputFile(tableInfo));
+                    }
+                }
+            }
 
-		} catch (IOException e) {
-			logger.error("无法创建文件,请检查配置信息!", e);
-		}
-	}
+        } catch (IOException e) {
+            logger.error("无法创建文件,请检查配置信息!", e);
+        }
+    }
 
-	/**
-	 * 将模板转化成为文件
-	 *
-	 * @param context
-	 *            内容对象
-	 * @param templatePath
-	 *            模板文件
-	 * @param outputFile
-	 *            文件生成的目录
-	 */
-	private void vmToFile(VelocityContext context, String templatePath, String outputFile) throws IOException {
-		if (StringUtils.isEmpty(templatePath)) {
-			return;
-		}
-		VelocityEngine velocity = getVelocityEngine();
-		Template template = velocity.getTemplate(templatePath, ConstVal.UTF8);
-		File file = new File(outputFile);
-		if (!file.getParentFile().exists()) {
-			// 如果文件所在的目录不存在,则创建目录
-			if (!file.getParentFile().mkdirs()) {
-				logger.debug("创建文件所在的目录失败!");
-				return;
-			}
-		}
-		FileOutputStream fos = new FileOutputStream(outputFile);
-		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, ConstVal.UTF8));
-		template.merge(context, writer);
-		writer.close();
-		logger.debug("模板:" + templatePath + ";  文件:" + outputFile);
-	}
+    /**
+     * 将模板转化成为文件
+     *
+     * @param context      内容对象
+     * @param templatePath 模板文件
+     * @param outputFile   文件生成的目录
+     */
+    private void vmToFile(VelocityContext context, String templatePath, String outputFile) throws IOException {
+        if (StringUtils.isEmpty(templatePath)) {
+            return;
+        }
+        VelocityEngine velocity = getVelocityEngine();
+        Template template = velocity.getTemplate(templatePath, ConstVal.UTF8);
+        File file = new File(outputFile);
+        if (!file.getParentFile().exists()) {
+            // 如果文件所在的目录不存在,则创建目录
+            if (!file.getParentFile().mkdirs()) {
+                logger.debug("创建文件所在的目录失败!");
+                return;
+            }
+        }
+        FileOutputStream fos = new FileOutputStream(outputFile);
+        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(fos, ConstVal.UTF8));
+        template.merge(context, writer);
+        writer.close();
+        logger.debug("模板:" + templatePath + ";  文件:" + outputFile);
+    }
 
-	/**
-	 * 设置模版引擎,主要指向获取模版路径
-	 */
-	private VelocityEngine getVelocityEngine() {
-		if (engine == null) {
-			Properties p = new Properties();
-			p.setProperty(ConstVal.VM_LOADPATH_KEY, ConstVal.VM_LOADPATH_VALUE);
-			p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
-			p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
-			p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
-			p.setProperty(Velocity.OUTPUT_ENCODING, ConstVal.UTF8);
-			p.setProperty("file.resource.loader.unicode", "true");
-			engine = new VelocityEngine(p);
-		}
-		return engine;
-	}
+    /**
+     * 设置模版引擎,主要指向获取模版路径
+     */
+    private VelocityEngine getVelocityEngine() {
+        if (engine == null) {
+            Properties p = new Properties();
+            p.setProperty(ConstVal.VM_LOADPATH_KEY, ConstVal.VM_LOADPATH_VALUE);
+            p.setProperty(Velocity.FILE_RESOURCE_LOADER_PATH, "");
+            p.setProperty(Velocity.ENCODING_DEFAULT, ConstVal.UTF8);
+            p.setProperty(Velocity.INPUT_ENCODING, ConstVal.UTF8);
+            p.setProperty(Velocity.OUTPUT_ENCODING, ConstVal.UTF8);
+            p.setProperty("file.resource.loader.unicode", "true");
+            engine = new VelocityEngine(p);
+        }
+        return engine;
+    }
 
-	/**
-	 * 检测文件是否存在
-	 *
-	 * @return 是否
-	 */
-	private boolean isCreate(String filePath) {
-		File file = new File(filePath);
-		return !file.exists() || config.getGlobalConfig().isFileOverride();
-	}
+    /**
+     * 检测文件是否存在
+     *
+     * @return 是否
+     */
+    private boolean isCreate(String filePath) {
+        File file = new File(filePath);
+        return !file.exists() || config.getGlobalConfig().isFileOverride();
+    }
 
 }

+ 34 - 34
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/InjectionConfig.java

@@ -31,48 +31,48 @@ import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
  */
 public abstract class InjectionConfig {
 
-	/**
-	 * 全局配置
-	 */
-	private ConfigBuilder config;
+    /**
+     * 全局配置
+     */
+    private ConfigBuilder config;
 
-	/**
-	 * 自定义返回配置 Map 对象
-	 */
-	private Map<String, Object> map;
+    /**
+     * 自定义返回配置 Map 对象
+     */
+    private Map<String, Object> map;
 
-	/**
-	 * 自定义输出文件
-	 */
-	private List<FileOutConfig> fileOutConfigList;
+    /**
+     * 自定义输出文件
+     */
+    private List<FileOutConfig> fileOutConfigList;
 
-	/**
-	 * 注入自定义 Map 对象
-	 */
-	public abstract void initMap();
+    /**
+     * 注入自定义 Map 对象
+     */
+    public abstract void initMap();
 
-	public ConfigBuilder getConfig() {
-		return config;
-	}
+    public ConfigBuilder getConfig() {
+        return config;
+    }
 
-	public void setConfig(ConfigBuilder config) {
-		this.config = config;
-	}
+    public void setConfig(ConfigBuilder config) {
+        this.config = config;
+    }
 
-	public Map<String, Object> getMap() {
-		return map;
-	}
+    public Map<String, Object> getMap() {
+        return map;
+    }
 
-	public void setMap(Map<String, Object> map) {
-		this.map = map;
-	}
+    public void setMap(Map<String, Object> map) {
+        this.map = map;
+    }
 
-	public List<FileOutConfig> getFileOutConfigList() {
-		return fileOutConfigList;
-	}
+    public List<FileOutConfig> getFileOutConfigList() {
+        return fileOutConfigList;
+    }
 
-	public void setFileOutConfigList(List<FileOutConfig> fileOutConfigList) {
-		this.fileOutConfigList = fileOutConfigList;
-	}
+    public void setFileOutConfigList(List<FileOutConfig> fileOutConfigList) {
+        this.fileOutConfigList = fileOutConfigList;
+    }
 
 }

+ 34 - 34
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/ConstVal.java

@@ -25,45 +25,45 @@ import java.nio.charset.Charset;
  * @since 2016/8/31
  */
 public class ConstVal {
-	
-	public static final String MODULENAME = "ModuleName";
-	
-	public static final String ENTITY = "Entity";
-	public static final String SERIVCE = "Service";
-	public static final String SERVICEIMPL = "ServiceImpl";
-	public static final String MAPPER = "Mapper";
-	public static final String XML = "Xml";
-	public static final String CONTROLLER = "Controller";
 
-	public static final String ENTITY_PATH = "entity_path";
-	public static final String SERIVCE_PATH = "serivce_path";
-	public static final String SERVICEIMPL_PATH = "serviceimpl_path";
-	public static final String MAPPER_PATH = "mapper_path";
-	public static final String XML_PATH = "xml_path";
-	public static final String CONTROLLER_PATH = "controller_path";
+    public static final String MODULENAME = "ModuleName";
 
-	public static final String JAVA_TMPDIR = "java.io.tmpdir";
-	public static final String UTF8 = Charset.forName("UTF-8").name();
-	public static final String UNDERLINE = "_";
+    public static final String ENTITY = "Entity";
+    public static final String SERIVCE = "Service";
+    public static final String SERVICEIMPL = "ServiceImpl";
+    public static final String MAPPER = "Mapper";
+    public static final String XML = "Xml";
+    public static final String CONTROLLER = "Controller";
 
-	public static final String JAVA_SUFFIX = ".java";
-	public static final String XML_SUFFIX = ".xml";
+    public static final String ENTITY_PATH = "entity_path";
+    public static final String SERIVCE_PATH = "serivce_path";
+    public static final String SERVICEIMPL_PATH = "serviceimpl_path";
+    public static final String MAPPER_PATH = "mapper_path";
+    public static final String XML_PATH = "xml_path";
+    public static final String CONTROLLER_PATH = "controller_path";
 
-	public static final String TEMPLATE_ENTITY = "/templates/entity.java.vm";
-	public static final String TEMPLATE_MAPPER = "/templates/mapper.java.vm";
-	public static final String TEMPLATE_XML = "/templates/mapper.xml.vm";
-	public static final String TEMPLATE_SERVICE = "/templates/service.java.vm";
-	public static final String TEMPLATE_SERVICEIMPL = "/templates/serviceImpl.java.vm";
-	public static final String TEMPLATE_CONTROLLER = "/templates/controller.java.vm";
+    public static final String JAVA_TMPDIR = "java.io.tmpdir";
+    public static final String UTF8 = Charset.forName("UTF-8").name();
+    public static final String UNDERLINE = "_";
 
-	public static final String ENTITY_NAME = File.separator + "%s" + JAVA_SUFFIX;
+    public static final String JAVA_SUFFIX = ".java";
+    public static final String XML_SUFFIX = ".xml";
 
-	// 配置使用classloader加载资源
-	public static final String VM_LOADPATH_KEY = "file.resource.loader.class";
-	public static final String VM_LOADPATH_VALUE = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
+    public static final String TEMPLATE_ENTITY = "/templates/entity.java.vm";
+    public static final String TEMPLATE_MAPPER = "/templates/mapper.java.vm";
+    public static final String TEMPLATE_XML = "/templates/mapper.xml.vm";
+    public static final String TEMPLATE_SERVICE = "/templates/service.java.vm";
+    public static final String TEMPLATE_SERVICEIMPL = "/templates/serviceImpl.java.vm";
+    public static final String TEMPLATE_CONTROLLER = "/templates/controller.java.vm";
+
+    public static final String ENTITY_NAME = File.separator + "%s" + JAVA_SUFFIX;
+
+    // 配置使用classloader加载资源
+    public static final String VM_LOADPATH_KEY = "file.resource.loader.class";
+    public static final String VM_LOADPATH_VALUE = "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader";
+
+    public static final String SUPERD_MAPPER_CLASS = "com.baomidou.mybatisplus.mapper.BaseMapper";
+    public static final String SUPERD_SERVICE_CLASS = "com.baomidou.mybatisplus.service.IService";
+    public static final String SUPERD_SERVICEIMPL_CLASS = "com.baomidou.mybatisplus.service.impl.ServiceImpl";
 
-	public static final String SUPERD_MAPPER_CLASS = "com.baomidou.mybatisplus.mapper.BaseMapper";
-	public static final String SUPERD_SERVICE_CLASS = "com.baomidou.mybatisplus.service.IService";
-	public static final String SUPERD_SERVICEIMPL_CLASS = "com.baomidou.mybatisplus.service.impl.ServiceImpl";
-	
 }

+ 121 - 123
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/DataSourceConfig.java

@@ -36,128 +36,126 @@ import com.baomidou.mybatisplus.generator.config.rules.DbType;
  */
 public class DataSourceConfig {
 
-	/**
-	 * 数据库类型
-	 */
-	private DbType dbType;
-	/**
-	 * 类型转换
-	 */
-	private ITypeConvert typeConvert;
-	/**
-	 * 驱动连接的URL
-	 */
-	private String url;
-	/**
-	 * 驱动名称
-	 */
-	private String driverName;
-	/**
-	 * 数据库连接用户名
-	 */
-	private String username;
-	/**
-	 * 数据库连接密码
-	 */
-	private String password;
-
-	/**
-	 * 判断数据库类型
-	 *
-	 * @return 类型枚举值
-	 */
-	public DbType getDbType() {
-		if (null == dbType) {
-			if (driverName.contains("mysql")) {
-				dbType = DbType.MYSQL;
-			} else if (driverName.contains("oracle")) {
-				dbType = DbType.ORACLE;
-			} else if (driverName.contains("postgresql")) {
-				dbType = DbType.POSTGRE_SQL;
-			} else {
-				throw new MybatisPlusException("Unknown type of database!");
-			}
-		}
-		return dbType;
-	}
-
-	public void setDbType(DbType dbType) {
-		this.dbType = dbType;
-	}
-
-	public ITypeConvert getTypeConvert() {
-		if (null == typeConvert) {
-			switch (getDbType()) {
-			case ORACLE:
-				typeConvert = new OracleTypeConvert();
-				break;
-			case SQL_SERVER:
-				typeConvert = new SqlServerTypeConvert();
-				break;
-			case POSTGRE_SQL:
-				typeConvert = new PostgreSqlTypeConvert();
-				break;
-			default:
-				// 默认 MYSQL
-				typeConvert = new MySqlTypeConvert();
-				break;
-			}
-		}
-		return typeConvert;
-	}
-
-	public void setTypeConvert(ITypeConvert typeConvert) {
-		this.typeConvert = typeConvert;
-	}
-
-	/**
-	 * 创建数据库连接对象
-	 *
-	 * @return Connection
-	 */
-	public Connection getConn() {
-		Connection conn = null;
-		try {
-			Class.forName(driverName);
-			conn = DriverManager.getConnection(url, username, password);
-		} catch (ClassNotFoundException e) {
-			e.printStackTrace();
-		} catch (SQLException e) {
-			e.printStackTrace();
-		}
-		return conn;
-	}
-
-	public String getUrl() {
-		return url;
-	}
-
-	public void setUrl(String url) {
-		this.url = url;
-	}
-
-	public String getDriverName() {
-		return driverName;
-	}
-
-	public void setDriverName(String driverName) {
-		this.driverName = driverName;
-	}
-
-	public String getUsername() {
-		return username;
-	}
-
-	public void setUsername(String username) {
-		this.username = username;
-	}
-
-	public String getPassword() {
-		return password;
-	}
-
-	public void setPassword(String password) {
-		this.password = password;
-	}
+    /**
+     * 数据库类型
+     */
+    private DbType dbType;
+    /**
+     * 类型转换
+     */
+    private ITypeConvert typeConvert;
+    /**
+     * 驱动连接的URL
+     */
+    private String url;
+    /**
+     * 驱动名称
+     */
+    private String driverName;
+    /**
+     * 数据库连接用户名
+     */
+    private String username;
+    /**
+     * 数据库连接密码
+     */
+    private String password;
+
+    /**
+     * 判断数据库类型
+     *
+     * @return 类型枚举值
+     */
+    public DbType getDbType() {
+        if (null == dbType) {
+            if (driverName.contains("mysql")) {
+                dbType = DbType.MYSQL;
+            } else if (driverName.contains("oracle")) {
+                dbType = DbType.ORACLE;
+            } else if (driverName.contains("postgresql")) {
+                dbType = DbType.POSTGRE_SQL;
+            } else {
+                throw new MybatisPlusException("Unknown type of database!");
+            }
+        }
+        return dbType;
+    }
+
+    public void setDbType(DbType dbType) {
+        this.dbType = dbType;
+    }
+
+    public ITypeConvert getTypeConvert() {
+        if (null == typeConvert) {
+            switch (getDbType()) {
+                case ORACLE:
+                    typeConvert = new OracleTypeConvert();
+                    break;
+                case SQL_SERVER:
+                    typeConvert = new SqlServerTypeConvert();
+                    break;
+                case POSTGRE_SQL:
+                    typeConvert = new PostgreSqlTypeConvert();
+                    break;
+                default:
+                    // 默认 MYSQL
+                    typeConvert = new MySqlTypeConvert();
+                    break;
+            }
+        }
+        return typeConvert;
+    }
+
+    public void setTypeConvert(ITypeConvert typeConvert) {
+        this.typeConvert = typeConvert;
+    }
+
+    /**
+     * 创建数据库连接对象
+     *
+     * @return Connection
+     */
+    public Connection getConn() {
+        Connection conn = null;
+        try {
+            Class.forName(driverName);
+            conn = DriverManager.getConnection(url, username, password);
+        } catch (ClassNotFoundException | SQLException e) {
+            e.printStackTrace();
+        }
+        return conn;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getDriverName() {
+        return driverName;
+    }
+
+    public void setDriverName(String driverName) {
+        this.driverName = driverName;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
 
 }

+ 20 - 19
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/FileOutConfig.java

@@ -26,30 +26,31 @@ import com.baomidou.mybatisplus.generator.config.po.TableInfo;
  * @since 2017-01-18
  */
 public abstract class FileOutConfig {
-	/**
-	 * 模板
-	 */
-	private String templatePath;
 
-	/**
-	 * 输出文件
-	 */
-	public abstract String outputFile(TableInfo tableInfo);
+    /**
+     * 模板
+     */
+    private String templatePath;
 
-	public FileOutConfig() {
+    public FileOutConfig() {
 
-	}
+    }
 
-	public FileOutConfig(String templatePath) {
-		this.templatePath = templatePath;
-	}
+    public FileOutConfig(String templatePath) {
+        this.templatePath = templatePath;
+    }
 
-	public String getTemplatePath() {
-		return templatePath;
-	}
+    /**
+     * 输出文件
+     */
+    public abstract String outputFile(TableInfo tableInfo);
 
-	public void setTemplatePath(String templatePath) {
-		this.templatePath = templatePath;
-	}
+    public String getTemplatePath() {
+        return templatePath;
+    }
+
+    public void setTemplatePath(String templatePath) {
+        this.templatePath = templatePath;
+    }
 
 }

+ 151 - 150
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/GlobalConfig.java

@@ -24,156 +24,157 @@ package com.baomidou.mybatisplus.generator.config;
  * @since 2016-12-02
  */
 public class GlobalConfig {
-	/**
-	 * 生成文件的输出目录【默认 D 盘根目录】
-	 */
-	private String outputDir = "D://";
-
-	/**
-	 * 是否覆盖已有文件
-	 */
-	private boolean fileOverride = false;
-
-	/**
-	 * 是否打开输出目录
-	 */
-	private boolean open = true;
-
-	/**
-	 * 是否在xml中添加二级缓存配置
-	 */
-	private boolean enableCache = true;
-
-	/**
-	 * 开发人员
-	 */
-	private String author;
-
-	/**
-	 * 开启 ActiveRecord 模式
-	 */
-	private boolean activeRecord = true;
-
-	/**
-	 * 开启 BaseResultMap
-	 */
-	private boolean baseResultMap = false;
-
-	/**
-	 * 开启 baseColumnList
-	 */
-	private boolean baseColumnList = false;
-	/**
-	 * 各层文件名称方式,例如: %Action 生成 UserAction
-	 */
-	private String mapperName;
-	private String xmlName;
-	private String serviceName;
-	private String serviceImplName;
-	private String controllerName;
-
-	public String getOutputDir() {
-		return outputDir;
-	}
-
-	public void setOutputDir(String outputDir) {
-		this.outputDir = outputDir;
-	}
-
-	public boolean isFileOverride() {
-		return fileOverride;
-	}
-
-	public void setFileOverride(boolean fileOverride) {
-		this.fileOverride = fileOverride;
-	}
-
-	public boolean isOpen() {
-		return open;
-	}
-
-	public void setOpen(boolean open) {
-		this.open = open;
-	}
-
-	public boolean isEnableCache() {
-		return enableCache;
-	}
-
-	public void setEnableCache(boolean enableCache) {
-		this.enableCache = enableCache;
-	}
-
-	public String getAuthor() {
-		return author;
-	}
-
-	public void setAuthor(String author) {
-		this.author = author;
-	}
-
-	public boolean isActiveRecord() {
-		return activeRecord;
-	}
-
-	public void setActiveRecord(boolean activeRecord) {
-		this.activeRecord = activeRecord;
-	}
-
-	public boolean isBaseResultMap() {
-		return baseResultMap;
-	}
-
-	public void setBaseResultMap(boolean baseResultMap) {
-		this.baseResultMap = baseResultMap;
-	}
-
-	public boolean isBaseColumnList() {
-		return baseColumnList;
-	}
-
-	public void setBaseColumnList(boolean baseColumnList) {
-		this.baseColumnList = baseColumnList;
-	}
-
-	public String getMapperName() {
-		return mapperName;
-	}
-
-	public void setMapperName(String mapperName) {
-		this.mapperName = mapperName;
-	}
-
-	public String getXmlName() {
-		return xmlName;
-	}
-
-	public void setXmlName(String xmlName) {
-		this.xmlName = xmlName;
-	}
-
-	public String getServiceName() {
-		return serviceName;
-	}
-
-	public void setServiceName(String serviceName) {
-		this.serviceName = serviceName;
-	}
-
-	public String getServiceImplName() {
-		return serviceImplName;
-	}
-
-	public void setServiceImplName(String serviceImplName) {
-		this.serviceImplName = serviceImplName;
-	}
-
-	public String getControllerName() {
-		return controllerName;
-	}
 
-	public void setControllerName(String controllerName) {
-		this.controllerName = controllerName;
-	}
+    /**
+     * 生成文件的输出目录【默认 D 盘根目录】
+     */
+    private String outputDir = "D://";
+
+    /**
+     * 是否覆盖已有文件
+     */
+    private boolean fileOverride = false;
+
+    /**
+     * 是否打开输出目录
+     */
+    private boolean open = true;
+
+    /**
+     * 是否在xml中添加二级缓存配置
+     */
+    private boolean enableCache = true;
+
+    /**
+     * 开发人员
+     */
+    private String author;
+
+    /**
+     * 开启 ActiveRecord 模式
+     */
+    private boolean activeRecord = true;
+
+    /**
+     * 开启 BaseResultMap
+     */
+    private boolean baseResultMap = false;
+
+    /**
+     * 开启 baseColumnList
+     */
+    private boolean baseColumnList = false;
+    /**
+     * 各层文件名称方式,例如: %Action 生成 UserAction
+     */
+    private String mapperName;
+    private String xmlName;
+    private String serviceName;
+    private String serviceImplName;
+    private String controllerName;
+
+    public String getOutputDir() {
+        return outputDir;
+    }
+
+    public void setOutputDir(String outputDir) {
+        this.outputDir = outputDir;
+    }
+
+    public boolean isFileOverride() {
+        return fileOverride;
+    }
+
+    public void setFileOverride(boolean fileOverride) {
+        this.fileOverride = fileOverride;
+    }
+
+    public boolean isOpen() {
+        return open;
+    }
+
+    public void setOpen(boolean open) {
+        this.open = open;
+    }
+
+    public boolean isEnableCache() {
+        return enableCache;
+    }
+
+    public void setEnableCache(boolean enableCache) {
+        this.enableCache = enableCache;
+    }
+
+    public String getAuthor() {
+        return author;
+    }
+
+    public void setAuthor(String author) {
+        this.author = author;
+    }
+
+    public boolean isActiveRecord() {
+        return activeRecord;
+    }
+
+    public void setActiveRecord(boolean activeRecord) {
+        this.activeRecord = activeRecord;
+    }
+
+    public boolean isBaseResultMap() {
+        return baseResultMap;
+    }
+
+    public void setBaseResultMap(boolean baseResultMap) {
+        this.baseResultMap = baseResultMap;
+    }
+
+    public boolean isBaseColumnList() {
+        return baseColumnList;
+    }
+
+    public void setBaseColumnList(boolean baseColumnList) {
+        this.baseColumnList = baseColumnList;
+    }
+
+    public String getMapperName() {
+        return mapperName;
+    }
+
+    public void setMapperName(String mapperName) {
+        this.mapperName = mapperName;
+    }
+
+    public String getXmlName() {
+        return xmlName;
+    }
+
+    public void setXmlName(String xmlName) {
+        this.xmlName = xmlName;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getServiceImplName() {
+        return serviceImplName;
+    }
+
+    public void setServiceImplName(String serviceImplName) {
+        this.serviceImplName = serviceImplName;
+    }
+
+    public String getControllerName() {
+        return controllerName;
+    }
+
+    public void setControllerName(String controllerName) {
+        this.controllerName = controllerName;
+    }
 
 }

+ 13 - 13
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/ITypeConvert.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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
@@ -27,15 +27,15 @@ import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
  */
 public interface ITypeConvert {
 
-	/**
-	 * <p>
-	 * 执行类型转换
-	 * </p>
-	 * 
-	 * @param fieldType
-	 *            字段类型
-	 * @return
-	 */
-	DbColumnType processTypeConvert(String fieldType);
+    /**
+     * <p>
+     * 执行类型转换
+     * </p>
+     *
+     * @param fieldType
+     *            字段类型
+     * @return
+     */
+    DbColumnType processTypeConvert(String fieldType);
 
 }

+ 108 - 108
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/PackageConfig.java

@@ -26,113 +26,113 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  */
 public class PackageConfig {
 
-	/**
-	 * 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
-	 */
-	private String parent = "com.baomidou";
-
-	/**
-	 * 父包模块名。
-	 */
-	private String moduleName = null;
-
-	/**
-	 * Entity包名
-	 */
-	private String entity = "entity";
-
-	/**
-	 * Service包名
-	 */
-	private String service = "service";
-
-	/**
-	 * Service Impl包名
-	 */
-	private String serviceImpl = "service.impl";
-	/**
-	 * Mapper包名
-	 */
-	private String mapper = "mapper";
-
-	/**
-	 * Mapper XML包名
-	 */
-	private String xml = "mapper.xml";
-
-	/**
-	 * Controller包名
-	 */
-	private String controller = "web";
-
-	public String getParent() {
-		if (StringUtils.isNotEmpty(moduleName)) {
-			return parent + "." + moduleName;
-		}
-		return parent;
-	}
-
-	public String getModuleName() {
-		return moduleName;
-	}
-
-	public void setModuleName(String moduleName) {
-		this.moduleName = moduleName;
-	}
-
-	public String getEntity() {
-		return entity;
-	}
-
-	public void setEntity(String entity) {
-		this.entity = entity;
-	}
-
-	public String getService() {
-		return service;
-	}
-
-	public void setService(String service) {
-		this.service = service;
-	}
-
-	public String getServiceImpl() {
-		return serviceImpl;
-	}
-
-	public void setServiceImpl(String serviceImpl) {
-		this.serviceImpl = serviceImpl;
-	}
-
-	public String getMapper() {
-		return mapper;
-	}
-
-	public void setMapper(String mapper) {
-		this.mapper = mapper;
-	}
-
-	public String getXml() {
-		return xml;
-	}
-
-	public void setXml(String xml) {
-		this.xml = xml;
-	}
-
-	public void setParent(String parent) {
-		this.parent = parent;
-	}
-
-	public String getController() {
-		if (StringUtils.isEmpty(controller)) {
-			return "web";
-		}
-		return controller;
-	}
-
-	public void setController(String controller) {
-		this.controller = controller;
-	}
+    /**
+     * 父包名。如果为空,将下面子包名必须写全部, 否则就只需写子包名
+     */
+    private String parent = "com.baomidou";
+
+    /**
+     * 父包模块名。
+     */
+    private String moduleName = null;
+
+    /**
+     * Entity包名
+     */
+    private String entity = "entity";
+
+    /**
+     * Service包名
+     */
+    private String service = "service";
+
+    /**
+     * Service Impl包名
+     */
+    private String serviceImpl = "service.impl";
+    /**
+     * Mapper包名
+     */
+    private String mapper = "mapper";
+
+    /**
+     * Mapper XML包名
+     */
+    private String xml = "mapper.xml";
+
+    /**
+     * Controller包名
+     */
+    private String controller = "web";
+
+    public String getParent() {
+        if (StringUtils.isNotEmpty(moduleName)) {
+            return parent + "." + moduleName;
+        }
+        return parent;
+    }
+
+    public void setParent(String parent) {
+        this.parent = parent;
+    }
+
+    public String getModuleName() {
+        return moduleName;
+    }
+
+    public void setModuleName(String moduleName) {
+        this.moduleName = moduleName;
+    }
+
+    public String getEntity() {
+        return entity;
+    }
+
+    public void setEntity(String entity) {
+        this.entity = entity;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    public void setService(String service) {
+        this.service = service;
+    }
+
+    public String getServiceImpl() {
+        return serviceImpl;
+    }
+
+    public void setServiceImpl(String serviceImpl) {
+        this.serviceImpl = serviceImpl;
+    }
+
+    public String getMapper() {
+        return mapper;
+    }
+
+    public void setMapper(String mapper) {
+        this.mapper = mapper;
+    }
+
+    public String getXml() {
+        return xml;
+    }
+
+    public void setXml(String xml) {
+        this.xml = xml;
+    }
+
+    public String getController() {
+        if (StringUtils.isEmpty(controller)) {
+            return "web";
+        }
+        return controller;
+    }
+
+    public void setController(String controller) {
+        this.controller = controller;
+    }
 
 }

+ 225 - 227
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/StrategyConfig.java

@@ -28,231 +28,229 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  */
 public class StrategyConfig {
 
-	/**
-	 * 表名、字段名、是否使用下划线命名(默认 false)
-	 */
-	public static boolean DB_COLUMN_UNDERLINE = false;
-
-	/**
-	 * 是否大写命名
-	 */
-	private boolean isCapitalMode = false;
-
-	/**
-	 * 数据库表映射到实体的命名策略
-	 */
-	private NamingStrategy naming = NamingStrategy.nochange;
-
-	/**
-	 * 表前缀
-	 */
-	private String[] tablePrefix;
-
-	/**
-	 * 自定义继承的Entity类全称,带包名
-	 */
-	private String superEntityClass;
-
-	/**
-	 * 自定义基础的Entity类,公共字段
-	 */
-	private String[] superEntityColumns;
-
-	/**
-	 * 自定义继承的Mapper类全称,带包名
-	 */
-	private String superMapperClass = ConstVal.SUPERD_MAPPER_CLASS;
-
-	/**
-	 * 自定义继承的Service类全称,带包名
-	 */
-	private String superServiceClass = ConstVal.SUPERD_SERVICE_CLASS;
-
-	/**
-	 * 自定义继承的ServiceImpl类全称,带包名
-	 */
-	private String superServiceImplClass = ConstVal.SUPERD_SERVICEIMPL_CLASS;
-
-	/**
-	 * 自定义继承的Controller类全称,带包名
-	 */
-	private String superControllerClass;
-
-	/*
-	 * 需要包含的表名(与exclude二选一配置)
-	 */
-	private String[] include = null;
-
-	/**
-	 * 需要排除的表名
-	 */
-	private String[] exclude = null;
-	/**
-	 * 【实体】是否生成字段常量(默认 false)<br>
-	 * -----------------------------------<br>
-	 * public static final String ID = "test_id";
-	 */
-	private boolean entityColumnConstant = false;
-
-	/**
-	 * 【实体】是否为构建者模型(默认 false)<br>
-	 * -----------------------------------<br>
-	 * public User setName(String name) { this.name = name; return this; }
-	 */
-	private boolean entityBuilderModel = false;
-
-	public void setDbColumnUnderline(boolean dbColumnUnderline) {
-		DB_COLUMN_UNDERLINE = dbColumnUnderline;
-	}
-
-	/**
-	 * <p>
-	 * 大写命名、字段符合大写字母数字下划线命名
-	 * </p>
-	 * 
-	 * @param word
-	 *            待判断字符串
-	 * @return
-	 */
-	public boolean isCapitalModeNaming(String word) {
-		return isCapitalMode && StringUtils.isCapitalMode(word);
-	}
-
-	/**
-	 * <p>
-	 * 表名称包含指定前缀
-	 * </p>
-	 * 
-	 * @param tableName
-	 *            表名称
-	 * @return
-	 */
-	public boolean containsTablePrefix(String tableName) {
-		if (null != tableName) {
-			String[] tps = getTablePrefix();
-			if (null != tps) {
-				for (String tp : tps) {
-					if (tableName.contains(tp)) {
-						return true;
-					}
-				}
-			}
-		}
-		return false;
-	}
-
-	public boolean isCapitalMode() {
-		return isCapitalMode;
-	}
-
-	public void setCapitalMode(boolean isCapitalMode) {
-		this.isCapitalMode = isCapitalMode;
-	}
-
-	public NamingStrategy getNaming() {
-		return naming;
-	}
-
-	public void setNaming(NamingStrategy naming) {
-		this.naming = naming;
-	}
-
-	public String[] getTablePrefix() {
-		return tablePrefix;
-	}
-
-	public void setTablePrefix(String[] tablePrefix) {
-		this.tablePrefix = tablePrefix;
-	}
-
-	public String getSuperEntityClass() {
-		return superEntityClass;
-	}
-
-	public void setSuperEntityClass(String superEntityClass) {
-		this.superEntityClass = superEntityClass;
-	}
-
-	public boolean includeSuperEntityColumns(String fieldName) {
-		if (null != superEntityColumns) {
-			for (String column : superEntityColumns) {
-				if (column.contains(fieldName)) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
-	public String[] getSuperEntityColumns() {
-		return superEntityColumns;
-	}
-
-	public void setSuperEntityColumns(String[] superEntityColumns) {
-		this.superEntityColumns = superEntityColumns;
-	}
-
-	public String getSuperMapperClass() {
-		return superMapperClass;
-	}
-
-	public void setSuperMapperClass(String superMapperClass) {
-		this.superMapperClass = superMapperClass;
-	}
-
-	public String getSuperServiceClass() {
-		return superServiceClass;
-	}
-
-	public void setSuperServiceClass(String superServiceClass) {
-		this.superServiceClass = superServiceClass;
-	}
-
-	public String getSuperServiceImplClass() {
-		return superServiceImplClass;
-	}
-
-	public void setSuperServiceImplClass(String superServiceImplClass) {
-		this.superServiceImplClass = superServiceImplClass;
-	}
-
-	public String getSuperControllerClass() {
-		return superControllerClass;
-	}
-
-	public void setSuperControllerClass(String superControllerClass) {
-		this.superControllerClass = superControllerClass;
-	}
-
-	public String[] getInclude() {
-		return include;
-	}
-
-	public void setInclude(String[] include) {
-		this.include = include;
-	}
-
-	public String[] getExclude() {
-		return exclude;
-	}
-
-	public void setExclude(String[] exclude) {
-		this.exclude = exclude;
-	}
-
-	public boolean isEntityColumnConstant() {
-		return entityColumnConstant;
-	}
-
-	public void setEntityColumnConstant(boolean entityColumnConstant) {
-		this.entityColumnConstant = entityColumnConstant;
-	}
-
-	public boolean isEntityBuilderModel() {
-		return entityBuilderModel;
-	}
-
-	public void setEntityBuilderModel(boolean entityBuilderModel) {
-		this.entityBuilderModel = entityBuilderModel;
-	}
+    /**
+     * 表名、字段名、是否使用下划线命名(默认 false)
+     */
+    public static boolean DB_COLUMN_UNDERLINE = false;
+
+    /**
+     * 是否大写命名
+     */
+    private boolean isCapitalMode = false;
+
+    /**
+     * 数据库表映射到实体的命名策略
+     */
+    private NamingStrategy naming = NamingStrategy.nochange;
+
+    /**
+     * 表前缀
+     */
+    private String[] tablePrefix;
+
+    /**
+     * 自定义继承的Entity类全称,带包名
+     */
+    private String superEntityClass;
+
+    /**
+     * 自定义基础的Entity类,公共字段
+     */
+    private String[] superEntityColumns;
+
+    /**
+     * 自定义继承的Mapper类全称,带包名
+     */
+    private String superMapperClass = ConstVal.SUPERD_MAPPER_CLASS;
+
+    /**
+     * 自定义继承的Service类全称,带包名
+     */
+    private String superServiceClass = ConstVal.SUPERD_SERVICE_CLASS;
+
+    /**
+     * 自定义继承的ServiceImpl类全称,带包名
+     */
+    private String superServiceImplClass = ConstVal.SUPERD_SERVICEIMPL_CLASS;
+
+    /**
+     * 自定义继承的Controller类全称,带包名
+     */
+    private String superControllerClass;
+
+    /*
+     * 需要包含的表名(与exclude二选一配置)
+     */
+    private String[] include = null;
+
+    /**
+     * 需要排除的表名
+     */
+    private String[] exclude = null;
+    /**
+     * 【实体】是否生成字段常量(默认 false)<br>
+     * -----------------------------------<br>
+     * public static final String ID = "test_id";
+     */
+    private boolean entityColumnConstant = false;
+
+    /**
+     * 【实体】是否为构建者模型(默认 false)<br>
+     * -----------------------------------<br>
+     * public User setName(String name) { this.name = name; return this; }
+     */
+    private boolean entityBuilderModel = false;
+
+    public void setDbColumnUnderline(boolean dbColumnUnderline) {
+        DB_COLUMN_UNDERLINE = dbColumnUnderline;
+    }
+
+    /**
+     * <p>
+     * 大写命名、字段符合大写字母数字下划线命名
+     * </p>
+     *
+     * @param word 待判断字符串
+     * @return
+     */
+    public boolean isCapitalModeNaming(String word) {
+        return isCapitalMode && StringUtils.isCapitalMode(word);
+    }
+
+    /**
+     * <p>
+     * 表名称包含指定前缀
+     * </p>
+     *
+     * @param tableName 表名称
+     * @return
+     */
+    public boolean containsTablePrefix(String tableName) {
+        if (null != tableName) {
+            String[] tps = getTablePrefix();
+            if (null != tps) {
+                for (String tp : tps) {
+                    if (tableName.contains(tp)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
+    public boolean isCapitalMode() {
+        return isCapitalMode;
+    }
+
+    public void setCapitalMode(boolean isCapitalMode) {
+        this.isCapitalMode = isCapitalMode;
+    }
+
+    public NamingStrategy getNaming() {
+        return naming;
+    }
+
+    public void setNaming(NamingStrategy naming) {
+        this.naming = naming;
+    }
+
+    public String[] getTablePrefix() {
+        return tablePrefix;
+    }
+
+    public void setTablePrefix(String[] tablePrefix) {
+        this.tablePrefix = tablePrefix;
+    }
+
+    public String getSuperEntityClass() {
+        return superEntityClass;
+    }
+
+    public void setSuperEntityClass(String superEntityClass) {
+        this.superEntityClass = superEntityClass;
+    }
+
+    public boolean includeSuperEntityColumns(String fieldName) {
+        if (null != superEntityColumns) {
+            for (String column : superEntityColumns) {
+                if (column.contains(fieldName)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    public String[] getSuperEntityColumns() {
+        return superEntityColumns;
+    }
+
+    public void setSuperEntityColumns(String[] superEntityColumns) {
+        this.superEntityColumns = superEntityColumns;
+    }
+
+    public String getSuperMapperClass() {
+        return superMapperClass;
+    }
+
+    public void setSuperMapperClass(String superMapperClass) {
+        this.superMapperClass = superMapperClass;
+    }
+
+    public String getSuperServiceClass() {
+        return superServiceClass;
+    }
+
+    public void setSuperServiceClass(String superServiceClass) {
+        this.superServiceClass = superServiceClass;
+    }
+
+    public String getSuperServiceImplClass() {
+        return superServiceImplClass;
+    }
+
+    public void setSuperServiceImplClass(String superServiceImplClass) {
+        this.superServiceImplClass = superServiceImplClass;
+    }
+
+    public String getSuperControllerClass() {
+        return superControllerClass;
+    }
+
+    public void setSuperControllerClass(String superControllerClass) {
+        this.superControllerClass = superControllerClass;
+    }
+
+    public String[] getInclude() {
+        return include;
+    }
+
+    public void setInclude(String[] include) {
+        this.include = include;
+    }
+
+    public String[] getExclude() {
+        return exclude;
+    }
+
+    public void setExclude(String[] exclude) {
+        this.exclude = exclude;
+    }
+
+    public boolean isEntityColumnConstant() {
+        return entityColumnConstant;
+    }
+
+    public void setEntityColumnConstant(boolean entityColumnConstant) {
+        this.entityColumnConstant = entityColumnConstant;
+    }
+
+    public boolean isEntityBuilderModel() {
+        return entityBuilderModel;
+    }
+
+    public void setEntityBuilderModel(boolean entityBuilderModel) {
+        this.entityBuilderModel = entityBuilderModel;
+    }
 }

+ 44 - 44
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/TemplateConfig.java

@@ -19,70 +19,70 @@ package com.baomidou.mybatisplus.generator.config;
  * <p>
  * 模板路径配置项
  * </p>
- * 
+ *
  * @author tzg
-  *@since 2016/11/10
+ * @since 2016/11/10
  */
 public class TemplateConfig {
 
-	private String entity = ConstVal.TEMPLATE_ENTITY;
+    private String entity = ConstVal.TEMPLATE_ENTITY;
 
-	private String service = ConstVal.TEMPLATE_SERVICE;
+    private String service = ConstVal.TEMPLATE_SERVICE;
 
-	private String serviceImpl = ConstVal.TEMPLATE_SERVICEIMPL;
+    private String serviceImpl = ConstVal.TEMPLATE_SERVICEIMPL;
 
-	private String mapper = ConstVal.TEMPLATE_MAPPER;
+    private String mapper = ConstVal.TEMPLATE_MAPPER;
 
-	private String xml = ConstVal.TEMPLATE_XML;
+    private String xml = ConstVal.TEMPLATE_XML;
 
-	private String controller = ConstVal.TEMPLATE_CONTROLLER;
+    private String controller = ConstVal.TEMPLATE_CONTROLLER;
 
-	public String getEntity() {
-		return entity;
-	}
+    public String getEntity() {
+        return entity;
+    }
 
-	public void setEntity(String entity) {
-		this.entity = entity;
-	}
+    public void setEntity(String entity) {
+        this.entity = entity;
+    }
 
-	public String getService() {
-		return service;
-	}
+    public String getService() {
+        return service;
+    }
 
-	public void setService(String service) {
-		this.service = service;
-	}
+    public void setService(String service) {
+        this.service = service;
+    }
 
-	public String getServiceImpl() {
-		return serviceImpl;
-	}
+    public String getServiceImpl() {
+        return serviceImpl;
+    }
 
-	public void setServiceImpl(String serviceImpl) {
-		this.serviceImpl = serviceImpl;
-	}
+    public void setServiceImpl(String serviceImpl) {
+        this.serviceImpl = serviceImpl;
+    }
 
-	public String getMapper() {
-		return mapper;
-	}
+    public String getMapper() {
+        return mapper;
+    }
 
-	public void setMapper(String mapper) {
-		this.mapper = mapper;
-	}
+    public void setMapper(String mapper) {
+        this.mapper = mapper;
+    }
 
-	public String getXml() {
-		return xml;
-	}
+    public String getXml() {
+        return xml;
+    }
 
-	public void setXml(String xml) {
-		this.xml = xml;
-	}
+    public void setXml(String xml) {
+        this.xml = xml;
+    }
 
-	public String getController() {
-		return controller;
-	}
+    public String getController() {
+        return controller;
+    }
 
-	public void setController(String controller) {
-		this.controller = controller;
-	}
+    public void setController(String controller) {
+        this.controller = controller;
+    }
 
 }

+ 532 - 549
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/builder/ConfigBuilder.java

@@ -15,6 +15,18 @@
  */
 package com.baomidou.mybatisplus.generator.config.builder;
 
+import java.io.File;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import com.baomidou.mybatisplus.generator.config.ConstVal;
 import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
 import com.baomidou.mybatisplus.generator.config.GlobalConfig;
@@ -28,18 +40,6 @@ import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
 import com.baomidou.mybatisplus.generator.config.rules.QuerySQL;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 
-import java.io.File;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
 /**
  * 配置汇总 传递给文件生成工具
  *
@@ -48,543 +48,526 @@ import java.util.Set;
  */
 public class ConfigBuilder {
 
-	/**
-	 * SQL连接
-	 */
-	private Connection connection;
-	/**
-	 * SQL语句类型
-	 */
-	private QuerySQL querySQL;
-	private String superEntityClass;
-	private String superMapperClass;
-	/**
-	 * service超类定义
-	 */
-	private String superServiceClass;
-	private String superServiceImplClass;
-	private String superControllerClass;
-	/**
-	 * 数据库表信息
-	 */
-	private List<TableInfo> tableInfoList;
-
-	/**
-	 * 包配置详情
-	 */
-	private Map<String, String> packageInfo;
-	/**
-	 * 路径配置信息
-	 */
-	private Map<String, String> pathInfo;
-
-	/**
-	 * 模板路径配置信息
-	 */
-	private TemplateConfig template;
-
-	/**
-	 * 数据库配置
-	 */
-	private DataSourceConfig dataSourceConfig;
-
-	/**
-	 * 策略配置
-	 */
-	private StrategyConfig strategyConfig;
-
-	/**
-	 * 全局配置信息
-	 */
-	private GlobalConfig globalConfig;
-
-	/**
-	 * 在构造器中处理配置
-	 *
-	 * @param packageConfig
-	 *            包配置
-	 * @param dataSourceConfig
-	 *            数据源配置
-	 * @param strategyConfig
-	 *            表配置
-	 * @param template
-	 *            模板配置
-	 * @param globalConfig
-	 *            全局配置
-	 */
-	public ConfigBuilder(PackageConfig packageConfig, DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig,
-			TemplateConfig template, GlobalConfig globalConfig) {
-		// 全局配置
-		if (null == globalConfig) {
-			this.globalConfig = new GlobalConfig();
-		} else {
-			this.globalConfig = globalConfig;
-		}
-		// 模板配置
-		if (null == template) {
-			this.template = new TemplateConfig();
-		} else {
-			this.template = template;
-		}
-		// 包配置
-		if (null == packageConfig) {
-			handlerPackage(this.template, this.globalConfig.getOutputDir(), new PackageConfig());
-		} else {
-			handlerPackage(this.template, this.globalConfig.getOutputDir(), packageConfig);
-		}
-		this.dataSourceConfig = dataSourceConfig;
-		handlerDataSource(dataSourceConfig);
-		// 策略配置
-		if (null == strategyConfig) {
-			this.strategyConfig = new StrategyConfig();
-		} else {
-			this.strategyConfig = strategyConfig;
-		}
-		handlerStrategy(this.strategyConfig);
-	}
-
-	// ************************ 曝露方法 BEGIN*****************************
-
-	/**
-	 * 所有包配置信息
-	 *
-	 * @return 包配置
-	 */
-	public Map<String, String> getPackageInfo() {
-		return packageInfo;
-	}
-
-	/**
-	 * 所有路径配置
-	 *
-	 * @return 路径配置
-	 */
-	public Map<String, String> getPathInfo() {
-		return pathInfo;
-	}
-
-	public String getSuperEntityClass() {
-		return superEntityClass;
-	}
-
-	public String getSuperMapperClass() {
-		return superMapperClass;
-	}
-
-	/**
-	 * 获取超类定义
-	 *
-	 * @return 完整超类名称
-	 */
-	public String getSuperServiceClass() {
-		return superServiceClass;
-	}
-
-	public String getSuperServiceImplClass() {
-		return superServiceImplClass;
-	}
-
-	public String getSuperControllerClass() {
-		return superControllerClass;
-	}
-
-	/**
-	 * 表信息
-	 *
-	 * @return 所有表信息
-	 */
-	public List<TableInfo> getTableInfoList() {
-		return tableInfoList;
-	}
-
-	/**
-	 * 模板路径配置信息
-	 *
-	 * @return 所以模板路径配置信息
-	 */
-	public TemplateConfig getTemplate() {
-		return template == null ? new TemplateConfig() : template;
-	}
-
-	// ****************************** 曝露方法 END**********************************
-
-	/**
-	 * 处理包配置
-	 *
-	 * @param template
-	 *            TemplateConfig
-	 * @param outputDir
-	 * @param config
-	 *            PackageConfig
-	 */
-	private void handlerPackage(TemplateConfig template, String outputDir, PackageConfig config) {
-		packageInfo = new HashMap<String, String>();
-		packageInfo.put(ConstVal.MODULENAME, config.getModuleName());
-		packageInfo.put(ConstVal.ENTITY, joinPackage(config.getParent(), config.getEntity()));
-		packageInfo.put(ConstVal.MAPPER, joinPackage(config.getParent(), config.getMapper()));
-		packageInfo.put(ConstVal.XML, joinPackage(config.getParent(), config.getXml()));
-		packageInfo.put(ConstVal.SERIVCE, joinPackage(config.getParent(), config.getService()));
-		packageInfo.put(ConstVal.SERVICEIMPL, joinPackage(config.getParent(), config.getServiceImpl()));
-		packageInfo.put(ConstVal.CONTROLLER, joinPackage(config.getParent(), config.getController()));
-
-		// 生成路径信息
-		pathInfo = new HashMap<String, String>();
-		if (StringUtils.isNotEmpty(template.getEntity())) {
-			pathInfo.put(ConstVal.ENTITY_PATH, joinPath(outputDir, packageInfo.get(ConstVal.ENTITY)));
-		}
-		if (StringUtils.isNotEmpty(template.getMapper())) {
-			pathInfo.put(ConstVal.MAPPER_PATH, joinPath(outputDir, packageInfo.get(ConstVal.MAPPER)));
-		}
-		if (StringUtils.isNotEmpty(template.getXml())) {
-			pathInfo.put(ConstVal.XML_PATH, joinPath(outputDir, packageInfo.get(ConstVal.XML)));
-		}
-		if (StringUtils.isNotEmpty(template.getService())) {
-			pathInfo.put(ConstVal.SERIVCE_PATH, joinPath(outputDir, packageInfo.get(ConstVal.SERIVCE)));
-		}
-		if (StringUtils.isNotEmpty(template.getServiceImpl())) {
-			pathInfo.put(ConstVal.SERVICEIMPL_PATH, joinPath(outputDir, packageInfo.get(ConstVal.SERVICEIMPL)));
-		}
-		if (StringUtils.isNotEmpty(template.getController())) {
-			pathInfo.put(ConstVal.CONTROLLER_PATH, joinPath(outputDir, packageInfo.get(ConstVal.CONTROLLER)));
-		}
-	}
-
-	/**
-	 * 处理数据源配置
-	 *
-	 * @param config
-	 *            DataSourceConfig
-	 */
-	private void handlerDataSource(DataSourceConfig config) {
-		connection = config.getConn();
-		querySQL = getQuerySQL(config.getDbType());
-	}
-
-	/**
-	 * 处理数据库表 加载数据库表、列、注释相关数据集
-	 *
-	 * @param config
-	 *            StrategyConfig
-	 */
-	private void handlerStrategy(StrategyConfig config) {
-		processTypes(config);
-		tableInfoList = getTablesInfo(config);
-	}
-
-	/**
-	 * 处理superClassName,IdClassType,IdStrategy配置
-	 *
-	 * @param config
-	 *            策略配置
-	 */
-	private void processTypes(StrategyConfig config) {
-		if (StringUtils.isEmpty(config.getSuperServiceClass())) {
-			superServiceClass = ConstVal.SUPERD_SERVICE_CLASS;
-		} else {
-			superServiceClass = config.getSuperServiceClass();
-		}
-		if (StringUtils.isEmpty(config.getSuperServiceImplClass())) {
-			superServiceImplClass = ConstVal.SUPERD_SERVICEIMPL_CLASS;
-		} else {
-			superServiceImplClass = config.getSuperServiceImplClass();
-		}
-		if (StringUtils.isEmpty(config.getSuperMapperClass())) {
-			superMapperClass = ConstVal.SUPERD_MAPPER_CLASS;
-		} else {
-			superMapperClass = config.getSuperMapperClass();
-		}
-		superEntityClass = config.getSuperEntityClass();
-		superControllerClass = config.getSuperControllerClass();
-	}
-
-	/**
-	 * 处理表对应的类名称
-	 *
-	 * @param tableList
-	 *            表名称
-	 * @param strategy
-	 *            命名策略
-	 * @param tablePrefix
-	 * @return 补充完整信息后的表
-	 */
-	private List<TableInfo> processTable(List<TableInfo> tableList, NamingStrategy strategy, String[] tablePrefix) {
-		for (TableInfo tableInfo : tableList) {
-			tableInfo.setEntityName(strategyConfig, NamingStrategy.capitalFirst(processName(tableInfo.getName(), strategy, tablePrefix)));
-			if (StringUtils.isNotEmpty(globalConfig.getMapperName())) {
-				tableInfo.setMapperName(String.format(globalConfig.getMapperName(), tableInfo.getEntityName()));
-			} else {
-				tableInfo.setMapperName(tableInfo.getEntityName() + ConstVal.MAPPER);
-			}
-			if (StringUtils.isNotEmpty(globalConfig.getXmlName())) {
-				tableInfo.setXmlName(String.format(globalConfig.getXmlName(), tableInfo.getEntityName()));
-			} else {
-				tableInfo.setXmlName(tableInfo.getEntityName() + ConstVal.MAPPER);
-			}
-			if (StringUtils.isNotEmpty(globalConfig.getServiceName())) {
-				tableInfo.setServiceName(String.format(globalConfig.getServiceName(), tableInfo.getEntityName()));
-			} else {
-				tableInfo.setServiceName("I" + tableInfo.getEntityName() + ConstVal.SERIVCE);
-			}
-			if (StringUtils.isNotEmpty(globalConfig.getServiceImplName())) {
-				tableInfo.setServiceImplName(String.format(globalConfig.getServiceImplName(), tableInfo.getEntityName()));
-			} else {
-				tableInfo.setServiceImplName(tableInfo.getEntityName() + ConstVal.SERVICEIMPL);
-			}
-			if (StringUtils.isNotEmpty(globalConfig.getControllerName())) {
-				tableInfo.setControllerName(String.format(globalConfig.getControllerName(), tableInfo.getEntityName()));
-			} else {
-				tableInfo.setControllerName(tableInfo.getEntityName() + ConstVal.CONTROLLER);
-			}
-		}
-		return tableList;
-	}
-
-	/**
-	 * 获取所有的数据库表信息
-	 *
-	 * @return 表信息
-	 */
-	private List<TableInfo> getTablesInfo(StrategyConfig config) {
-		boolean isInclude = (null != config.getInclude() && config.getInclude().length > 0);
-		boolean isExclude = (null != config.getExclude() && config.getExclude().length > 0);
-		if (isInclude && isExclude) {
-			throw new RuntimeException("<strategy> 标签中 <include> 与 <exclude> 只能配置一项!");
-		}
-		List<TableInfo> tableList = new ArrayList<TableInfo>();
-		Set<String> notExistTables = new HashSet<String>();
-		NamingStrategy strategy = config.getNaming();
-		PreparedStatement pstate = null;
-		try {
-			pstate = connection.prepareStatement(querySQL.getTableCommentsSql());
-			ResultSet results = pstate.executeQuery();
-			TableInfo tableInfo;
-			while (results.next()) {
-				String tableName = results.getString(querySQL.getTableName());
-				if (StringUtils.isNotEmpty(tableName)) {
-					String tableComment = results.getString(querySQL.getTableComment());
-					tableInfo = new TableInfo();
-					if (isInclude) {
-						for (String includeTab : config.getInclude()) {
-							if (includeTab.equalsIgnoreCase(tableName)) {
-								tableInfo.setName(tableName);
-								tableInfo.setComment(tableComment);
-							} else {
-								notExistTables.add(includeTab);
-							}
-						}
-					} else if (isExclude) {
-						for (String excludeTab : config.getExclude()) {
-							if (!excludeTab.equalsIgnoreCase(tableName)) {
-								tableInfo.setName(tableName);
-								tableInfo.setComment(tableComment);
-							} else {
-								notExistTables.add(excludeTab);
-							}
-						}
-					} else {
-						tableInfo.setName(tableName);
-						tableInfo.setComment(tableComment);
-					}
-					if (StringUtils.isNotEmpty(tableInfo.getName())) {
-						List<TableField> fieldList = getListFields(tableInfo.getName(), strategy);
-						tableInfo.setFields(fieldList);
-						tableList.add(tableInfo);
-					}
-				} else {
-					System.err.println("当前数据库为空!!!");
-				}
-			}
-			// 将已经存在的表移除
-			for (TableInfo tabInfo : tableList) {
-				notExistTables.remove(tabInfo.getName());
-			}
-			if (notExistTables.size() > 0) {
-				System.err.println("表 " + notExistTables + " 在数据库中不存在!!!");
-			}
-		} catch (SQLException e) {
-			e.printStackTrace();
-		} finally {
-			// 释放资源
-			try {
-				if (pstate != null) {
-					pstate.close();
-				}
-				if (connection != null) {
-					connection.close();
-				}
-			} catch (SQLException e) {
-				e.printStackTrace();
-			}
-		}
-		return processTable(tableList, strategy, config.getTablePrefix());
-	}
-
-	/**
-	 * 判断主键是否为identity,目前仅对mysql进行检查
-	 * @param results ResultSet
-	 * @return 主键是否为identity
-	 * @throws SQLException
+    /**
+     * SQL连接
+     */
+    private Connection connection;
+    /**
+     * SQL语句类型
+     */
+    private QuerySQL querySQL;
+    private String superEntityClass;
+    private String superMapperClass;
+    /**
+     * service超类定义
+     */
+    private String superServiceClass;
+    private String superServiceImplClass;
+    private String superControllerClass;
+    /**
+     * 数据库表信息
+     */
+    private List<TableInfo> tableInfoList;
+
+    /**
+     * 包配置详情
+     */
+    private Map<String, String> packageInfo;
+    /**
+     * 路径配置信息
+     */
+    private Map<String, String> pathInfo;
+
+    /**
+     * 模板路径配置信息
+     */
+    private TemplateConfig template;
+
+    /**
+     * 数据库配置
+     */
+    private DataSourceConfig dataSourceConfig;
+
+    /**
+     * 策略配置
+     */
+    private StrategyConfig strategyConfig;
+
+    /**
+     * 全局配置信息
+     */
+    private GlobalConfig globalConfig;
+
+    /**
+     * 在构造器中处理配置
+     *
+     * @param packageConfig    包配置
+     * @param dataSourceConfig 数据源配置
+     * @param strategyConfig   表配置
+     * @param template         模板配置
+     * @param globalConfig     全局配置
+     */
+    public ConfigBuilder(PackageConfig packageConfig, DataSourceConfig dataSourceConfig, StrategyConfig strategyConfig,
+                         TemplateConfig template, GlobalConfig globalConfig) {
+        // 全局配置
+        if (null == globalConfig) {
+            this.globalConfig = new GlobalConfig();
+        } else {
+            this.globalConfig = globalConfig;
+        }
+        // 模板配置
+        if (null == template) {
+            this.template = new TemplateConfig();
+        } else {
+            this.template = template;
+        }
+        // 包配置
+        if (null == packageConfig) {
+            handlerPackage(this.template, this.globalConfig.getOutputDir(), new PackageConfig());
+        } else {
+            handlerPackage(this.template, this.globalConfig.getOutputDir(), packageConfig);
+        }
+        this.dataSourceConfig = dataSourceConfig;
+        handlerDataSource(dataSourceConfig);
+        // 策略配置
+        if (null == strategyConfig) {
+            this.strategyConfig = new StrategyConfig();
+        } else {
+            this.strategyConfig = strategyConfig;
+        }
+        handlerStrategy(this.strategyConfig);
+    }
+
+    // ************************ 曝露方法 BEGIN*****************************
+
+    /**
+     * 所有包配置信息
+     *
+     * @return 包配置
+     */
+    public Map<String, String> getPackageInfo() {
+        return packageInfo;
+    }
+
+    /**
+     * 所有路径配置
+     *
+     * @return 路径配置
+     */
+    public Map<String, String> getPathInfo() {
+        return pathInfo;
+    }
+
+    public String getSuperEntityClass() {
+        return superEntityClass;
+    }
+
+    public String getSuperMapperClass() {
+        return superMapperClass;
+    }
+
+    /**
+     * 获取超类定义
+     *
+     * @return 完整超类名称
+     */
+    public String getSuperServiceClass() {
+        return superServiceClass;
+    }
+
+    public String getSuperServiceImplClass() {
+        return superServiceImplClass;
+    }
+
+    public String getSuperControllerClass() {
+        return superControllerClass;
+    }
+
+    /**
+     * 表信息
+     *
+     * @return 所有表信息
+     */
+    public List<TableInfo> getTableInfoList() {
+        return tableInfoList;
+    }
+
+    /**
+     * 模板路径配置信息
+     *
+     * @return 所以模板路径配置信息
+     */
+    public TemplateConfig getTemplate() {
+        return template == null ? new TemplateConfig() : template;
+    }
+
+    // ****************************** 曝露方法 END**********************************
+
+    /**
+     * 处理包配置
+     *
+     * @param template  TemplateConfig
+     * @param outputDir
+     * @param config    PackageConfig
+     */
+    private void handlerPackage(TemplateConfig template, String outputDir, PackageConfig config) {
+        packageInfo = new HashMap<String, String>();
+        packageInfo.put(ConstVal.MODULENAME, config.getModuleName());
+        packageInfo.put(ConstVal.ENTITY, joinPackage(config.getParent(), config.getEntity()));
+        packageInfo.put(ConstVal.MAPPER, joinPackage(config.getParent(), config.getMapper()));
+        packageInfo.put(ConstVal.XML, joinPackage(config.getParent(), config.getXml()));
+        packageInfo.put(ConstVal.SERIVCE, joinPackage(config.getParent(), config.getService()));
+        packageInfo.put(ConstVal.SERVICEIMPL, joinPackage(config.getParent(), config.getServiceImpl()));
+        packageInfo.put(ConstVal.CONTROLLER, joinPackage(config.getParent(), config.getController()));
+
+        // 生成路径信息
+        pathInfo = new HashMap<String, String>();
+        if (StringUtils.isNotEmpty(template.getEntity())) {
+            pathInfo.put(ConstVal.ENTITY_PATH, joinPath(outputDir, packageInfo.get(ConstVal.ENTITY)));
+        }
+        if (StringUtils.isNotEmpty(template.getMapper())) {
+            pathInfo.put(ConstVal.MAPPER_PATH, joinPath(outputDir, packageInfo.get(ConstVal.MAPPER)));
+        }
+        if (StringUtils.isNotEmpty(template.getXml())) {
+            pathInfo.put(ConstVal.XML_PATH, joinPath(outputDir, packageInfo.get(ConstVal.XML)));
+        }
+        if (StringUtils.isNotEmpty(template.getService())) {
+            pathInfo.put(ConstVal.SERIVCE_PATH, joinPath(outputDir, packageInfo.get(ConstVal.SERIVCE)));
+        }
+        if (StringUtils.isNotEmpty(template.getServiceImpl())) {
+            pathInfo.put(ConstVal.SERVICEIMPL_PATH, joinPath(outputDir, packageInfo.get(ConstVal.SERVICEIMPL)));
+        }
+        if (StringUtils.isNotEmpty(template.getController())) {
+            pathInfo.put(ConstVal.CONTROLLER_PATH, joinPath(outputDir, packageInfo.get(ConstVal.CONTROLLER)));
+        }
+    }
+
+    /**
+     * 处理数据源配置
+     *
+     * @param config DataSourceConfig
+     */
+    private void handlerDataSource(DataSourceConfig config) {
+        connection = config.getConn();
+        querySQL = getQuerySQL(config.getDbType());
+    }
+
+    /**
+     * 处理数据库表 加载数据库表、列、注释相关数据集
+     *
+     * @param config StrategyConfig
+     */
+    private void handlerStrategy(StrategyConfig config) {
+        processTypes(config);
+        tableInfoList = getTablesInfo(config);
+    }
+
+    /**
+     * 处理superClassName,IdClassType,IdStrategy配置
+     *
+     * @param config 策略配置
+     */
+    private void processTypes(StrategyConfig config) {
+        if (StringUtils.isEmpty(config.getSuperServiceClass())) {
+            superServiceClass = ConstVal.SUPERD_SERVICE_CLASS;
+        } else {
+            superServiceClass = config.getSuperServiceClass();
+        }
+        if (StringUtils.isEmpty(config.getSuperServiceImplClass())) {
+            superServiceImplClass = ConstVal.SUPERD_SERVICEIMPL_CLASS;
+        } else {
+            superServiceImplClass = config.getSuperServiceImplClass();
+        }
+        if (StringUtils.isEmpty(config.getSuperMapperClass())) {
+            superMapperClass = ConstVal.SUPERD_MAPPER_CLASS;
+        } else {
+            superMapperClass = config.getSuperMapperClass();
+        }
+        superEntityClass = config.getSuperEntityClass();
+        superControllerClass = config.getSuperControllerClass();
+    }
+
+    /**
+     * 处理表对应的类名称
+     *
+     * @param tableList   表名称
+     * @param strategy    命名策略
+     * @param tablePrefix
+     * @return 补充完整信息后的表
+     */
+    private List<TableInfo> processTable(List<TableInfo> tableList, NamingStrategy strategy, String[] tablePrefix) {
+        for (TableInfo tableInfo : tableList) {
+            tableInfo.setEntityName(strategyConfig, NamingStrategy.capitalFirst(processName(tableInfo.getName(), strategy, tablePrefix)));
+            if (StringUtils.isNotEmpty(globalConfig.getMapperName())) {
+                tableInfo.setMapperName(String.format(globalConfig.getMapperName(), tableInfo.getEntityName()));
+            } else {
+                tableInfo.setMapperName(tableInfo.getEntityName() + ConstVal.MAPPER);
+            }
+            if (StringUtils.isNotEmpty(globalConfig.getXmlName())) {
+                tableInfo.setXmlName(String.format(globalConfig.getXmlName(), tableInfo.getEntityName()));
+            } else {
+                tableInfo.setXmlName(tableInfo.getEntityName() + ConstVal.MAPPER);
+            }
+            if (StringUtils.isNotEmpty(globalConfig.getServiceName())) {
+                tableInfo.setServiceName(String.format(globalConfig.getServiceName(), tableInfo.getEntityName()));
+            } else {
+                tableInfo.setServiceName("I" + tableInfo.getEntityName() + ConstVal.SERIVCE);
+            }
+            if (StringUtils.isNotEmpty(globalConfig.getServiceImplName())) {
+                tableInfo.setServiceImplName(String.format(globalConfig.getServiceImplName(), tableInfo.getEntityName()));
+            } else {
+                tableInfo.setServiceImplName(tableInfo.getEntityName() + ConstVal.SERVICEIMPL);
+            }
+            if (StringUtils.isNotEmpty(globalConfig.getControllerName())) {
+                tableInfo.setControllerName(String.format(globalConfig.getControllerName(), tableInfo.getEntityName()));
+            } else {
+                tableInfo.setControllerName(tableInfo.getEntityName() + ConstVal.CONTROLLER);
+            }
+        }
+        return tableList;
+    }
+
+    /**
+     * 获取所有的数据库表信息
+     *
+     * @return 表信息
+     */
+    private List<TableInfo> getTablesInfo(StrategyConfig config) {
+        boolean isInclude = (null != config.getInclude() && config.getInclude().length > 0);
+        boolean isExclude = (null != config.getExclude() && config.getExclude().length > 0);
+        if (isInclude && isExclude) {
+            throw new RuntimeException("<strategy> 标签中 <include> 与 <exclude> 只能配置一项!");
+        }
+        List<TableInfo> tableList = new ArrayList<TableInfo>();
+        Set<String> notExistTables = new HashSet<String>();
+        NamingStrategy strategy = config.getNaming();
+        PreparedStatement pstate = null;
+        try {
+            pstate = connection.prepareStatement(querySQL.getTableCommentsSql());
+            ResultSet results = pstate.executeQuery();
+            TableInfo tableInfo;
+            while (results.next()) {
+                String tableName = results.getString(querySQL.getTableName());
+                if (StringUtils.isNotEmpty(tableName)) {
+                    String tableComment = results.getString(querySQL.getTableComment());
+                    tableInfo = new TableInfo();
+                    if (isInclude) {
+                        for (String includeTab : config.getInclude()) {
+                            if (includeTab.equalsIgnoreCase(tableName)) {
+                                tableInfo.setName(tableName);
+                                tableInfo.setComment(tableComment);
+                            } else {
+                                notExistTables.add(includeTab);
+                            }
+                        }
+                    } else if (isExclude) {
+                        for (String excludeTab : config.getExclude()) {
+                            if (!excludeTab.equalsIgnoreCase(tableName)) {
+                                tableInfo.setName(tableName);
+                                tableInfo.setComment(tableComment);
+                            } else {
+                                notExistTables.add(excludeTab);
+                            }
+                        }
+                    } else {
+                        tableInfo.setName(tableName);
+                        tableInfo.setComment(tableComment);
+                    }
+                    if (StringUtils.isNotEmpty(tableInfo.getName())) {
+                        List<TableField> fieldList = getListFields(tableInfo.getName(), strategy);
+                        tableInfo.setFields(fieldList);
+                        tableList.add(tableInfo);
+                    }
+                } else {
+                    System.err.println("当前数据库为空!!!");
+                }
+            }
+            // 将已经存在的表移除
+            for (TableInfo tabInfo : tableList) {
+                notExistTables.remove(tabInfo.getName());
+            }
+            if (notExistTables.size() > 0) {
+                System.err.println("表 " + notExistTables + " 在数据库中不存在!!!");
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        } finally {
+            // 释放资源
+            try {
+                if (pstate != null) {
+                    pstate.close();
+                }
+                if (connection != null) {
+                    connection.close();
+                }
+            } catch (SQLException e) {
+                e.printStackTrace();
+            }
+        }
+        return processTable(tableList, strategy, config.getTablePrefix());
+    }
+
+    /**
+     * 判断主键是否为identity,目前仅对mysql进行检查
+     *
+     * @param results ResultSet
+     * @return 主键是否为identity
+     * @throws SQLException
+     */
+    private boolean isKeyIdentity(ResultSet results) throws SQLException {
+        if (QuerySQL.MYSQL == this.querySQL) {
+            String extra = results.getString("Extra");
+            if ("auto_increment".equals(extra)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 将字段信息与表信息关联
+     *
+     * @param tableName 表名称
+     * @param strategy  命名策略
+     * @return 表信息
+     */
+    private List<TableField> getListFields(String tableName, NamingStrategy strategy) throws SQLException {
+        boolean havedId = false;
+        PreparedStatement pstate = connection.prepareStatement(String.format(querySQL.getTableFieldsSql(), tableName));
+        ResultSet results = pstate.executeQuery();
+
+        List<TableField> fieldList = new ArrayList<TableField>();
+        while (results.next()) {
+            TableField field = new TableField();
+            String key = results.getString(querySQL.getFieldKey());
+            // 避免多重主键设置,目前只取第一个找到ID,并放到list中的索引为0的位置
+            boolean isId = StringUtils.isNotEmpty(key) && key.toUpperCase().equals("PRI");
+            // 处理ID
+            if (isId && !havedId) {
+                field.setKeyFlag(true);
+                if (isKeyIdentity(results)) {
+                    field.setKeyIdentityFlag(true);
+                }
+                havedId = true;
+            } else {
+                field.setKeyFlag(false);
+            }
+            // 处理其它信息
+            field.setName(results.getString(querySQL.getFieldName()));
+            if (strategyConfig.includeSuperEntityColumns(field.getName())) {
+                // 跳过公共字段
+                continue;
+            }
+            field.setType(results.getString(querySQL.getFieldType()));
+            field.setPropertyName(strategyConfig, processName(field.getName(), strategy));
+            field.setColumnType(dataSourceConfig.getTypeConvert().processTypeConvert(field.getType()));
+            field.setComment(results.getString(querySQL.getFieldComment()));
+            fieldList.add(field);
+        }
+        return fieldList;
+    }
+
+    /**
+     * 连接路径字符串
+     *
+     * @param parentDir   路径常量字符串
+     * @param packageName 包名
+     * @return 连接后的路径
+     */
+    private String joinPath(String parentDir, String packageName) {
+        if (StringUtils.isEmpty(parentDir)) {
+            parentDir = System.getProperty(ConstVal.JAVA_TMPDIR);
+        }
+        if (!StringUtils.endsWith(parentDir, File.separator)) {
+            parentDir += File.separator;
+        }
+        packageName = packageName.replaceAll("\\.", "\\" + File.separator);
+        return parentDir + packageName;
+    }
+
+    /**
+     * 连接父子包名
+     *
+     * @param parent     父包名
+     * @param subPackage 子包名
+     * @return 连接后的包名
+     */
+    private String joinPackage(String parent, String subPackage) {
+        if (StringUtils.isEmpty(parent)) {
+            return subPackage;
+        }
+        return parent + "." + subPackage;
+    }
+
+    /**
+     * 处理字段名称
+     *
+     * @return 根据策略返回处理后的名称
+     */
+    private String processName(String name, NamingStrategy strategy) {
+        return processName(name, strategy, null);
+    }
+
+    /**
+     * 处理字段名称
+     *
+     * @param name
+     * @param strategy
+     * @param tablePrefix
+     * @return 根据策略返回处理后的名称
+     */
+    private String processName(String name, NamingStrategy strategy, String[] tablePrefix) {
+        boolean removePrefix = false;
+        if (tablePrefix != null && tablePrefix.length >= 1) {
+            removePrefix = true;
+        }
+        String propertyName;
+        if (removePrefix) {
+            if (strategy == NamingStrategy.underline_to_camel) {
+                // 删除前缀、下划线转驼峰
+                propertyName = NamingStrategy.removePrefixAndCamel(name, tablePrefix);
+            } else {
+                // 删除前缀
+                propertyName = NamingStrategy.removePrefix(name, tablePrefix);
+            }
+        } else if (strategy == NamingStrategy.underline_to_camel) {
+            // 下划线转驼峰
+            propertyName = NamingStrategy.underlineToCamel(name);
+        } else {
+            // 不处理
+            propertyName = name;
+        }
+        return propertyName;
+    }
+
+    /**
+     * 获取当前的SQL类型
+     *
+     * @return DB类型
      */
-	private boolean isKeyIdentity(ResultSet results) throws SQLException{
-		if(QuerySQL.MYSQL==this.querySQL){
-			String extra= results.getString("Extra");
-			if("auto_increment".equals(extra)){
-				return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * 将字段信息与表信息关联
-	 *
-	 * @param tableName
-	 *            表名称
-	 * @param strategy
-	 *            命名策略
-	 * @return 表信息
-	 */
-	private List<TableField> getListFields(String tableName, NamingStrategy strategy) throws SQLException {
-		boolean havedId = false;
-		PreparedStatement pstate = connection.prepareStatement(String.format(querySQL.getTableFieldsSql(), tableName));
-		ResultSet results = pstate.executeQuery();
-
-		List<TableField> fieldList = new ArrayList<TableField>();
-		while (results.next()) {
-			TableField field = new TableField();
-			String key = results.getString(querySQL.getFieldKey());
-			// 避免多重主键设置,目前只取第一个找到ID,并放到list中的索引为0的位置
-			boolean isId = StringUtils.isNotEmpty(key) && key.toUpperCase().equals("PRI");
-			// 处理ID
-			if (isId && !havedId) {
-				field.setKeyFlag(true);
-				if(isKeyIdentity(results)){
-					field.setKeyIdentityFlag(true);
-				}
-				havedId = true;
-			} else {
-				field.setKeyFlag(false);
-			}
-			// 处理其它信息
-			field.setName(results.getString(querySQL.getFieldName()));
-			if (strategyConfig.includeSuperEntityColumns(field.getName())) {
-				// 跳过公共字段
-				continue;
-			}
-			field.setType(results.getString(querySQL.getFieldType()));
-			field.setPropertyName(strategyConfig, processName(field.getName(), strategy));
-			field.setColumnType(dataSourceConfig.getTypeConvert().processTypeConvert(field.getType()));
-			field.setComment(results.getString(querySQL.getFieldComment()));
-			fieldList.add(field);
-		}
-		return fieldList;
-	}
-
-	/**
-	 * 连接路径字符串
-	 *
-	 * @param parentDir
-	 *            路径常量字符串
-	 * @param packageName
-	 *            包名
-	 * @return 连接后的路径
-	 */
-	private String joinPath(String parentDir, String packageName) {
-		if (StringUtils.isEmpty(parentDir)) {
-			parentDir = System.getProperty(ConstVal.JAVA_TMPDIR);
-		}
-		if (!StringUtils.endsWith(parentDir, File.separator)) {
-			parentDir += File.separator;
-		}
-		packageName = packageName.replaceAll("\\.", "\\" + File.separator);
-		return parentDir + packageName;
-	}
-
-	/**
-	 * 连接父子包名
-	 *
-	 * @param parent
-	 *            父包名
-	 * @param subPackage
-	 *            子包名
-	 * @return 连接后的包名
-	 */
-	private String joinPackage(String parent, String subPackage) {
-		if (StringUtils.isEmpty(parent)) {
-			return subPackage;
-		}
-		return parent + "." + subPackage;
-	}
-
-	/**
-	 * 处理字段名称
-	 *
-	 * @return 根据策略返回处理后的名称
-	 */
-	private String processName(String name, NamingStrategy strategy) {
-		return processName(name, strategy, null);
-	}
-
-	/**
-	 * 处理字段名称
-	 *
-	 * @param name
-	 * @param strategy
-	 * @param tablePrefix
-	 * @return 根据策略返回处理后的名称
-	 */
-	private String processName(String name, NamingStrategy strategy, String[] tablePrefix) {
-		boolean removePrefix = false;
-		if (tablePrefix != null && tablePrefix.length >= 1) {
-			removePrefix = true;
-		}
-		String propertyName;
-		if (removePrefix) {
-			if (strategy == NamingStrategy.underline_to_camel) {
-				// 删除前缀、下划线转驼峰
-				propertyName = NamingStrategy.removePrefixAndCamel(name, tablePrefix);
-			} else {
-				// 删除前缀
-				propertyName = NamingStrategy.removePrefix(name, tablePrefix);
-			}
-		} else if (strategy == NamingStrategy.underline_to_camel) {
-			// 下划线转驼峰
-			propertyName = NamingStrategy.underlineToCamel(name);
-		} else {
-			// 不处理
-			propertyName = name;
-		}
-		return propertyName;
-	}
-
-	/**
-	 * 获取当前的SQL类型
-	 *
-	 * @return DB类型
-	 */
-	private QuerySQL getQuerySQL(DbType dbType) {
-		for (QuerySQL qs : QuerySQL.values()) {
-			if (qs.getDbType().equals(dbType.getValue())) {
-				return qs;
-			}
-		}
-		return QuerySQL.MYSQL;
-	}
-
-	public StrategyConfig getStrategyConfig() {
-		return strategyConfig;
-	}
-
-	public void setStrategyConfig(StrategyConfig strategyConfig) {
-		this.strategyConfig = strategyConfig;
-	}
-
-	public GlobalConfig getGlobalConfig() {
-		return globalConfig;
-	}
-
-	public void setGlobalConfig(GlobalConfig globalConfig) {
-		this.globalConfig = globalConfig;
-	}
+    private QuerySQL getQuerySQL(DbType dbType) {
+        for (QuerySQL qs : QuerySQL.values()) {
+            if (qs.getDbType().equals(dbType.getValue())) {
+                return qs;
+            }
+        }
+        return QuerySQL.MYSQL;
+    }
+
+    public StrategyConfig getStrategyConfig() {
+        return strategyConfig;
+    }
+
+    public void setStrategyConfig(StrategyConfig strategyConfig) {
+        this.strategyConfig = strategyConfig;
+    }
+
+    public GlobalConfig getGlobalConfig() {
+        return globalConfig;
+    }
+
+    public void setGlobalConfig(GlobalConfig globalConfig) {
+        this.globalConfig = globalConfig;
+    }
 
 }

+ 30 - 30
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/MySqlTypeConvert.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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,32 +28,32 @@ import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
  */
 public class MySqlTypeConvert implements ITypeConvert {
 
-	public DbColumnType processTypeConvert(String fieldType) {
-		String t = fieldType.toLowerCase();
-		if (t.contains("char") || t.contains("text")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("bigint")) {
-			return DbColumnType.LONG;
-		} else if (t.contains("int")) {
-			return DbColumnType.INTEGER;
-		} else if (t.contains("date") || t.contains("time") || t.contains("year")) {
-			return DbColumnType.DATE;
-		} else if (t.contains("text")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("bit")) {
-			return DbColumnType.BOOLEAN;
-		} else if (t.contains("decimal")) {
-			return DbColumnType.BIG_DECIMAL;
-		} else if (t.contains("blob")) {
-			return DbColumnType.BYTE_ARRAY;
-		} else if (t.contains("float")) {
-			return DbColumnType.FLOAT;
-		} else if (t.contains("double")) {
-			return DbColumnType.DOUBLE;
-		} else if (t.contains("json") || t.contains("enum")) {
-			return DbColumnType.STRING;
-		}
-		return DbColumnType.STRING;
-	}
+    public DbColumnType processTypeConvert(String fieldType) {
+        String t = fieldType.toLowerCase();
+        if (t.contains("char") || t.contains("text")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("bigint")) {
+            return DbColumnType.LONG;
+        } else if (t.contains("int")) {
+            return DbColumnType.INTEGER;
+        } else if (t.contains("date") || t.contains("time") || t.contains("year")) {
+            return DbColumnType.DATE;
+        } else if (t.contains("text")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("bit")) {
+            return DbColumnType.BOOLEAN;
+        } else if (t.contains("decimal")) {
+            return DbColumnType.BIG_DECIMAL;
+        } else if (t.contains("blob")) {
+            return DbColumnType.BYTE_ARRAY;
+        } else if (t.contains("float")) {
+            return DbColumnType.FLOAT;
+        } else if (t.contains("double")) {
+            return DbColumnType.DOUBLE;
+        } else if (t.contains("json") || t.contains("enum")) {
+            return DbColumnType.STRING;
+        }
+        return DbColumnType.STRING;
+    }
 
 }

+ 25 - 25
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/OracleTypeConvert.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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,27 +28,27 @@ import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
  */
 public class OracleTypeConvert implements ITypeConvert {
 
-	public DbColumnType processTypeConvert(String fieldType) {
-		String t = fieldType.toUpperCase();
-		if (t.contains("CHAR")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("DATE") || t.contains("TIMESTAMP")) {
-			return DbColumnType.DATE;
-		} else if (t.contains("NUMBER")) {
-			if (t.matches("NUMBER\\(+\\d{1}+\\)")) {
-				return DbColumnType.INTEGER;
-			} else if (t.matches("NUMBER\\(+\\d{2}+\\)")) {
-				return DbColumnType.LONG;
-			}
-			return DbColumnType.DOUBLE;
-		} else if (t.contains("FLOAT")) {
-			return DbColumnType.FLOAT;
-		} else if (t.contains("BLOB")) {
-			return DbColumnType.OBJECT;
-		} else if (t.contains("RAW")) {
-			return DbColumnType.BYTE_ARRAY;
-		}
-		return DbColumnType.STRING;
-	}
+    public DbColumnType processTypeConvert(String fieldType) {
+        String t = fieldType.toUpperCase();
+        if (t.contains("CHAR")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("DATE") || t.contains("TIMESTAMP")) {
+            return DbColumnType.DATE;
+        } else if (t.contains("NUMBER")) {
+            if (t.matches("NUMBER\\(+\\d{1}+\\)")) {
+                return DbColumnType.INTEGER;
+            } else if (t.matches("NUMBER\\(+\\d{2}+\\)")) {
+                return DbColumnType.LONG;
+            }
+            return DbColumnType.DOUBLE;
+        } else if (t.contains("FLOAT")) {
+            return DbColumnType.FLOAT;
+        } else if (t.contains("BLOB")) {
+            return DbColumnType.OBJECT;
+        } else if (t.contains("RAW")) {
+            return DbColumnType.BYTE_ARRAY;
+        }
+        return DbColumnType.STRING;
+    }
 
 }

+ 30 - 30
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/PostgreSqlTypeConvert.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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,32 +28,32 @@ import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
  */
 public class PostgreSqlTypeConvert implements ITypeConvert {
 
-	public DbColumnType processTypeConvert(String fieldType) {
-		String t = fieldType.toLowerCase();
-		if (t.contains("char") || t.contains("text")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("bigint")) {
-			return DbColumnType.LONG;
-		} else if (t.contains("int")) {
-			return DbColumnType.INTEGER;
-		} else if (t.contains("date") || t.contains("time") || t.contains("year")) {
-			return DbColumnType.DATE;
-		} else if (t.contains("text")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("bit")) {
-			return DbColumnType.BOOLEAN;
-		} else if (t.contains("decimal")) {
-			return DbColumnType.BIG_DECIMAL;
-		} else if (t.contains("blob")) {
-			return DbColumnType.BYTE_ARRAY;
-		} else if (t.contains("float")) {
-			return DbColumnType.FLOAT;
-		} else if (t.contains("double")) {
-			return DbColumnType.DOUBLE;
-		} else if (t.contains("json") || t.contains("enum")) {
-			return DbColumnType.STRING;
-		}
-		return DbColumnType.STRING;
-	}
+    public DbColumnType processTypeConvert(String fieldType) {
+        String t = fieldType.toLowerCase();
+        if (t.contains("char") || t.contains("text")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("bigint")) {
+            return DbColumnType.LONG;
+        } else if (t.contains("int")) {
+            return DbColumnType.INTEGER;
+        } else if (t.contains("date") || t.contains("time") || t.contains("year")) {
+            return DbColumnType.DATE;
+        } else if (t.contains("text")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("bit")) {
+            return DbColumnType.BOOLEAN;
+        } else if (t.contains("decimal")) {
+            return DbColumnType.BIG_DECIMAL;
+        } else if (t.contains("blob")) {
+            return DbColumnType.BYTE_ARRAY;
+        } else if (t.contains("float")) {
+            return DbColumnType.FLOAT;
+        } else if (t.contains("double")) {
+            return DbColumnType.DOUBLE;
+        } else if (t.contains("json") || t.contains("enum")) {
+            return DbColumnType.STRING;
+        }
+        return DbColumnType.STRING;
+    }
 
 }

+ 28 - 28
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/converts/SqlServerTypeConvert.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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,30 +28,30 @@ import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
  */
 public class SqlServerTypeConvert implements ITypeConvert {
 
-	public DbColumnType processTypeConvert(String fieldType) {
-		String t = fieldType.toLowerCase();
-		if (t.contains("char") || t.contains("text") || t.contains("xml")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("bigint")) {
-			return DbColumnType.LONG;
-		} else if (t.contains("int")) {
-			return DbColumnType.INTEGER;
-		} else if (t.contains("date") || t.contains("time")) {
-			return DbColumnType.DATE;
-		} else if (t.contains("text")) {
-			return DbColumnType.STRING;
-		} else if (t.contains("bit")) {
-			return DbColumnType.BOOLEAN;
-		} else if (t.contains("decimal") || t.contains("numeric")) {
-			return DbColumnType.DOUBLE;
-		} else if (t.contains("money")) {
-			return DbColumnType.BIG_DECIMAL;
-		} else if (t.contains("binary") || t.contains("image")) {
-			return DbColumnType.BYTE_ARRAY;
-		} else if (t.contains("float") || t.contains("real")) {
-			return DbColumnType.FLOAT;
-		}
-		return DbColumnType.STRING;
-	}
+    public DbColumnType processTypeConvert(String fieldType) {
+        String t = fieldType.toLowerCase();
+        if (t.contains("char") || t.contains("text") || t.contains("xml")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("bigint")) {
+            return DbColumnType.LONG;
+        } else if (t.contains("int")) {
+            return DbColumnType.INTEGER;
+        } else if (t.contains("date") || t.contains("time")) {
+            return DbColumnType.DATE;
+        } else if (t.contains("text")) {
+            return DbColumnType.STRING;
+        } else if (t.contains("bit")) {
+            return DbColumnType.BOOLEAN;
+        } else if (t.contains("decimal") || t.contains("numeric")) {
+            return DbColumnType.DOUBLE;
+        } else if (t.contains("money")) {
+            return DbColumnType.BIG_DECIMAL;
+        } else if (t.contains("binary") || t.contains("image")) {
+            return DbColumnType.BYTE_ARRAY;
+        } else if (t.contains("float") || t.contains("real")) {
+            return DbColumnType.FLOAT;
+        }
+        return DbColumnType.STRING;
+    }
 
 }

+ 104 - 101
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableField.java

@@ -28,106 +28,109 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @since 2016-12-03
  */
 public class TableField {
-	private boolean convert;
-	private boolean keyFlag;
-	/** 主键是否为自增类型 */
-	private boolean keyIdentityFlag;
-	private String name;
-	private String type;
-	private String propertyName;
-	private DbColumnType columnType;
-	private String comment;
-
-	public boolean isConvert() {
-		return convert;
-	}
-
-	public void setConvert(boolean convert) {
-		this.convert = convert;
-	}
-
-	protected void setConvert(StrategyConfig strategyConfig) {
-		if (strategyConfig.isCapitalModeNaming(name)) {
-			this.convert = false;
-		} else {
-			// 转换字段
-			if (StrategyConfig.DB_COLUMN_UNDERLINE) {
-				// 包含大写处理
-				if (StringUtils.containsUpperCase(name)) {
-					this.convert = true;
-				}
-			} else if (!name.equals(propertyName)) {
-				this.convert = true;
-			}
-		}
-	}
-
-	public boolean isKeyFlag() {
-		return keyFlag;
-	}
-
-	public void setKeyFlag(boolean keyFlag) {
-		this.keyFlag = keyFlag;
-	}
-
-	public boolean isKeyIdentityFlag() {
-		return keyIdentityFlag;
-	}
-
-	public void setKeyIdentityFlag(boolean keyIdentityFlag) {
-		this.keyIdentityFlag = keyIdentityFlag;
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public String getType() {
-		return type;
-	}
-
-	public void setType(String type) {
-		this.type = type;
-	}
-
-	public String getPropertyName() {
-		return propertyName;
-	}
-
-	public void setPropertyName(StrategyConfig strategyConfig, String propertyName) {
-		this.propertyName = propertyName;
-		this.setConvert(strategyConfig);
-	}
-
-	public DbColumnType getColumnType() {
-		return columnType;
-	}
-
-	public void setColumnType(DbColumnType columnType) {
-		this.columnType = columnType;
-	}
-
-	public String getPropertyType() {
-		if (null != columnType) {
-			return columnType.getType();
-		}
-		return null;
-	}
-
-	public String getComment() {
-		return comment;
-	}
-
-	public void setComment(String comment) {
-		this.comment = comment;
-	}
-
-	public String getCapitalName() {
-		return propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
-	}
+
+    private boolean convert;
+    private boolean keyFlag;
+    /**
+     * 主键是否为自增类型
+     */
+    private boolean keyIdentityFlag;
+    private String name;
+    private String type;
+    private String propertyName;
+    private DbColumnType columnType;
+    private String comment;
+
+    public boolean isConvert() {
+        return convert;
+    }
+
+    protected void setConvert(StrategyConfig strategyConfig) {
+        if (strategyConfig.isCapitalModeNaming(name)) {
+            this.convert = false;
+        } else {
+            // 转换字段
+            if (StrategyConfig.DB_COLUMN_UNDERLINE) {
+                // 包含大写处理
+                if (StringUtils.containsUpperCase(name)) {
+                    this.convert = true;
+                }
+            } else if (!name.equals(propertyName)) {
+                this.convert = true;
+            }
+        }
+    }
+
+    public void setConvert(boolean convert) {
+        this.convert = convert;
+    }
+
+    public boolean isKeyFlag() {
+        return keyFlag;
+    }
+
+    public void setKeyFlag(boolean keyFlag) {
+        this.keyFlag = keyFlag;
+    }
+
+    public boolean isKeyIdentityFlag() {
+        return keyIdentityFlag;
+    }
+
+    public void setKeyIdentityFlag(boolean keyIdentityFlag) {
+        this.keyIdentityFlag = keyIdentityFlag;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    public String getPropertyName() {
+        return propertyName;
+    }
+
+    public void setPropertyName(StrategyConfig strategyConfig, String propertyName) {
+        this.propertyName = propertyName;
+        this.setConvert(strategyConfig);
+    }
+
+    public DbColumnType getColumnType() {
+        return columnType;
+    }
+
+    public void setColumnType(DbColumnType columnType) {
+        this.columnType = columnType;
+    }
+
+    public String getPropertyType() {
+        if (null != columnType) {
+            return columnType.getType();
+        }
+        return null;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getCapitalName() {
+        return propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
+    }
 
 }

+ 194 - 194
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/po/TableInfo.java

@@ -15,16 +15,16 @@
  */
 package com.baomidou.mybatisplus.generator.config.po;
 
-import com.baomidou.mybatisplus.generator.config.StrategyConfig;
-import com.baomidou.mybatisplus.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.toolkit.StringUtils;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+import com.baomidou.mybatisplus.generator.config.StrategyConfig;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+
 /**
  * <p>
  * 表信息,关联到当前字段信息
@@ -34,195 +34,195 @@ import java.util.Set;
  * @since 2016/8/30
  */
 public class TableInfo {
-	private boolean convert;
-	private String name;
-	private String comment;
-
-	private String entityName;
-	private String mapperName;
-	private String xmlName;
-	private String serviceName;
-	private String serviceImplName;
-	private String controllerName;
-
-	private List<TableField> fields;
-	private List<String> importPackages = new ArrayList<String>();
-	private String fieldNames;
-
-	public boolean isConvert() {
-		return convert;
-	}
-
-	public void setConvert(boolean convert) {
-		this.convert = convert;
-	}
-
-	protected void setConvert(StrategyConfig strategyConfig) {
-		if (strategyConfig.containsTablePrefix(name)) {
-			// 包含前缀
-			this.convert = true;
-		} else if (strategyConfig.isCapitalModeNaming(name)) {
-			// 包含
-			this.convert = false;
-		} else {
-			// 转换字段
-			if (StrategyConfig.DB_COLUMN_UNDERLINE) {
-				// 包含大写处理
-				if (StringUtils.containsUpperCase(name)) {
-					this.convert = true;
-				}
-			} else if (!entityName.equalsIgnoreCase(name)) {
-				this.convert = true;
-			}
-		}
-	}
-
-	public String getName() {
-		return name;
-	}
-
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public String getComment() {
-		return comment;
-	}
-
-	public void setComment(String comment) {
-		this.comment = comment;
-	}
-
-	public String getEntityPath() {
-		StringBuilder ep = new StringBuilder();
-		ep.append(entityName.substring(0, 1).toLowerCase());
-		ep.append(entityName.substring(1));
-		return ep.toString();
-	}
-
-	public String getEntityName() {
-		return entityName;
-	}
-
-	public void setEntityName(StrategyConfig strategyConfig, String entityName) {
-		this.entityName = entityName;
-		this.setConvert(strategyConfig);
-	}
-
-	public String getMapperName() {
-		return mapperName;
-	}
-
-	public void setMapperName(String mapperName) {
-		this.mapperName = mapperName;
-	}
-
-	public String getXmlName() {
-		return xmlName;
-	}
-
-	public void setXmlName(String xmlName) {
-		this.xmlName = xmlName;
-	}
-
-	public String getServiceName() {
-		return serviceName;
-	}
-
-	public void setServiceName(String serviceName) {
-		this.serviceName = serviceName;
-	}
-
-	public String getServiceImplName() {
-		return serviceImplName;
-	}
-
-	public void setServiceImplName(String serviceImplName) {
-		this.serviceImplName = serviceImplName;
-	}
-
-	public String getControllerName() {
-		return controllerName;
-	}
-
-	public void setControllerName(String controllerName) {
-		this.controllerName = controllerName;
-	}
-
-	public List<TableField> getFields() {
-		return fields;
-	}
-
-	public void setFields(List<TableField> fields) {
-		if (CollectionUtils.isNotEmpty(fields)) {
-			this.fields = fields;
-			// 收集导入包信息
-			Set<String> pkgSet = new HashSet<String>();
-			for (TableField field : fields) {
-				if (null != field.getColumnType() && null != field.getColumnType().getPkg()) {
-					pkgSet.add(field.getColumnType().getPkg());
-				}
-				if (field.isKeyFlag()) {
-					// 主键
-					if (field.isConvert() || field.isKeyIdentityFlag()) {
-						pkgSet.add("com.baomidou.mybatisplus.annotations.TableId");
-					}
-					// 自增
-					if (field.isKeyIdentityFlag()) {
-						pkgSet.add("com.baomidou.mybatisplus.enums.IdType");
-					}
-				} else if (field.isConvert()) {
-					// 普通字段
-					pkgSet.add("com.baomidou.mybatisplus.annotations.TableField");
-				}
-			}
-			if (!pkgSet.isEmpty()) {
-				this.importPackages = new ArrayList<String>(Arrays.asList(pkgSet.toArray(new String[] {})));
-			}
-		}
-	}
-
-	public List<String> getImportPackages() {
-		return importPackages;
-	}
-
-	public void setImportPackages(String pkg) {
-		importPackages.add(pkg);
-	}
-
-	/**
-	 * 转换filed实体为xmlmapper中的basecolumn字符串信息
-	 *
-	 * @return
-	 */
-	public String getFieldNames() {
-		if (StringUtils.isEmpty(fieldNames)) {
-			StringBuilder names = new StringBuilder();
-			for (int i = 0; i < fields.size(); i++) {
-				TableField fd = fields.get(i);
-				if (i == fields.size() - 1) {
-					names.append(cov2col(fd));
-				} else {
-					names.append(cov2col(fd)).append(", ");
-				}
-			}
-			fieldNames = names.toString();
-		}
-		return fieldNames;
-	}
-
-	/**
-	 * mapper xml中的字字段添加as
-	 *
-	 * @param field
-	 *            字段实体
-	 * @return 转换后的信息
-	 */
-	private String cov2col(TableField field) {
-		if (null != field) {
-			return field.isConvert() ? field.getName() + " AS " + field.getPropertyName() : field.getName();
-		}
-		return StringUtils.EMPTY;
-	}
+
+    private boolean convert;
+    private String name;
+    private String comment;
+
+    private String entityName;
+    private String mapperName;
+    private String xmlName;
+    private String serviceName;
+    private String serviceImplName;
+    private String controllerName;
+
+    private List<TableField> fields;
+    private List<String> importPackages = new ArrayList<String>();
+    private String fieldNames;
+
+    public boolean isConvert() {
+        return convert;
+    }
+
+    protected void setConvert(StrategyConfig strategyConfig) {
+        if (strategyConfig.containsTablePrefix(name)) {
+            // 包含前缀
+            this.convert = true;
+        } else if (strategyConfig.isCapitalModeNaming(name)) {
+            // 包含
+            this.convert = false;
+        } else {
+            // 转换字段
+            if (StrategyConfig.DB_COLUMN_UNDERLINE) {
+                // 包含大写处理
+                if (StringUtils.containsUpperCase(name)) {
+                    this.convert = true;
+                }
+            } else if (!entityName.equalsIgnoreCase(name)) {
+                this.convert = true;
+            }
+        }
+    }
+
+    public void setConvert(boolean convert) {
+        this.convert = convert;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getEntityPath() {
+        StringBuilder ep = new StringBuilder();
+        ep.append(entityName.substring(0, 1).toLowerCase());
+        ep.append(entityName.substring(1));
+        return ep.toString();
+    }
+
+    public String getEntityName() {
+        return entityName;
+    }
+
+    public void setEntityName(StrategyConfig strategyConfig, String entityName) {
+        this.entityName = entityName;
+        this.setConvert(strategyConfig);
+    }
+
+    public String getMapperName() {
+        return mapperName;
+    }
+
+    public void setMapperName(String mapperName) {
+        this.mapperName = mapperName;
+    }
+
+    public String getXmlName() {
+        return xmlName;
+    }
+
+    public void setXmlName(String xmlName) {
+        this.xmlName = xmlName;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public void setServiceName(String serviceName) {
+        this.serviceName = serviceName;
+    }
+
+    public String getServiceImplName() {
+        return serviceImplName;
+    }
+
+    public void setServiceImplName(String serviceImplName) {
+        this.serviceImplName = serviceImplName;
+    }
+
+    public String getControllerName() {
+        return controllerName;
+    }
+
+    public void setControllerName(String controllerName) {
+        this.controllerName = controllerName;
+    }
+
+    public List<TableField> getFields() {
+        return fields;
+    }
+
+    public void setFields(List<TableField> fields) {
+        if (CollectionUtils.isNotEmpty(fields)) {
+            this.fields = fields;
+            // 收集导入包信息
+            Set<String> pkgSet = new HashSet<String>();
+            for (TableField field : fields) {
+                if (null != field.getColumnType() && null != field.getColumnType().getPkg()) {
+                    pkgSet.add(field.getColumnType().getPkg());
+                }
+                if (field.isKeyFlag()) {
+                    // 主键
+                    if (field.isConvert() || field.isKeyIdentityFlag()) {
+                        pkgSet.add("com.baomidou.mybatisplus.annotations.TableId");
+                    }
+                    // 自增
+                    if (field.isKeyIdentityFlag()) {
+                        pkgSet.add("com.baomidou.mybatisplus.enums.IdType");
+                    }
+                } else if (field.isConvert()) {
+                    // 普通字段
+                    pkgSet.add("com.baomidou.mybatisplus.annotations.TableField");
+                }
+            }
+            if (!pkgSet.isEmpty()) {
+                this.importPackages = new ArrayList<String>(Arrays.asList(pkgSet.toArray(new String[]{})));
+            }
+        }
+    }
+
+    public List<String> getImportPackages() {
+        return importPackages;
+    }
+
+    public void setImportPackages(String pkg) {
+        importPackages.add(pkg);
+    }
+
+    /**
+     * 转换filed实体为xmlmapper中的basecolumn字符串信息
+     *
+     * @return
+     */
+    public String getFieldNames() {
+        if (StringUtils.isEmpty(fieldNames)) {
+            StringBuilder names = new StringBuilder();
+            for (int i = 0; i < fields.size(); i++) {
+                TableField fd = fields.get(i);
+                if (i == fields.size() - 1) {
+                    names.append(cov2col(fd));
+                } else {
+                    names.append(cov2col(fd)).append(", ");
+                }
+            }
+            fieldNames = names.toString();
+        }
+        return fieldNames;
+    }
+
+    /**
+     * mapper xml中的字字段添加as
+     *
+     * @param field 字段实体
+     * @return 转换后的信息
+     */
+    private String cov2col(TableField field) {
+        if (null != field) {
+            return field.isConvert() ? field.getName() + " AS " + field.getPropertyName() : field.getName();
+        }
+        return StringUtils.EMPTY;
+    }
 
 }

+ 35 - 31
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbColumnType.java

@@ -19,45 +19,49 @@ package com.baomidou.mybatisplus.generator.config.rules;
  * <p>
  * 表字段类型
  * </p>
- * 
+ *
  * @author hubin
  * @since 2017-01-11
  */
 public enum DbColumnType {
-	STRING("String", null),
-	LONG("Long", null),
-	INTEGER("Integer", null),
-	FLOAT("Float", null),
-	DOUBLE("Double", null),
-	BOOLEAN("Boolean", null),
-	BYTE_ARRAY("byte[]", null),
-	CHARACTER("Character", null),
-	OBJECT("Object", null),
-	DATE("Date", "java.util.Date"),
-	TIME("Time", "java.sql.Time"),
-	BLOB("Blob", "java.sql.Blob"),
-	CLOB("Clob", "java.sql.Clob"),
-	TIMESTAMP("Timestamp", "java.sql.Timestamp"),
-	BIG_INTEGER("BigInteger", "java.math.BigInteger"),
-	BIG_DECIMAL("BigDecimal", "java.math.BigDecimal");
+    STRING("String", null),
+    LONG("Long", null),
+    INTEGER("Integer", null),
+    FLOAT("Float", null),
+    DOUBLE("Double", null),
+    BOOLEAN("Boolean", null),
+    BYTE_ARRAY("byte[]", null),
+    CHARACTER("Character", null),
+    OBJECT("Object", null),
+    DATE("Date", "java.util.Date"),
+    TIME("Time", "java.sql.Time"),
+    BLOB("Blob", "java.sql.Blob"),
+    CLOB("Clob", "java.sql.Clob"),
+    TIMESTAMP("Timestamp", "java.sql.Timestamp"),
+    BIG_INTEGER("BigInteger", "java.math.BigInteger"),
+    BIG_DECIMAL("BigDecimal", "java.math.BigDecimal");
 
-	/** 类型 */
-	private final String type;
+    /**
+     * 类型
+     */
+    private final String type;
 
-	/** 包路径 */
-	private final String pkg;
+    /**
+     * 包路径
+     */
+    private final String pkg;
 
-	DbColumnType(final String type, final String pkg) {
-		this.type = type;
-		this.pkg = pkg;
-	}
+    DbColumnType(final String type, final String pkg) {
+        this.type = type;
+        this.pkg = pkg;
+    }
 
-	public String getType() {
-		return this.type;
-	}
+    public String getType() {
+        return this.type;
+    }
 
-	public String getPkg() {
-		return this.pkg;
-	}
+    public String getPkg() {
+        return this.pkg;
+    }
 
 }

+ 8 - 8
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/DbType.java

@@ -23,16 +23,16 @@ package com.baomidou.mybatisplus.generator.config.rules;
  */
 public enum DbType {
 
-	MYSQL("mysql"), ORACLE("oracle"), SQL_SERVER("sql_server"), POSTGRE_SQL("postgre_sql");
+    MYSQL("mysql"), ORACLE("oracle"), SQL_SERVER("sql_server"), POSTGRE_SQL("postgre_sql");
 
-	private String value;
+    private final String value;
 
-	DbType(String value) {
-		this.value = value;
-	}
+    DbType(String value) {
+        this.value = value;
+    }
 
-	public String getValue() {
-		return value;
-	}
+    public String getValue() {
+        return value;
+    }
 
 }

+ 99 - 100
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/NamingStrategy.java

@@ -25,112 +25,111 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @since 2016/8/30
  */
 public enum NamingStrategy {
-	/**
-	 * 不做任何改变,原样输出
-	 */
-	nochange,
-	/**
-	 * 下划线转驼峰命名
-	 */
-	underline_to_camel;
+    /**
+     * 不做任何改变,原样输出
+     */
+    nochange,
+    /**
+     * 下划线转驼峰命名
+     */
+    underline_to_camel;
 
-	public static String underlineToCamel(String name) {
-		// 快速检查
-		if (StringUtils.isEmpty(name)) {
-			// 没必要转换
-			return "";
-		}
-		String tempName = name;
-		StringBuilder result = new StringBuilder();
-		// 大写数字下划线组成转为小写
-		if (StringUtils.isCapitalMode(name)) {
-			tempName = name.toLowerCase();
-		}
-		// 用下划线将原始字符串分割
-		String camels[] = tempName.split(ConstVal.UNDERLINE);
-		for (String camel : camels) {
-			// 跳过原始字符串中开头、结尾的下换线或双重下划线
-			if (StringUtils.isEmpty(camel)) {
-				continue;
-			}
-			// 处理真正的驼峰片段
-			if (result.length() == 0) {
-				// 第一个驼峰片段,全部字母都小写
-				result.append(camel);
-			} else {
-				// 其他的驼峰片段,首字母大写
-				result.append(capitalFirst(camel));
-			}
-		}
-		return result.toString();
-	}
+    public static String underlineToCamel(String name) {
+        // 快速检查
+        if (StringUtils.isEmpty(name)) {
+            // 没必要转换
+            return "";
+        }
+        String tempName = name;
+        StringBuilder result = new StringBuilder();
+        // 大写数字下划线组成转为小写
+        if (StringUtils.isCapitalMode(name)) {
+            tempName = name.toLowerCase();
+        }
+        // 用下划线将原始字符串分割
+        String camels[] = tempName.split(ConstVal.UNDERLINE);
+        for (String camel : camels) {
+            // 跳过原始字符串中开头、结尾的下换线或双重下划线
+            if (StringUtils.isEmpty(camel)) {
+                continue;
+            }
+            // 处理真正的驼峰片段
+            if (result.length() == 0) {
+                // 第一个驼峰片段,全部字母都小写
+                result.append(camel);
+            } else {
+                // 其他的驼峰片段,首字母大写
+                result.append(capitalFirst(camel));
+            }
+        }
+        return result.toString();
+    }
 
-	/**
-	 * 去掉下划线前缀
-	 *
-	 * @param name
-	 * @return
-	 */
-	public static String removePrefix(String name) {
-		if (StringUtils.isEmpty(name)) {
-			return "";
-		}
-		int idx = name.indexOf(ConstVal.UNDERLINE);
-		if (idx == -1) {
-			return name;
-		}
-		return name.substring(idx + 1);
-	}
+    /**
+     * 去掉下划线前缀
+     *
+     * @param name
+     * @return
+     */
+    public static String removePrefix(String name) {
+        if (StringUtils.isEmpty(name)) {
+            return "";
+        }
+        int idx = name.indexOf(ConstVal.UNDERLINE);
+        if (idx == -1) {
+            return name;
+        }
+        return name.substring(idx + 1);
+    }
 
-	/**
-	 * 去掉指定的前缀
-	 * 
-	 * @param name
-	 * @param prefix
-	 * @return
-	 */
-	public static String removePrefix(String name, String[] prefix) {
-		if (StringUtils.isEmpty(name)) {
-			return "";
-		}
-		if (null != prefix) {
-			for (String pf : prefix) {
-				if (name.toLowerCase().matches("^" + pf.toLowerCase() + ".*")) {
-					// 判断是否有匹配的前缀,然后截取前缀
-					// 删除前缀
-					return name.substring(pf.length());
-				}
-			}
-		}
-		return name;
-	}
+    /**
+     * 去掉指定的前缀
+     *
+     * @param name
+     * @param prefix
+     * @return
+     */
+    public static String removePrefix(String name, String[] prefix) {
+        if (StringUtils.isEmpty(name)) {
+            return "";
+        }
+        if (null != prefix) {
+            for (String pf : prefix) {
+                if (name.toLowerCase().matches("^" + pf.toLowerCase() + ".*")) {
+                    // 判断是否有匹配的前缀,然后截取前缀
+                    // 删除前缀
+                    return name.substring(pf.length());
+                }
+            }
+        }
+        return name;
+    }
 
-	/**
-	 * 去掉下划线前缀且将后半部分转成驼峰格式
-	 *
-	 * @param name
-	 * @param tablePrefix
-	 * @return
-	 */
-	public static String removePrefixAndCamel(String name, String[] tablePrefix) {
-		return underlineToCamel(removePrefix(name, tablePrefix));
-	}
+    /**
+     * 去掉下划线前缀且将后半部分转成驼峰格式
+     *
+     * @param name
+     * @param tablePrefix
+     * @return
+     */
+    public static String removePrefixAndCamel(String name, String[] tablePrefix) {
+        return underlineToCamel(removePrefix(name, tablePrefix));
+    }
 
-	/**
-	 * 实体首字母大写
-	 *
-	 * @param name
-	 *            待转换的字符串
-	 * @return 转换后的字符串
-	 */
-	public static String capitalFirst(String name) {
-		if (StringUtils.isNotEmpty(name)) {
-			return name.substring(0, 1).toUpperCase() + name.substring(1);
-			/*char[] array = name.toCharArray();
+    /**
+     * 实体首字母大写
+     *
+     * @param name 待转换的字符串
+     * @return 转换后的字符串
+     */
+    public static String capitalFirst(String name) {
+        if (StringUtils.isNotEmpty(name)) {
+            return name.substring(0, 1).toUpperCase() + name.substring(1);
+            /*char[] array = name.toCharArray();
 			array[0] -= 32;
 			return String.valueOf(array);*/
-		}
-		return "";
-	}
+        }
+        return "";
+    }
 
 }

+ 106 - 106
mybatis-plus/src/main/java/com/baomidou/mybatisplus/generator/config/rules/QuerySQL.java

@@ -24,111 +24,111 @@ package com.baomidou.mybatisplus.generator.config.rules;
  * @since 2016-04-25
  */
 public enum QuerySQL {
-	MYSQL("mysql", "show tables", "show table status", "show full fields from %s", "NAME", "COMMENT", "FIELD", "TYPE",
-			"COMMENT", "KEY"),
-
-	ORACLE("oracle", "SELECT * FROM USER_TABLES", "SELECT * FROM USER_TAB_COMMENTS",
-			"SELECT A.COLUMN_NAME, CASE WHEN A.DATA_TYPE='NUMBER' THEN "
-					+ "(CASE WHEN A.DATA_PRECISION IS NULL THEN A.DATA_TYPE "
-					+ "WHEN NVL(A.DATA_SCALE, 0) > 0 THEN A.DATA_TYPE||'('||A.DATA_PRECISION||','||A.DATA_SCALE||')' "
-					+ "ELSE A.DATA_TYPE||'('||A.DATA_PRECISION||')' END) "
-					+ "ELSE A.DATA_TYPE END DATA_TYPE, B.COMMENTS,DECODE(C.POSITION, '1', 'PRI') KEY "
-					+ "FROM USER_TAB_COLUMNS A INNER JOIN USER_COL_COMMENTS B ON A.TABLE_NAME = B.TABLE_NAME"
-					+ " AND A.COLUMN_NAME = B.COLUMN_NAME LEFT JOIN USER_CONSTRAINTS D "
-					+ "ON D.TABLE_NAME = A.TABLE_NAME AND D.CONSTRAINT_TYPE = 'P' "
-					+ "LEFT JOIN USER_CONS_COLUMNS C ON C.CONSTRAINT_NAME = D.CONSTRAINT_NAME "
-					+ "AND C.COLUMN_NAME=A.COLUMN_NAME WHERE A.TABLE_NAME = '%s' ",
-			"TABLE_NAME", "COMMENTS", "COLUMN_NAME", "DATA_TYPE", "COMMENTS", "KEY"),
-
-	SQL_SERVER("sql_server",
-			"select cast(name as varchar(500)) as TABLE_NAME from sysObjects where xtype='U' order by name",
-			"select name as TABLE_NAME,(select cast(value as varchar(500)) from sys.extended_properties where major_id=id and minor_id = 0) as COMMENTS from sysobjects where xtype='U'",
-			"SELECT  cast(a.NAME AS VARCHAR(500)) AS TABLE_NAME,cast(b.NAME AS VARCHAR(500)) AS COLUMN_NAME, "
-					+ "cast(c.VALUE AS VARCHAR(500)) AS COMMENTS,cast(sys.types.NAME AS VARCHAR (500)) AS DATA_TYPE,"
-					+ "(" + " SELECT CASE count(1) WHEN 1 then 'PRI' ELSE '' END"
-					+ " FROM syscolumns,sysobjects,sysindexes,sysindexkeys,systypes "
-					+ " WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id (A.NAME) AND sysobjects.xtype = 'PK'"
-					+ " AND sysobjects.parent_obj = syscolumns.id " + " AND sysindexes.id = syscolumns.id "
-					+ " AND sysobjects.NAME = sysindexes.NAME AND sysindexkeys.id = syscolumns.id "
-					+ " AND sysindexkeys.indid = sysindexes.indid "
-					+ " AND syscolumns.colid = sysindexkeys.colid AND syscolumns.NAME = B.NAME) as 'KEY'"
-					+ " FROM sys.TABLES a " + " INNER JOIN sys.COLUMNS b ON b.object_id = a.object_id "
-					+ " LEFT JOIN sys.types ON b.user_type_id = sys.types.user_type_id   "
-					+ " LEFT JOIN sys.extended_properties c ON c.major_id = b.object_id AND c.minor_id = b.column_id "
-					+ " WHERE a.NAME = '%s' ",
-			"TABLE_NAME", "COMMENTS", "COLUMN_NAME", "DATA_TYPE", "COMMENTS", "KEY"),
-
-	POSTGRE_SQL("postgre_sql", "select tablename from pg_tables where schemaname='public' ORDER BY tablename",
-			"SELECT A.tablename, obj_description(relfilenode, 'pg_class') AS comments FROM pg_tables A, pg_class B WHERE A.schemaname='public' AND A.tablename = B.relname",
-			"SELECT A.attname AS name,format_type(A.atttypid,A.atttypmod) AS type,col_description(A.attrelid,A.attnum) AS comment,(CASE C.contype WHEN 'p' THEN 'PRI' ELSE '' END) AS key"
-					+ " FROM pg_attribute A INNER JOIN pg_class B ON A.attrelid = B.oid"
-					+ " LEFT JOIN pg_constraint C ON A.attnum = C.conkey[1] WHERE B.relname = '%s' AND A.attnum>0",
-			"tablename", "comments", "name", "type", "comment", "key");
-
-	private final String dbType;
-	private final String tablesSql;
-	private final String tableCommentsSql;
-	private final String tableFieldsSql;
-	private final String tableName;
-	private final String tableComment;
-	private final String fieldName;
-	private final String fieldType;
-	private final String fieldComment;
-	private final String fieldKey;
-
-	QuerySQL(final String dbType, final String tablesSql, final String tableCommentsSql, final String tableFieldsSql,
-			final String tableName, final String tableComment, final String fieldName, final String fieldType,
-			final String fieldComment, final String fieldKey) {
-		this.dbType = dbType;
-		this.tablesSql = tablesSql;
-		this.tableCommentsSql = tableCommentsSql;
-		this.tableFieldsSql = tableFieldsSql;
-		this.tableName = tableName;
-		this.tableComment = tableComment;
-		this.fieldName = fieldName;
-		this.fieldType = fieldType;
-		this.fieldComment = fieldComment;
-		this.fieldKey = fieldKey;
-	}
-
-	public String getDbType() {
-		return dbType;
-	}
-
-	public String getTablesSql() {
-		return tablesSql;
-	}
-
-	public String getTableCommentsSql() {
-		return tableCommentsSql;
-	}
-
-	public String getTableFieldsSql() {
-		return tableFieldsSql;
-	}
-
-	public String getTableName() {
-		return tableName;
-	}
-
-	public String getTableComment() {
-		return tableComment;
-	}
-
-	public String getFieldName() {
-		return fieldName;
-	}
-
-	public String getFieldType() {
-		return fieldType;
-	}
-
-	public String getFieldComment() {
-		return fieldComment;
-	}
-
-	public String getFieldKey() {
-		return fieldKey;
-	}
+    MYSQL("mysql", "show tables", "show table status", "show full fields from %s", "NAME", "COMMENT", "FIELD", "TYPE",
+            "COMMENT", "KEY"),
+
+    ORACLE("oracle", "SELECT * FROM USER_TABLES", "SELECT * FROM USER_TAB_COMMENTS",
+            "SELECT A.COLUMN_NAME, CASE WHEN A.DATA_TYPE='NUMBER' THEN "
+                    + "(CASE WHEN A.DATA_PRECISION IS NULL THEN A.DATA_TYPE "
+                    + "WHEN NVL(A.DATA_SCALE, 0) > 0 THEN A.DATA_TYPE||'('||A.DATA_PRECISION||','||A.DATA_SCALE||')' "
+                    + "ELSE A.DATA_TYPE||'('||A.DATA_PRECISION||')' END) "
+                    + "ELSE A.DATA_TYPE END DATA_TYPE, B.COMMENTS,DECODE(C.POSITION, '1', 'PRI') KEY "
+                    + "FROM USER_TAB_COLUMNS A INNER JOIN USER_COL_COMMENTS B ON A.TABLE_NAME = B.TABLE_NAME"
+                    + " AND A.COLUMN_NAME = B.COLUMN_NAME LEFT JOIN USER_CONSTRAINTS D "
+                    + "ON D.TABLE_NAME = A.TABLE_NAME AND D.CONSTRAINT_TYPE = 'P' "
+                    + "LEFT JOIN USER_CONS_COLUMNS C ON C.CONSTRAINT_NAME = D.CONSTRAINT_NAME "
+                    + "AND C.COLUMN_NAME=A.COLUMN_NAME WHERE A.TABLE_NAME = '%s' ",
+            "TABLE_NAME", "COMMENTS", "COLUMN_NAME", "DATA_TYPE", "COMMENTS", "KEY"),
+
+    SQL_SERVER("sql_server",
+            "select cast(name as varchar(500)) as TABLE_NAME from sysObjects where xtype='U' order by name",
+            "select name as TABLE_NAME,(select cast(value as varchar(500)) from sys.extended_properties where major_id=id and minor_id = 0) as COMMENTS from sysobjects where xtype='U'",
+            "SELECT  cast(a.NAME AS VARCHAR(500)) AS TABLE_NAME,cast(b.NAME AS VARCHAR(500)) AS COLUMN_NAME, "
+                    + "cast(c.VALUE AS VARCHAR(500)) AS COMMENTS,cast(sys.types.NAME AS VARCHAR (500)) AS DATA_TYPE,"
+                    + "(" + " SELECT CASE count(1) WHEN 1 then 'PRI' ELSE '' END"
+                    + " FROM syscolumns,sysobjects,sysindexes,sysindexkeys,systypes "
+                    + " WHERE syscolumns.xusertype = systypes.xusertype AND syscolumns.id = object_id (A.NAME) AND sysobjects.xtype = 'PK'"
+                    + " AND sysobjects.parent_obj = syscolumns.id " + " AND sysindexes.id = syscolumns.id "
+                    + " AND sysobjects.NAME = sysindexes.NAME AND sysindexkeys.id = syscolumns.id "
+                    + " AND sysindexkeys.indid = sysindexes.indid "
+                    + " AND syscolumns.colid = sysindexkeys.colid AND syscolumns.NAME = B.NAME) as 'KEY'"
+                    + " FROM sys.TABLES a " + " INNER JOIN sys.COLUMNS b ON b.object_id = a.object_id "
+                    + " LEFT JOIN sys.types ON b.user_type_id = sys.types.user_type_id   "
+                    + " LEFT JOIN sys.extended_properties c ON c.major_id = b.object_id AND c.minor_id = b.column_id "
+                    + " WHERE a.NAME = '%s' ",
+            "TABLE_NAME", "COMMENTS", "COLUMN_NAME", "DATA_TYPE", "COMMENTS", "KEY"),
+
+    POSTGRE_SQL("postgre_sql", "select tablename from pg_tables where schemaname='public' ORDER BY tablename",
+            "SELECT A.tablename, obj_description(relfilenode, 'pg_class') AS comments FROM pg_tables A, pg_class B WHERE A.schemaname='public' AND A.tablename = B.relname",
+            "SELECT A.attname AS name,format_type(A.atttypid,A.atttypmod) AS type,col_description(A.attrelid,A.attnum) AS comment,(CASE C.contype WHEN 'p' THEN 'PRI' ELSE '' END) AS key"
+                    + " FROM pg_attribute A INNER JOIN pg_class B ON A.attrelid = B.oid"
+                    + " LEFT JOIN pg_constraint C ON A.attnum = C.conkey[1] WHERE B.relname = '%s' AND A.attnum>0",
+            "tablename", "comments", "name", "type", "comment", "key");
+
+    private final String dbType;
+    private final String tablesSql;
+    private final String tableCommentsSql;
+    private final String tableFieldsSql;
+    private final String tableName;
+    private final String tableComment;
+    private final String fieldName;
+    private final String fieldType;
+    private final String fieldComment;
+    private final String fieldKey;
+
+    QuerySQL(final String dbType, final String tablesSql, final String tableCommentsSql, final String tableFieldsSql,
+             final String tableName, final String tableComment, final String fieldName, final String fieldType,
+             final String fieldComment, final String fieldKey) {
+        this.dbType = dbType;
+        this.tablesSql = tablesSql;
+        this.tableCommentsSql = tableCommentsSql;
+        this.tableFieldsSql = tableFieldsSql;
+        this.tableName = tableName;
+        this.tableComment = tableComment;
+        this.fieldName = fieldName;
+        this.fieldType = fieldType;
+        this.fieldComment = fieldComment;
+        this.fieldKey = fieldKey;
+    }
+
+    public String getDbType() {
+        return dbType;
+    }
+
+    public String getTablesSql() {
+        return tablesSql;
+    }
+
+    public String getTableCommentsSql() {
+        return tableCommentsSql;
+    }
+
+    public String getTableFieldsSql() {
+        return tableFieldsSql;
+    }
+
+    public String getTableName() {
+        return tableName;
+    }
+
+    public String getTableComment() {
+        return tableComment;
+    }
+
+    public String getFieldName() {
+        return fieldName;
+    }
+
+    public String getFieldType() {
+        return fieldType;
+    }
+
+    public String getFieldComment() {
+        return fieldComment;
+    }
+
+    public String getFieldKey() {
+        return fieldKey;
+    }
 
 }

+ 894 - 897
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/AutoSqlInjector.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
@@ -59,477 +59,474 @@ import com.baomidou.mybatisplus.toolkit.TableInfoHelper;
  */
 public class AutoSqlInjector implements ISqlInjector {
 
-	private static final Log logger = LogFactory.getLog(AutoSqlInjector.class);
-
-	protected Configuration configuration;
-	protected LanguageDriver languageDriver;
-	protected MapperBuilderAssistant builderAssistant;
-
-	/**
-	 * CRUD注入后给予标识 注入过后不再注入
-	 *
-	 * @param builderAssistant
-	 * @param mapperClass
-	 */
-	public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
-		String className = mapperClass.toString();
-		Set<String> mapperRegistryCache = GlobalConfiguration.getMapperRegistryCache(builderAssistant.getConfiguration());
-		if (!mapperRegistryCache.contains(className)) {
-			inject(builderAssistant, mapperClass);
-			mapperRegistryCache.add(className);
-		}
-	}
-
-	/**
-	 * 注入单点 crudSql
-	 */
-	public void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
-		this.configuration = builderAssistant.getConfiguration();
-		this.builderAssistant = builderAssistant;
-		this.languageDriver = configuration.getDefaultScriptingLanguageInstance();
-		GlobalConfiguration globalCache = GlobalConfiguration.getGlobalConfig(configuration);
-		/*
+    private static final Log logger = LogFactory.getLog(AutoSqlInjector.class);
+
+    protected Configuration configuration;
+    protected LanguageDriver languageDriver;
+    protected MapperBuilderAssistant builderAssistant;
+
+    /**
+     * CRUD注入后给予标识 注入过后不再注入
+     *
+     * @param builderAssistant
+     * @param mapperClass
+     */
+    public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
+        String className = mapperClass.toString();
+        Set<String> mapperRegistryCache = GlobalConfiguration.getMapperRegistryCache(builderAssistant.getConfiguration());
+        if (!mapperRegistryCache.contains(className)) {
+            inject(builderAssistant, mapperClass);
+            mapperRegistryCache.add(className);
+        }
+    }
+
+    /**
+     * 注入单点 crudSql
+     */
+    public void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
+        this.configuration = builderAssistant.getConfiguration();
+        this.builderAssistant = builderAssistant;
+        this.languageDriver = configuration.getDefaultScriptingLanguageInstance();
+        GlobalConfiguration globalCache = GlobalConfiguration.getGlobalConfig(configuration);
+        /*
 		 * 驼峰设置 PLUS 配置 > 原始配置
 		 */
-		if (!globalCache.isDbColumnUnderline()) {
-			globalCache.setDbColumnUnderline(configuration.isMapUnderscoreToCamelCase());
-		}
-		Class<?> modelClass = extractModelClass(mapperClass);
-		if (modelClass != null) {
-			/**
-			 * 表信息不为空的情况
-			 */
-			TableInfo table = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
-			if (null != table) {
-				injectSql(builderAssistant, mapperClass, modelClass, table);
-			} else {
-				/**
-				 * 警告 Mybatis-Plus 默认方法不能使用
-				 */
-				logger.warn(String.format("%s ,Not found Table Detail, Cannot use Mybatis-Plus CRUD Method.",
-						modelClass.toString()));
-			}
-		}
-	}
-
-	/**
-	 * <p>
-	 * 注入SQL
-	 * </p>
-	 *
-	 * @param builderAssistant
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSql(MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		/**
-		 * #148 表信息包含主键,注入主键相关方法
-		 */
-		if (StringUtils.isNotEmpty(table.getKeyProperty())) {
+        if (!globalCache.isDbColumnUnderline()) {
+            globalCache.setDbColumnUnderline(configuration.isMapUnderscoreToCamelCase());
+        }
+        Class<?> modelClass = extractModelClass(mapperClass);
+        if (modelClass != null) {
+            /**
+             * 表信息不为空的情况
+             */
+            TableInfo table = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
+            if (null != table) {
+                injectSql(builderAssistant, mapperClass, modelClass, table);
+            } else {
+                /**
+                 * 警告 Mybatis-Plus 默认方法不能使用
+                 */
+                logger.warn(String.format("%s ,Not found Table Detail, Cannot use Mybatis-Plus CRUD Method.",
+                        modelClass.toString()));
+            }
+        }
+    }
+
+    /**
+     * <p>
+     * 注入SQL
+     * </p>
+     *
+     * @param builderAssistant
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSql(MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        /**
+         * #148 表信息包含主键,注入主键相关方法
+         */
+        if (StringUtils.isNotEmpty(table.getKeyProperty())) {
 			/* 删除 */
-			this.injectDeleteByIdSql(false, mapperClass, modelClass, table);
-			this.injectDeleteByIdSql(true, mapperClass, modelClass, table);
+            this.injectDeleteByIdSql(false, mapperClass, modelClass, table);
+            this.injectDeleteByIdSql(true, mapperClass, modelClass, table);
 			/* 修改 */
-			this.injectUpdateByIdSql(true,mapperClass, modelClass, table);
-			this.injectUpdateByIdSql(false, mapperClass, modelClass, table);
+            this.injectUpdateByIdSql(true, mapperClass, modelClass, table);
+            this.injectUpdateByIdSql(false, mapperClass, modelClass, table);
 			/* 查询 */
-			this.injectSelectByIdSql(false, mapperClass, modelClass, table);
-			this.injectSelectByIdSql(true, mapperClass, modelClass, table);
-		} else {
-			// 表不包含主键时 给予警告
-			logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.",
-					modelClass.toString()));
-		}
-		/**
-		 * 正常注入无需主键方法
-		 */
+            this.injectSelectByIdSql(false, mapperClass, modelClass, table);
+            this.injectSelectByIdSql(true, mapperClass, modelClass, table);
+        } else {
+            // 表不包含主键时 给予警告
+            logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.",
+                    modelClass.toString()));
+        }
+        /**
+         * 正常注入无需主键方法
+         */
 		/* 插入 */
-		this.injectInsertOneSql(true,mapperClass, modelClass, table);
-		this.injectInsertOneSql(false, mapperClass, modelClass, table);
+        this.injectInsertOneSql(true, mapperClass, modelClass, table);
+        this.injectInsertOneSql(false, mapperClass, modelClass, table);
 		/* 删除 */
-		this.injectDeleteSql(mapperClass, modelClass, table);
-		this.injectDeleteByMapSql(mapperClass, table);
+        this.injectDeleteSql(mapperClass, modelClass, table);
+        this.injectDeleteByMapSql(mapperClass, table);
 		/* 修改 */
-		this.injectUpdateSql(mapperClass, modelClass, table);
+        this.injectUpdateSql(mapperClass, modelClass, table);
 		/* 查询 */
-		this.injectSelectByMapSql(mapperClass, modelClass, table);
-		this.injectSelectOneSql(mapperClass, modelClass, table);
-		this.injectSelectCountSql(mapperClass, modelClass, table);
-		this.injectSelectListSql(SqlMethod.SELECT_LIST, mapperClass, modelClass, table);
-		this.injectSelectListSql(SqlMethod.SELECT_PAGE, mapperClass, modelClass, table);
-		this.injectSelectMapsSql(SqlMethod.SELECT_MAPS, mapperClass, modelClass, table);
-		this.injectSelectMapsSql(SqlMethod.SELECT_MAPS_PAGE, mapperClass, modelClass, table);
-		this.injectSelectObjsSql(SqlMethod.SELECT_OBJS, mapperClass, modelClass, table);
+        this.injectSelectByMapSql(mapperClass, modelClass, table);
+        this.injectSelectOneSql(mapperClass, modelClass, table);
+        this.injectSelectCountSql(mapperClass, modelClass, table);
+        this.injectSelectListSql(SqlMethod.SELECT_LIST, mapperClass, modelClass, table);
+        this.injectSelectListSql(SqlMethod.SELECT_PAGE, mapperClass, modelClass, table);
+        this.injectSelectMapsSql(SqlMethod.SELECT_MAPS, mapperClass, modelClass, table);
+        this.injectSelectMapsSql(SqlMethod.SELECT_MAPS_PAGE, mapperClass, modelClass, table);
+        this.injectSelectObjsSql(SqlMethod.SELECT_OBJS, mapperClass, modelClass, table);
 		/* 自定义方法 */
-		this.inject(configuration, builderAssistant, mapperClass, modelClass, table);
-	}
-
-	/**
-	 * 自定义方法,注入点(子类需重写该方法)
-	 */
-	public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass,
-					   Class<?> modelClass, TableInfo table) {
-		// to do nothing
-	}
-
-	/**
-	 * 避免扫描到BaseMapper
-	 *
-	 * @param mapperClass
-	 * @return
-	 */
-	protected Class<?> extractModelClass(Class<?> mapperClass) {
-		if (mapperClass == BaseMapper.class) {
-			logger.warn(" Current Class is BaseMapper ");
-			return null;
-		} else {
-			Type[] types = mapperClass.getGenericInterfaces();
-			ParameterizedType target = null;
-			for (Type type : types) {
-				if (type instanceof ParameterizedType && BaseMapper.class.isAssignableFrom(mapperClass)) {
-					target = (ParameterizedType) type;
-					break;
-				}
-			}
-			return (Class<?>) target.getActualTypeArguments()[0];
-		}
-	}
-
-	/**
-	 * <p>
-	 * 注入插入 SQL 语句
-	 * </p>
-	 *
-	 * @param selective
-	 *            是否选择插入
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectInsertOneSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        this.inject(configuration, builderAssistant, mapperClass, modelClass, table);
+    }
+
+    /**
+     * 自定义方法,注入点(子类需重写该方法)
+     */
+    public void inject(Configuration configuration, MapperBuilderAssistant builderAssistant, Class<?> mapperClass,
+                       Class<?> modelClass, TableInfo table) {
+        // to do nothing
+    }
+
+    /**
+     * 避免扫描到BaseMapper
+     *
+     * @param mapperClass
+     * @return
+     */
+    protected Class<?> extractModelClass(Class<?> mapperClass) {
+        if (mapperClass == BaseMapper.class) {
+            logger.warn(" Current Class is BaseMapper ");
+            return null;
+        } else {
+            Type[] types = mapperClass.getGenericInterfaces();
+            ParameterizedType target = null;
+            for (Type type : types) {
+                if (type instanceof ParameterizedType && BaseMapper.class.isAssignableFrom(mapperClass)) {
+                    target = (ParameterizedType) type;
+                    break;
+                }
+            }
+            return (Class<?>) target.getActualTypeArguments()[0];
+        }
+    }
+
+    /**
+     * <p>
+     * 注入插入 SQL 语句
+     * </p>
+     *
+     * @param selective
+     *            是否选择插入
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectInsertOneSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
 		/*
 		 * INSERT INTO table <trim prefix="(" suffix=")" suffixOverrides=",">
 		 * <if test="xx != null">xx,</if> </trim> <trim prefix="values ("
 		 * suffix=")" suffixOverrides=","> <if test="xx != null">#{xx},</if>
 		 * </trim>
 		 */
-		KeyGenerator keyGenerator = new NoKeyGenerator();
-		StringBuilder fieldBuilder = new StringBuilder();
-		StringBuilder placeholderBuilder = new StringBuilder();
-		SqlMethod sqlMethod = selective ? SqlMethod.INSERT_ONE :  SqlMethod.INSERT_ONE_ALL_COLUMN;
-
-		fieldBuilder.append("\n<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
-		placeholderBuilder.append("\n<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
-		String keyProperty = null;
-		String keyColumn = null;
-
-		// 表包含主键处理逻辑,如果不包含主键当普通字段处理
-		if (StringUtils.isNotEmpty(table.getKeyProperty())) {
-			if (table.getIdType() == IdType.AUTO) {
+        KeyGenerator keyGenerator = new NoKeyGenerator();
+        StringBuilder fieldBuilder = new StringBuilder();
+        StringBuilder placeholderBuilder = new StringBuilder();
+        SqlMethod sqlMethod = selective ? SqlMethod.INSERT_ONE : SqlMethod.INSERT_ONE_ALL_COLUMN;
+
+        fieldBuilder.append("\n<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
+        placeholderBuilder.append("\n<trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n");
+        String keyProperty = null;
+        String keyColumn = null;
+
+        // 表包含主键处理逻辑,如果不包含主键当普通字段处理
+        if (StringUtils.isNotEmpty(table.getKeyProperty())) {
+            if (table.getIdType() == IdType.AUTO) {
 				/* 自增主键 */
-				keyGenerator = new Jdbc3KeyGenerator();
-				keyProperty = table.getKeyProperty();
-				keyColumn = table.getKeyColumn();
-			} else {
+                keyGenerator = new Jdbc3KeyGenerator();
+                keyProperty = table.getKeyProperty();
+                keyColumn = table.getKeyColumn();
+            } else {
 				/* 用户输入自定义ID */
-				fieldBuilder.append(table.getKeyColumn()).append(",");
-				placeholderBuilder.append("#{").append(table.getKeyProperty()).append("},");
-			}
-		}
-
-		List<TableFieldInfo> fieldList = table.getFieldList();
-
-		for (TableFieldInfo fieldInfo : fieldList) {
-			if(selective){
-				fieldBuilder.append(convertIfTagIgnored(fieldInfo, false));
-				fieldBuilder.append(fieldInfo.getColumn()).append(",");
-				fieldBuilder.append(convertIfTagIgnored(fieldInfo, true));
-				placeholderBuilder.append(convertIfTagIgnored(fieldInfo, false));
-				placeholderBuilder.append("#{").append(fieldInfo.getEl()).append("},");
-				placeholderBuilder.append(convertIfTagIgnored(fieldInfo, true));
-			}else{
-				fieldBuilder.append(fieldInfo.getColumn()).append(",");
-				placeholderBuilder.append("#{").append(fieldInfo.getEl()).append("},");
-			}
-		}
-		fieldBuilder.append("\n</trim>");
-		placeholderBuilder.append("\n</trim>");
-		String sql = String.format(sqlMethod.getSql(), table.getTableName(), fieldBuilder.toString(),
-				placeholderBuilder.toString());
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource, keyGenerator, keyProperty,
-				keyColumn);
-	}
-
-	/**
-	 * <p>
-	 * 注入 entity 条件删除 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectDeleteSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.DELETE;
-		String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereEntityWrapper(table));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
-	}
-
-	/**
-	 * <p>
-	 * 注入 map 条件删除 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param table
-	 */
-	protected void injectDeleteByMapSql(Class<?> mapperClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.DELETE_BY_MAP;
-		String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereByMap());
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
-		this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
-	}
-
-	/**
-	 * <p>
-	 * 注入删除 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectDeleteByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.DELETE_BY_ID;
-		SqlSource sqlSource;
-		if (batch) {
-			sqlMethod = SqlMethod.DELETE_BATCH_BY_IDS;
-			StringBuilder ids = new StringBuilder();
-			ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">");
-			ids.append("#{item}");
-			ids.append("\n</foreach>");
-			String sql = String.format(sqlMethod.getSql(), table.getTableName(), table.getKeyColumn(), ids.toString());
-			sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		} else {
-			String sql = String.format(sqlMethod.getSql(), table.getTableName(), table.getKeyColumn(), table.getKeyColumn());
-			sqlSource = new RawSqlSource(configuration, sql, Object.class);
-		}
-		this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
-	}
-
-	/**
-	 * <p>
-	 * 注入更新 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectUpdateByIdSql(boolean selective,Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod =selective ?  SqlMethod.UPDATE_BY_ID : SqlMethod.UPDATE_ALL_COLUMN_BY_ID;
-        String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(selective, table,null), table.getKeyColumn(),
+                fieldBuilder.append(table.getKeyColumn()).append(",");
+                placeholderBuilder.append("#{").append(table.getKeyProperty()).append("},");
+            }
+        }
+
+        List<TableFieldInfo> fieldList = table.getFieldList();
+
+        for (TableFieldInfo fieldInfo : fieldList) {
+            if (selective) {
+                fieldBuilder.append(convertIfTagIgnored(fieldInfo, false));
+                fieldBuilder.append(fieldInfo.getColumn()).append(",");
+                fieldBuilder.append(convertIfTagIgnored(fieldInfo, true));
+                placeholderBuilder.append(convertIfTagIgnored(fieldInfo, false));
+                placeholderBuilder.append("#{").append(fieldInfo.getEl()).append("},");
+                placeholderBuilder.append(convertIfTagIgnored(fieldInfo, true));
+            } else {
+                fieldBuilder.append(fieldInfo.getColumn()).append(",");
+                placeholderBuilder.append("#{").append(fieldInfo.getEl()).append("},");
+            }
+        }
+        fieldBuilder.append("\n</trim>");
+        placeholderBuilder.append("\n</trim>");
+        String sql = String.format(sqlMethod.getSql(), table.getTableName(), fieldBuilder.toString(),
+                placeholderBuilder.toString());
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addInsertMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource, keyGenerator, keyProperty,
+                keyColumn);
+    }
+
+    /**
+     * <p>
+     * 注入 entity 条件删除 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectDeleteSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.DELETE;
+        String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereEntityWrapper(table));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
+    }
+
+    /**
+     * <p>
+     * 注入 map 条件删除 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param table
+     */
+    protected void injectDeleteByMapSql(Class<?> mapperClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.DELETE_BY_MAP;
+        String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereByMap());
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
+        this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
+    }
+
+    /**
+     * <p>
+     * 注入删除 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectDeleteByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.DELETE_BY_ID;
+        SqlSource sqlSource;
+        if (batch) {
+            sqlMethod = SqlMethod.DELETE_BATCH_BY_IDS;
+            StringBuilder ids = new StringBuilder();
+            ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">");
+            ids.append("#{item}");
+            ids.append("\n</foreach>");
+            String sql = String.format(sqlMethod.getSql(), table.getTableName(), table.getKeyColumn(), ids.toString());
+            sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        } else {
+            String sql = String.format(sqlMethod.getSql(), table.getTableName(), table.getKeyColumn(), table.getKeyColumn());
+            sqlSource = new RawSqlSource(configuration, sql, Object.class);
+        }
+        this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);
+    }
+
+    /**
+     * <p>
+     * 注入更新 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectUpdateByIdSql(boolean selective, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = selective ? SqlMethod.UPDATE_BY_ID : SqlMethod.UPDATE_ALL_COLUMN_BY_ID;
+        String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(selective, table, null), table.getKeyColumn(),
                 table.getKeyProperty());
         SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
         this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
-	}
-
-	/**
-	 * <p>
-	 * 注入批量更新 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectUpdateSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.UPDATE;
-		String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(true,table, "et."), sqlWhereEntityWrapper(table));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
-	}
-
-	/**
-	 * <p>
-	 * 注入查询 SQL 语句
-	 * </p>
-	 *
-	 * @param batch
-	 *            是否为批量插入
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID;
-		SqlSource sqlSource;
-		if (batch) {
-			sqlMethod = SqlMethod.SELECT_BATCH_BY_IDS;
-			StringBuilder ids = new StringBuilder();
-			ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">");
-			ids.append("#{item}");
-			ids.append("\n</foreach>");
-			sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(),
-					sqlSelectColumns(table, false), table.getTableName(), table.getKeyColumn(), ids.toString()), modelClass);
-		} else {
-			sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(table, false),
-					table.getTableName(), table.getKeyColumn(), table.getKeyProperty()), Object.class);
-		}
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
-	}
-
-	/**
-	 * <p>
-	 * 注入 map 查询 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectByMapSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.SELECT_BY_MAP;
-		String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(), sqlWhereByMap());
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
-	}
-
-	/**
-	 * <p>
-	 * 注入实体查询一条记录 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectOneSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.SELECT_ONE;
-		String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(),
-				sqlWhere(table, false));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
-	}
-
-	/**
-	 * <p>
-	 * 注入EntityWrapper方式查询记录列表 SQL 语句
-	 * </p>
-	 *
-	 * @param sqlMethod
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectListSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, true), table.getTableName(),
-				sqlWhereEntityWrapper(table));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
-	}
-
-	/**
-	 * <p>
-	 * 注入EntityWrapper方式查询记录列表 SQL 语句
-	 * </p>
-	 *
-	 * @param sqlMethod
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectMapsSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, true), table.getTableName(),
-				sqlWhereEntityWrapper(table));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class, table);
-	}
-
-	/**
-	 * <p>
-	 * 注入EntityWrapper方式查询记录列表 SQL 语句
-	 * </p>
-	 *
-	 * @param sqlMethod
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectObjsSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		String sql = String.format(sqlMethod.getSql(), sqlSelectObjsColumns(table), table.getTableName(),
-				sqlWhereEntityWrapper(table));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Object.class, table);
-	}
-
-	/**
-	 * <p>
-	 * 注入EntityWrapper查询总记录数 SQL 语句
-	 * </p>
-	 *
-	 * @param mapperClass
-	 * @param modelClass
-	 * @param table
-	 */
-	protected void injectSelectCountSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
-		SqlMethod sqlMethod = SqlMethod.SELECT_COUNT;
-		String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereEntityWrapper(table));
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
-		this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Integer.class, null);
-	}
-
-	/**
-	 * <p>
-	 * EntityWrapper方式获取select where
-	 * </p>
-	 *
-	 * @param table
-	 * @return String
-	 */
-	protected String sqlWhereEntityWrapper(TableInfo table) {
-		StringBuilder where = new StringBuilder("\n<if test=\"ew!=null\">");
-		where.append("\n<if test=\"ew.entity!=null\">\n<where>");
-		if (StringUtils.isNotEmpty(table.getKeyProperty())) {
-			where.append("\n<if test=\"ew.entity.").append(table.getKeyProperty()).append("!=null\">\n");
-			where.append(table.getKeyColumn()).append("=#{ew.entity.").append(table.getKeyProperty()).append("}");
-			where.append("\n</if>");
-		}
-		List<TableFieldInfo> fieldList = table.getFieldList();
-		for (TableFieldInfo fieldInfo : fieldList) {
-			where.append(convertIfTag(fieldInfo, "ew.entity.", false));
-			where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.entity.").append(fieldInfo.getEl()).append("}");
-			where.append(convertIfTag(fieldInfo, true));
-		}
-		where.append("\n</where>\n</if>");
-		where.append("\n<if test=\"ew.sqlSegment!=null\">\n${ew.sqlSegment}\n</if>");
-		where.append("\n</if>");
-		return where.toString();
-	}
-
-
-
-
-
-	/**
-	 * <p>
-	 * SQL 更新 set 语句
-	 * </p>
-	 *
-	 * @param table
-	 * @param prefix
-	 *            前缀
-	 * @return
-	 */
-	protected String sqlSet(boolean selective,TableInfo table, String prefix) {
-		StringBuilder set = new StringBuilder();
-		set.append("<trim prefix=\"SET\" suffixOverrides=\",\">");
-		List<TableFieldInfo> fieldList = table.getFieldList();
-		for (TableFieldInfo fieldInfo : fieldList) {
-            if (selective){
+    }
+
+    /**
+     * <p>
+     * 注入批量更新 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectUpdateSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.UPDATE;
+        String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlSet(true, table, "et."), sqlWhereEntityWrapper(table));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addUpdateMappedStatement(mapperClass, modelClass, sqlMethod.getMethod(), sqlSource);
+    }
+
+    /**
+     * <p>
+     * 注入查询 SQL 语句
+     * </p>
+     *
+     * @param batch
+     *            是否为批量插入
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectByIdSql(boolean batch, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.SELECT_BY_ID;
+        SqlSource sqlSource;
+        if (batch) {
+            sqlMethod = SqlMethod.SELECT_BATCH_BY_IDS;
+            StringBuilder ids = new StringBuilder();
+            ids.append("\n<foreach item=\"item\" index=\"index\" collection=\"list\" separator=\",\">");
+            ids.append("#{item}");
+            ids.append("\n</foreach>");
+            sqlSource = languageDriver.createSqlSource(configuration, String.format(sqlMethod.getSql(),
+                    sqlSelectColumns(table, false), table.getTableName(), table.getKeyColumn(), ids.toString()), modelClass);
+        } else {
+            sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(), sqlSelectColumns(table, false),
+                    table.getTableName(), table.getKeyColumn(), table.getKeyProperty()), Object.class);
+        }
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
+    }
+
+    /**
+     * <p>
+     * 注入 map 查询 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectByMapSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.SELECT_BY_MAP;
+        String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(), sqlWhereByMap());
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Map.class);
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
+    }
+
+    /**
+     * <p>
+     * 注入实体查询一条记录 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectOneSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.SELECT_ONE;
+        String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, false), table.getTableName(),
+                sqlWhere(table, false));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
+    }
+
+    /**
+     * <p>
+     * 注入EntityWrapper方式查询记录列表 SQL 语句
+     * </p>
+     *
+     * @param sqlMethod
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectListSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, true), table.getTableName(),
+                sqlWhereEntityWrapper(table));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, table);
+    }
+
+    /**
+     * <p>
+     * 注入EntityWrapper方式查询记录列表 SQL 语句
+     * </p>
+     *
+     * @param sqlMethod
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectMapsSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        String sql = String.format(sqlMethod.getSql(), sqlSelectColumns(table, true), table.getTableName(),
+                sqlWhereEntityWrapper(table));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Map.class, table);
+    }
+
+    /**
+     * <p>
+     * 注入EntityWrapper方式查询记录列表 SQL 语句
+     * </p>
+     *
+     * @param sqlMethod
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectObjsSql(SqlMethod sqlMethod, Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        String sql = String.format(sqlMethod.getSql(), sqlSelectObjsColumns(table), table.getTableName(),
+                sqlWhereEntityWrapper(table));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Object.class, table);
+    }
+
+    /**
+     * <p>
+     * 注入EntityWrapper查询总记录数 SQL 语句
+     * </p>
+     *
+     * @param mapperClass
+     * @param modelClass
+     * @param table
+     */
+    protected void injectSelectCountSql(Class<?> mapperClass, Class<?> modelClass, TableInfo table) {
+        SqlMethod sqlMethod = SqlMethod.SELECT_COUNT;
+        String sql = String.format(sqlMethod.getSql(), table.getTableName(), sqlWhereEntityWrapper(table));
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
+        this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, Integer.class, null);
+    }
+
+    /**
+     * <p>
+     * EntityWrapper方式获取select where
+     * </p>
+     *
+     * @param table
+     * @return String
+     */
+    protected String sqlWhereEntityWrapper(TableInfo table) {
+        StringBuilder where = new StringBuilder("\n<if test=\"ew!=null\">");
+        where.append("\n<if test=\"ew.entity!=null\">\n<where>");
+        if (StringUtils.isNotEmpty(table.getKeyProperty())) {
+            where.append("\n<if test=\"ew.entity.").append(table.getKeyProperty()).append("!=null\">\n");
+            where.append(table.getKeyColumn()).append("=#{ew.entity.").append(table.getKeyProperty()).append("}");
+            where.append("\n</if>");
+        }
+        List<TableFieldInfo> fieldList = table.getFieldList();
+        for (TableFieldInfo fieldInfo : fieldList) {
+            where.append(convertIfTag(fieldInfo, "ew.entity.", false));
+            where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.entity.").append(fieldInfo.getEl()).append("}");
+            where.append(convertIfTag(fieldInfo, true));
+        }
+        where.append("\n</where>\n</if>");
+        where.append("\n<if test=\"ew.sqlSegment!=null\">\n${ew.sqlSegment}\n</if>");
+        where.append("\n</if>");
+        return where.toString();
+    }
+
+
+    /**
+     * <p>
+     * SQL 更新 set 语句
+     * </p>
+     *
+     * @param table
+     * @param prefix
+     *            前缀
+     * @return
+     */
+    protected String sqlSet(boolean selective, TableInfo table, String prefix) {
+        StringBuilder set = new StringBuilder();
+        set.append("<trim prefix=\"SET\" suffixOverrides=\",\">");
+        List<TableFieldInfo> fieldList = table.getFieldList();
+        for (TableFieldInfo fieldInfo : fieldList) {
+            if (selective) {
                 set.append(convertIfTag(true, fieldInfo, prefix, false));
                 set.append(fieldInfo.getColumn()).append("=#{");
                 if (null != prefix) {
@@ -537,475 +534,475 @@ public class AutoSqlInjector implements ISqlInjector {
                 }
                 set.append(fieldInfo.getEl()).append("},");
                 set.append(convertIfTag(true, fieldInfo, null, true));
-            }else{
+            } else {
                 set.append(fieldInfo.getColumn()).append("=#{");
                 if (null != prefix) {
                     set.append(prefix);
                 }
                 set.append(fieldInfo.getEl()).append("},");
             }
-		}
-		set.append("\n</trim>");
-		return set.toString();
-	}
-
-	/**
-	 * <p>
-	 * 获取需要转义的SQL字段
-	 * </p>
-	 *
-	 * @param convertStr
-	 * @return
-	 */
-	protected String sqlWordConvert(String convertStr) {
-		GlobalConfiguration globalConfig = GlobalConfiguration.getGlobalConfig(configuration);
-		return SqlReservedWords.convert(globalConfig, convertStr);
-	}
-
-	/**
-	 * <p>
-	 * SQL 查询所有表字段
-	 * </p>
-	 *
-	 * @param table
-	 * @param entityWrapper
-	 *            是否为包装类型查询
-	 * @return
-	 */
-	protected String sqlSelectColumns(TableInfo table, boolean entityWrapper) {
-		StringBuilder columns = new StringBuilder();
-		if (null != table.getResultMap()) {
+        }
+        set.append("\n</trim>");
+        return set.toString();
+    }
+
+    /**
+     * <p>
+     * 获取需要转义的SQL字段
+     * </p>
+     *
+     * @param convertStr
+     * @return
+     */
+    protected String sqlWordConvert(String convertStr) {
+        GlobalConfiguration globalConfig = GlobalConfiguration.getGlobalConfig(configuration);
+        return SqlReservedWords.convert(globalConfig, convertStr);
+    }
+
+    /**
+     * <p>
+     * SQL 查询所有表字段
+     * </p>
+     *
+     * @param table
+     * @param entityWrapper
+     *            是否为包装类型查询
+     * @return
+     */
+    protected String sqlSelectColumns(TableInfo table, boolean entityWrapper) {
+        StringBuilder columns = new StringBuilder();
+        if (null != table.getResultMap()) {
 			/*
 			 * 存在 resultMap 映射返回
 			 */
-			if (entityWrapper) {
-				columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>");
-			}
-			columns.append("*");
-			if (entityWrapper) {
-				columns.append("</otherwise></choose>");
-			}
-		} else {
+            if (entityWrapper) {
+                columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>");
+            }
+            columns.append("*");
+            if (entityWrapper) {
+                columns.append("</otherwise></choose>");
+            }
+        } else {
 			/*
 			 * 普通查询
 			 */
-			if (entityWrapper) {
-				columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>");
-			}
-			List<TableFieldInfo> fieldList = table.getFieldList();
-			int _size = 0;
-			if (null != fieldList) {
-				_size = fieldList.size();
-			}
-
-			// 主键处理
-			if (StringUtils.isNotEmpty(table.getKeyProperty())) {
-				if (table.isKeyRelated()) {
-					columns.append(table.getKeyColumn()).append(" AS ").append(sqlWordConvert(table.getKeyProperty()));
-				} else {
-					columns.append(sqlWordConvert(table.getKeyProperty()));
-				}
-				if (_size >= 1) {
-					// 判断其余字段是否存在
-					columns.append(",");
-				}
-			}
-
-			if (_size >= 1) {
-				// 字段处理
-				int i = 0;
-				Iterator<TableFieldInfo> iterator = fieldList.iterator();
-				while (iterator.hasNext()) {
-					TableFieldInfo fieldInfo = iterator.next();
-					// 匹配转换内容
-					String wordConvert = sqlWordConvert(fieldInfo.getProperty());
-					if (fieldInfo.getColumn().equals(wordConvert)) {
-						columns.append(wordConvert);
-					} else {
-						// 字段属性不一致
-						columns.append(fieldInfo.getColumn());
-						columns.append(" AS ").append(wordConvert);
-					}
-					if (i + 1 < _size) {
-						columns.append(",");
-					}
-					i++;
-				}
-			}
-			if (entityWrapper) {
-				columns.append("</otherwise></choose>");
-			}
-		}
+            if (entityWrapper) {
+                columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>");
+            }
+            List<TableFieldInfo> fieldList = table.getFieldList();
+            int _size = 0;
+            if (null != fieldList) {
+                _size = fieldList.size();
+            }
+
+            // 主键处理
+            if (StringUtils.isNotEmpty(table.getKeyProperty())) {
+                if (table.isKeyRelated()) {
+                    columns.append(table.getKeyColumn()).append(" AS ").append(sqlWordConvert(table.getKeyProperty()));
+                } else {
+                    columns.append(sqlWordConvert(table.getKeyProperty()));
+                }
+                if (_size >= 1) {
+                    // 判断其余字段是否存在
+                    columns.append(",");
+                }
+            }
+
+            if (_size >= 1) {
+                // 字段处理
+                int i = 0;
+                Iterator<TableFieldInfo> iterator = fieldList.iterator();
+                while (iterator.hasNext()) {
+                    TableFieldInfo fieldInfo = iterator.next();
+                    // 匹配转换内容
+                    String wordConvert = sqlWordConvert(fieldInfo.getProperty());
+                    if (fieldInfo.getColumn().equals(wordConvert)) {
+                        columns.append(wordConvert);
+                    } else {
+                        // 字段属性不一致
+                        columns.append(fieldInfo.getColumn());
+                        columns.append(" AS ").append(wordConvert);
+                    }
+                    if (i + 1 < _size) {
+                        columns.append(",");
+                    }
+                    i++;
+                }
+            }
+            if (entityWrapper) {
+                columns.append("</otherwise></choose>");
+            }
+        }
 
 		/*
 		 * 返回所有查询字段内容
 		 */
-		return columns.toString();
-	}
-
-	/**
-	 * <p>
-	 * SQL 设置selectObj sqlselect
-	 * </p>
-	 *
-	 * @param table
-	 *            是否为包装类型查询
-	 * @return
-	 */
-	protected String sqlSelectObjsColumns(TableInfo table) {
-		StringBuilder columns = new StringBuilder();
+        return columns.toString();
+    }
+
+    /**
+     * <p>
+     * SQL 设置selectObj sqlselect
+     * </p>
+     *
+     * @param table
+     *            是否为包装类型查询
+     * @return
+     */
+    protected String sqlSelectObjsColumns(TableInfo table) {
+        StringBuilder columns = new StringBuilder();
 		/*
 		 * 普通查询
 		 */
-		columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>");
-		List<TableFieldInfo> fieldList = table.getFieldList();
-		// 主键处理
-		if (StringUtils.isNotEmpty(table.getKeyProperty())) {
-			if (table.isKeyRelated()) {
-				columns.append(table.getKeyColumn()).append(" AS ").append(sqlWordConvert(table.getKeyProperty()));
-			} else {
-				columns.append(sqlWordConvert(table.getKeyProperty()));
-			}
-		} else {
-			TableFieldInfo fieldInfo = fieldList.get(0);
-			// 匹配转换内容
-			String wordConvert = sqlWordConvert(fieldInfo.getProperty());
-			if (fieldInfo.getColumn().equals(wordConvert)) {
-				columns.append(wordConvert);
-			} else {
-				// 字段属性不一致
-				columns.append(fieldInfo.getColumn());
-				columns.append(" AS ").append(wordConvert);
-			}
-		}
-		columns.append("</otherwise></choose>");
-		return columns.toString();
-	}
-
-	/**
-	 * <p>
-	 * SQL 查询条件
-	 * </p>
-	 *
-	 * @param table
-	 * @param space
-	 *            是否为空判断
-	 * @return
-	 */
-	protected String sqlWhere(TableInfo table, boolean space) {
-		StringBuilder where = new StringBuilder();
-		if (space) {
-			where.append("\n<if test=\"ew!=null\">");
-		}
-		where.append("\n<where>");
-		if (StringUtils.isNotEmpty(table.getKeyProperty())) {
-			where.append("\n<if test=\"ew.").append(table.getKeyProperty()).append("!=null\">\n");
-			where.append(table.getKeyColumn()).append("=#{ew.").append(table.getKeyProperty()).append("}");
-			where.append("\n</if>");
-		}
-		List<TableFieldInfo> fieldList = table.getFieldList();
-		for (TableFieldInfo fieldInfo : fieldList) {
-			where.append(convertIfTag(fieldInfo, "ew.", false));
-			where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.").append(fieldInfo.getEl()).append("}");
-			where.append(convertIfTag(fieldInfo, true));
-		}
-		where.append("\n</where>");
-		if (space) {
-			where.append("\n</if>");
-		}
-		return where.toString();
-	}
-
-	/**
-	 * <p>
-	 * SQL map 查询条件
-	 * </p>
-	 */
-	protected String sqlWhereByMap() {
-		StringBuilder where = new StringBuilder();
-		where.append("\n<if test=\"cm!=null and !cm.isEmpty\">");
-		where.append("\n<where>");
-		where.append("\n<foreach collection=\"cm.keys\" item=\"k\" separator=\"AND\">");
-		where.append("\n<if test=\"cm[k] != null\">");
-		String quote = GlobalConfiguration.getIdentifierQuote(configuration);
-		if (StringUtils.isNotEmpty(quote)) {
-			where.append("\n");
-			where.append(quote);
-			where.append("${k}");
-			where.append(quote);
-			where.append(" = #{cm[${k}]}");
-		} else {
-			where.append("\n${k} = #{cm[${k}]}");
-		}
-		where.append("\n</if>");
-		where.append("\n</foreach>");
-		where.append("\n</where>");
-		where.append("\n</if>");
-		return where.toString();
-	}
-
-	/**
-	 * <p>
-	 * IF 条件转换方法
-	 * </p>
-	 *
-	 * @param ignored
-	 *            允许忽略
-	 * @param fieldInfo
-	 *            字段信息
-	 * @param prefix
-	 *            条件前缀
-	 * @param close
-	 *            是否闭合标签
-	 * @return
-	 */
-	protected String convertIfTag(boolean ignored, TableFieldInfo fieldInfo, String prefix, boolean close) {
+        columns.append("<choose><when test=\"ew != null and ew.sqlSelect != null\">${ew.sqlSelect}</when><otherwise>");
+        List<TableFieldInfo> fieldList = table.getFieldList();
+        // 主键处理
+        if (StringUtils.isNotEmpty(table.getKeyProperty())) {
+            if (table.isKeyRelated()) {
+                columns.append(table.getKeyColumn()).append(" AS ").append(sqlWordConvert(table.getKeyProperty()));
+            } else {
+                columns.append(sqlWordConvert(table.getKeyProperty()));
+            }
+        } else {
+            TableFieldInfo fieldInfo = fieldList.get(0);
+            // 匹配转换内容
+            String wordConvert = sqlWordConvert(fieldInfo.getProperty());
+            if (fieldInfo.getColumn().equals(wordConvert)) {
+                columns.append(wordConvert);
+            } else {
+                // 字段属性不一致
+                columns.append(fieldInfo.getColumn());
+                columns.append(" AS ").append(wordConvert);
+            }
+        }
+        columns.append("</otherwise></choose>");
+        return columns.toString();
+    }
+
+    /**
+     * <p>
+     * SQL 查询条件
+     * </p>
+     *
+     * @param table
+     * @param space
+     *            是否为空判断
+     * @return
+     */
+    protected String sqlWhere(TableInfo table, boolean space) {
+        StringBuilder where = new StringBuilder();
+        if (space) {
+            where.append("\n<if test=\"ew!=null\">");
+        }
+        where.append("\n<where>");
+        if (StringUtils.isNotEmpty(table.getKeyProperty())) {
+            where.append("\n<if test=\"ew.").append(table.getKeyProperty()).append("!=null\">\n");
+            where.append(table.getKeyColumn()).append("=#{ew.").append(table.getKeyProperty()).append("}");
+            where.append("\n</if>");
+        }
+        List<TableFieldInfo> fieldList = table.getFieldList();
+        for (TableFieldInfo fieldInfo : fieldList) {
+            where.append(convertIfTag(fieldInfo, "ew.", false));
+            where.append(" AND ").append(fieldInfo.getColumn()).append("=#{ew.").append(fieldInfo.getEl()).append("}");
+            where.append(convertIfTag(fieldInfo, true));
+        }
+        where.append("\n</where>");
+        if (space) {
+            where.append("\n</if>");
+        }
+        return where.toString();
+    }
+
+    /**
+     * <p>
+     * SQL map 查询条件
+     * </p>
+     */
+    protected String sqlWhereByMap() {
+        StringBuilder where = new StringBuilder();
+        where.append("\n<if test=\"cm!=null and !cm.isEmpty\">");
+        where.append("\n<where>");
+        where.append("\n<foreach collection=\"cm.keys\" item=\"k\" separator=\"AND\">");
+        where.append("\n<if test=\"cm[k] != null\">");
+        String quote = GlobalConfiguration.getIdentifierQuote(configuration);
+        if (StringUtils.isNotEmpty(quote)) {
+            where.append("\n");
+            where.append(quote);
+            where.append("${k}");
+            where.append(quote);
+            where.append(" = #{cm[${k}]}");
+        } else {
+            where.append("\n${k} = #{cm[${k}]}");
+        }
+        where.append("\n</if>");
+        where.append("\n</foreach>");
+        where.append("\n</where>");
+        where.append("\n</if>");
+        return where.toString();
+    }
+
+    /**
+     * <p>
+     * IF 条件转换方法
+     * </p>
+     *
+     * @param ignored
+     *            允许忽略
+     * @param fieldInfo
+     *            字段信息
+     * @param prefix
+     *            条件前缀
+     * @param close
+     *            是否闭合标签
+     * @return
+     */
+    protected String convertIfTag(boolean ignored, TableFieldInfo fieldInfo, String prefix, boolean close) {
 		/* 忽略策略 */
-		FieldStrategy fieldStrategy = fieldInfo.getFieldStrategy();
-		if (fieldStrategy == FieldStrategy.IGNORED) {
-			if (ignored) {
-				return "";
-			}
-			// 查询策略,使用全局策略
-			fieldStrategy = GlobalConfiguration.getGlobalConfig(configuration).getFieldStrategy();
-		}
-
-		// 关闭标签
-		if (close) {
-			return "</if>";
-		}
+        FieldStrategy fieldStrategy = fieldInfo.getFieldStrategy();
+        if (fieldStrategy == FieldStrategy.IGNORED) {
+            if (ignored) {
+                return "";
+            }
+            // 查询策略,使用全局策略
+            fieldStrategy = GlobalConfiguration.getGlobalConfig(configuration).getFieldStrategy();
+        }
+
+        // 关闭标签
+        if (close) {
+            return "</if>";
+        }
 
 		/* 前缀处理 */
-		String property = fieldInfo.getProperty();
-		if (null != prefix) {
-			property = prefix + property;
-		}
-
-		// 验证逻辑
-		if (fieldStrategy == FieldStrategy.NOT_EMPTY) {
-			String propertyType = fieldInfo.getPropertyType();
-			if (StringUtils.isCharSequence(propertyType)) {
-				return String.format("\n\t<if test=\"%s!=null and %s!=''\">", property, property);
-			} else {
-				return String.format("\n\t<if test=\"%s!=null \">", property);
-			}
-		} else {
-			// FieldStrategy.NOT_NULL
-			return String.format("\n\t<if test=\"%s!=null\">", property);
-		}
-	}
-
-	protected String convertIfTagIgnored(TableFieldInfo fieldInfo, boolean colse) {
-		return convertIfTag(true, fieldInfo, null, colse);
-	}
-
-	protected String convertIfTag(TableFieldInfo fieldInfo, String prefix, boolean colse) {
-		return convertIfTag(false, fieldInfo, prefix, colse);
-	}
-
-	protected String convertIfTag(TableFieldInfo fieldInfo, boolean colse) {
-		return convertIfTag(fieldInfo, null, colse);
-	}
-
-	/*
-	 * 查询
-	 */
-	public MappedStatement addSelectMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource, Class<?> resultType,
-													TableInfo table) {
-		if (null != table) {
-			String resultMap = table.getResultMap();
-			if (null != resultMap) {
+        String property = fieldInfo.getProperty();
+        if (null != prefix) {
+            property = prefix + property;
+        }
+
+        // 验证逻辑
+        if (fieldStrategy == FieldStrategy.NOT_EMPTY) {
+            String propertyType = fieldInfo.getPropertyType();
+            if (StringUtils.isCharSequence(propertyType)) {
+                return String.format("\n\t<if test=\"%s!=null and %s!=''\">", property, property);
+            } else {
+                return String.format("\n\t<if test=\"%s!=null \">", property);
+            }
+        } else {
+            // FieldStrategy.NOT_NULL
+            return String.format("\n\t<if test=\"%s!=null\">", property);
+        }
+    }
+
+    protected String convertIfTagIgnored(TableFieldInfo fieldInfo, boolean colse) {
+        return convertIfTag(true, fieldInfo, null, colse);
+    }
+
+    protected String convertIfTag(TableFieldInfo fieldInfo, String prefix, boolean colse) {
+        return convertIfTag(false, fieldInfo, prefix, colse);
+    }
+
+    protected String convertIfTag(TableFieldInfo fieldInfo, boolean colse) {
+        return convertIfTag(fieldInfo, null, colse);
+    }
+
+    /*
+     * 查询
+     */
+    public MappedStatement addSelectMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource, Class<?> resultType,
+                                                    TableInfo table) {
+        if (null != table) {
+            String resultMap = table.getResultMap();
+            if (null != resultMap) {
 				/* 返回 resultMap 映射结果集 */
-				return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.SELECT, null, resultMap, null,
-						new NoKeyGenerator(), null, null);
-			}
-		}
+                return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.SELECT, null, resultMap, null,
+                        new NoKeyGenerator(), null, null);
+            }
+        }
 
 		/* 普通查询 */
-		return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.SELECT, null, null, resultType,
-				new NoKeyGenerator(), null, null);
-	}
-
-	/*
-	 * 插入
-	 */
-	public MappedStatement addInsertMappedStatement(Class<?> mapperClass, Class<?> modelClass, String id, SqlSource sqlSource,
-													KeyGenerator keyGenerator, String keyProperty, String keyColumn) {
-		return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.INSERT, modelClass, null, Integer.class,
-				keyGenerator, keyProperty, keyColumn);
-	}
-
-	/*
-	 * 删除
-	 */
-	public MappedStatement addDeleteMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource) {
-		return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.DELETE, null, null, Integer.class,
-				new NoKeyGenerator(), null, null);
-	}
-
-	/*
-	 * 更新
-	 */
-	public MappedStatement addUpdateMappedStatement(Class<?> mapperClass, Class<?> modelClass, String id, SqlSource sqlSource) {
-		return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.UPDATE, modelClass, null, Integer.class,
-				new NoKeyGenerator(), null, null);
-	}
-
-	public MappedStatement addMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource,
-											  SqlCommandType sqlCommandType, Class<?> parameterClass, String resultMap, Class<?> resultType,
-											  KeyGenerator keyGenerator, String keyProperty, String keyColumn) {
-		String statementName = mapperClass.getName() + "." + id;
-		if (configuration.hasStatement(statementName)) {
-			System.err.println("{" + statementName
-					+ "} Has been loaded by XML or SqlProvider, ignoring the injection of the SQL.");
-			return null;
-		}
+        return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.SELECT, null, null, resultType,
+                new NoKeyGenerator(), null, null);
+    }
+
+    /*
+     * 插入
+     */
+    public MappedStatement addInsertMappedStatement(Class<?> mapperClass, Class<?> modelClass, String id, SqlSource sqlSource,
+                                                    KeyGenerator keyGenerator, String keyProperty, String keyColumn) {
+        return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.INSERT, modelClass, null, Integer.class,
+                keyGenerator, keyProperty, keyColumn);
+    }
+
+    /*
+     * 删除
+     */
+    public MappedStatement addDeleteMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource) {
+        return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.DELETE, null, null, Integer.class,
+                new NoKeyGenerator(), null, null);
+    }
+
+    /*
+     * 更新
+     */
+    public MappedStatement addUpdateMappedStatement(Class<?> mapperClass, Class<?> modelClass, String id, SqlSource sqlSource) {
+        return this.addMappedStatement(mapperClass, id, sqlSource, SqlCommandType.UPDATE, modelClass, null, Integer.class,
+                new NoKeyGenerator(), null, null);
+    }
+
+    public MappedStatement addMappedStatement(Class<?> mapperClass, String id, SqlSource sqlSource,
+                                              SqlCommandType sqlCommandType, Class<?> parameterClass, String resultMap, Class<?> resultType,
+                                              KeyGenerator keyGenerator, String keyProperty, String keyColumn) {
+        String statementName = mapperClass.getName() + "." + id;
+        if (configuration.hasStatement(statementName)) {
+            System.err.println("{" + statementName
+                    + "} Has been loaded by XML or SqlProvider, ignoring the injection of the SQL.");
+            return null;
+        }
 		/* 缓存逻辑处理 */
-		boolean isSelect = false;
-		if (sqlCommandType == SqlCommandType.SELECT) {
-			isSelect = true;
-		}
-		return builderAssistant.addMappedStatement(id, sqlSource, StatementType.PREPARED, sqlCommandType, null, null, null,
-				parameterClass, resultMap, resultType, null, !isSelect, isSelect, false, keyGenerator, keyProperty, keyColumn,
-				configuration.getDatabaseId(), languageDriver, null);
-	}
-
-	// --------------------------------------------------------SqlRunner------------------------------------------------------------
-	public void injectSqlRunner(Configuration configuration) {
-		this.configuration = configuration;
-		this.languageDriver = configuration.getDefaultScriptingLanguageInstance();
-		initSelectList();
-		initSelectObjs();
-		initInsert();
-		initUpdate();
-		initDelete();
-		initCount();
-	}
-
-	/**
-	 * 是否已经存在MappedStatement
-	 *
-	 * @param mappedStatement
-	 * @return
-	 */
-	private boolean hasMappedStatement(String mappedStatement) {
-		return configuration.hasStatement(mappedStatement, false);
-	}
-
-	/**
-	 * 创建查询MappedStatement
-	 *
-	 * @param mappedStatement
-	 * @param sqlSource
-	 *            执行的sqlSource
-	 * @param resultType
-	 *            返回的结果类型
-	 */
-	@SuppressWarnings("serial")
-	private void createSelectMappedStatement(String mappedStatement, SqlSource sqlSource, final Class<?> resultType) {
-		MappedStatement ms = new MappedStatement.Builder(configuration, mappedStatement, sqlSource, SqlCommandType.SELECT)
-				.resultMaps(new ArrayList<ResultMap>() {
-					{
-						add(new ResultMap.Builder(configuration, "defaultResultMap", resultType, new ArrayList<ResultMapping>(0))
-								.build());
-					}
-				}).build();
-		// 缓存
-		configuration.addMappedStatement(ms);
-	}
-
-	/**
-	 * 创建一个MappedStatement
-	 *
-	 * @param mappedStatement
-	 * @param sqlSource
-	 *            执行的sqlSource
-	 * @param sqlCommandType
-	 *            执行的sqlCommandType
-	 */
-	@SuppressWarnings("serial")
-	private void createUpdateMappedStatement(String mappedStatement, SqlSource sqlSource, SqlCommandType sqlCommandType) {
-		MappedStatement ms = new MappedStatement.Builder(configuration, mappedStatement, sqlSource, sqlCommandType).resultMaps(
-				new ArrayList<ResultMap>() {
-					{
-						add(new ResultMap.Builder(configuration, "defaultResultMap", int.class, new ArrayList<ResultMapping>(0))
-								.build());
-					}
-				}).build();
-		// 缓存
-		configuration.addMappedStatement(ms);
-	}
-
-	/**
-	 * initSelectList
-	 */
-	private void initSelectList() {
-		if (hasMappedStatement(SqlRunner.SELECT_LIST)) {
-			logger.warn("MappedStatement 'SqlRunner.SelectList' Already Exists");
-			return;
-		}
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
-		createSelectMappedStatement(SqlRunner.SELECT_LIST, sqlSource, Map.class);
-	}
-
-	/**
-	 * initSelectObjs
-	 */
-	private void initSelectObjs() {
-		if (hasMappedStatement(SqlRunner.SELECT_OBJS)) {
-			logger.warn("MappedStatement 'SqlRunner.SelectObjs' Already Exists");
-			return;
-		}
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Object.class);
-		createSelectMappedStatement(SqlRunner.SELECT_OBJS, sqlSource, Object.class);
-	}
-
-	/**
-	 * initCount
-	 */
-	private void initCount() {
-		if (hasMappedStatement(SqlRunner.COUNT)) {
-			logger.warn("MappedStatement 'SqlRunner.Count' Already Exists");
-			return;
-		}
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
-		createSelectMappedStatement(SqlRunner.COUNT, sqlSource, Integer.class);
-	}
-
-	/**
-	 * initInsert
-	 */
-	private void initInsert() {
-		if (hasMappedStatement(SqlRunner.INSERT)) {
-			logger.warn("MappedStatement 'SqlRunner.Insert' Already Exists");
-			return;
-		}
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
-		createUpdateMappedStatement(SqlRunner.INSERT, sqlSource, SqlCommandType.INSERT);
-	}
-
-	/**
-	 * initUpdate
-	 */
-	private void initUpdate() {
-		if (hasMappedStatement(SqlRunner.UPDATE)) {
-			logger.warn("MappedStatement 'SqlRunner.Update' Already Exists");
-			return;
-		}
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
-		createUpdateMappedStatement(SqlRunner.UPDATE, sqlSource, SqlCommandType.UPDATE);
-	}
-
-	/**
-	 * initDelete
-	 */
-	private void initDelete() {
-		if (hasMappedStatement(SqlRunner.DELETE)) {
-			logger.warn("MappedStatement 'SqlRunner.Delete' Already Exists");
-			return;
-		}
-		SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
-		createUpdateMappedStatement(SqlRunner.DELETE, sqlSource, SqlCommandType.DELETE);
-	}
+        boolean isSelect = false;
+        if (sqlCommandType == SqlCommandType.SELECT) {
+            isSelect = true;
+        }
+        return builderAssistant.addMappedStatement(id, sqlSource, StatementType.PREPARED, sqlCommandType, null, null, null,
+                parameterClass, resultMap, resultType, null, !isSelect, isSelect, false, keyGenerator, keyProperty, keyColumn,
+                configuration.getDatabaseId(), languageDriver, null);
+    }
+
+    // --------------------------------------------------------SqlRunner------------------------------------------------------------
+    public void injectSqlRunner(Configuration configuration) {
+        this.configuration = configuration;
+        this.languageDriver = configuration.getDefaultScriptingLanguageInstance();
+        initSelectList();
+        initSelectObjs();
+        initInsert();
+        initUpdate();
+        initDelete();
+        initCount();
+    }
+
+    /**
+     * 是否已经存在MappedStatement
+     *
+     * @param mappedStatement
+     * @return
+     */
+    private boolean hasMappedStatement(String mappedStatement) {
+        return configuration.hasStatement(mappedStatement, false);
+    }
+
+    /**
+     * 创建查询MappedStatement
+     *
+     * @param mappedStatement
+     * @param sqlSource
+     *            执行的sqlSource
+     * @param resultType
+     *            返回的结果类型
+     */
+    @SuppressWarnings("serial")
+    private void createSelectMappedStatement(String mappedStatement, SqlSource sqlSource, final Class<?> resultType) {
+        MappedStatement ms = new MappedStatement.Builder(configuration, mappedStatement, sqlSource, SqlCommandType.SELECT)
+                .resultMaps(new ArrayList<ResultMap>() {
+                    {
+                        add(new ResultMap.Builder(configuration, "defaultResultMap", resultType, new ArrayList<ResultMapping>(0))
+                                .build());
+                    }
+                }).build();
+        // 缓存
+        configuration.addMappedStatement(ms);
+    }
+
+    /**
+     * 创建一个MappedStatement
+     *
+     * @param mappedStatement
+     * @param sqlSource
+     *            执行的sqlSource
+     * @param sqlCommandType
+     *            执行的sqlCommandType
+     */
+    @SuppressWarnings("serial")
+    private void createUpdateMappedStatement(String mappedStatement, SqlSource sqlSource, SqlCommandType sqlCommandType) {
+        MappedStatement ms = new MappedStatement.Builder(configuration, mappedStatement, sqlSource, sqlCommandType).resultMaps(
+                new ArrayList<ResultMap>() {
+                    {
+                        add(new ResultMap.Builder(configuration, "defaultResultMap", int.class, new ArrayList<ResultMapping>(0))
+                                .build());
+                    }
+                }).build();
+        // 缓存
+        configuration.addMappedStatement(ms);
+    }
+
+    /**
+     * initSelectList
+     */
+    private void initSelectList() {
+        if (hasMappedStatement(SqlRunner.SELECT_LIST)) {
+            logger.warn("MappedStatement 'SqlRunner.SelectList' Already Exists");
+            return;
+        }
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
+        createSelectMappedStatement(SqlRunner.SELECT_LIST, sqlSource, Map.class);
+    }
+
+    /**
+     * initSelectObjs
+     */
+    private void initSelectObjs() {
+        if (hasMappedStatement(SqlRunner.SELECT_OBJS)) {
+            logger.warn("MappedStatement 'SqlRunner.SelectObjs' Already Exists");
+            return;
+        }
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Object.class);
+        createSelectMappedStatement(SqlRunner.SELECT_OBJS, sqlSource, Object.class);
+    }
+
+    /**
+     * initCount
+     */
+    private void initCount() {
+        if (hasMappedStatement(SqlRunner.COUNT)) {
+            logger.warn("MappedStatement 'SqlRunner.Count' Already Exists");
+            return;
+        }
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
+        createSelectMappedStatement(SqlRunner.COUNT, sqlSource, Integer.class);
+    }
+
+    /**
+     * initInsert
+     */
+    private void initInsert() {
+        if (hasMappedStatement(SqlRunner.INSERT)) {
+            logger.warn("MappedStatement 'SqlRunner.Insert' Already Exists");
+            return;
+        }
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
+        createUpdateMappedStatement(SqlRunner.INSERT, sqlSource, SqlCommandType.INSERT);
+    }
+
+    /**
+     * initUpdate
+     */
+    private void initUpdate() {
+        if (hasMappedStatement(SqlRunner.UPDATE)) {
+            logger.warn("MappedStatement 'SqlRunner.Update' Already Exists");
+            return;
+        }
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
+        createUpdateMappedStatement(SqlRunner.UPDATE, sqlSource, SqlCommandType.UPDATE);
+    }
+
+    /**
+     * initDelete
+     */
+    private void initDelete() {
+        if (hasMappedStatement(SqlRunner.DELETE)) {
+            logger.warn("MappedStatement 'SqlRunner.Delete' Already Exists");
+            return;
+        }
+        SqlSource sqlSource = languageDriver.createSqlSource(configuration, SqlRunner.SQLScript, Map.class);
+        createUpdateMappedStatement(SqlRunner.DELETE, sqlSource, SqlCommandType.DELETE);
+    }
 
 }

+ 217 - 215
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/BaseMapper.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -35,217 +35,219 @@ import org.apache.ibatis.session.RowBounds;
  */
 public interface BaseMapper<T> {
 
-	/**
-	 * <p>
-	 * 插入一条记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return int
-	 */
-	Integer insert(T entity);
-	/**
-	 * <p>
-	 * 插入一条记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return int
-	 */
-	Integer insertAllColumn(T entity);
-
-	/**
-	 * <p>
-	 * 根据 ID 删除
-	 * </p>
-	 *
-	 * @param id
-	 *            主键ID
-	 * @return int
-	 */
-	Integer deleteById(Serializable id);
-
-	/**
-	 * <p>
-	 * 根据 columnMap 条件,删除记录
-	 * </p>
-	 *
-	 * @param columnMap
-	 *            表字段 map 对象
-	 * @return int
-	 */
-	Integer deleteByMap(@Param("cm") Map<String, Object> columnMap);
-
-	/**
-	 * <p>
-	 * 根据 entity 条件,删除记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return int
-	 */
-	Integer delete(@Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 删除(根据ID 批量删除)
-	 * </p>
-	 *
-	 * @param idList
-	 *            主键ID列表
-	 * @return int
-	 */
-	Integer deleteBatchIds(List<? extends Serializable> idList);
-
-	/**
-	 * <p>
-	 * 根据 ID 修改
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return int
-	 */
-	Integer updateById(T entity);
-	/**
-	 * <p>
-	 * 根据 ID 修改
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return int
-	 */
-	Integer updateAllColumnById(T entity);
-
-	/**
-	 * <p>
-	 * 根据 whereEntity 条件,更新记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return
-	 */
-	Integer update(@Param("et") T entity, @Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 ID 查询
-	 * </p>
-	 *
-	 * @param id
-	 *            主键ID
-	 * @return T
-	 */
-	T selectById(Serializable id);
-
-	/**
-	 * <p>
-	 * 查询(根据ID 批量查询)
-	 * </p>
-	 *
-	 * @param idList
-	 *            主键ID列表
-	 * @return List<T>
-	 */
-	List<T> selectBatchIds(List<? extends Serializable> idList);
-
-	/**
-	 * <p>
-	 * 查询(根据 columnMap 条件)
-	 * </p>
-	 *
-	 * @param columnMap
-	 *            表字段 map 对象
-	 * @return List<T>
-	 */
-	List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
-
-	/**
-	 * <p>
-	 * 根据 entity 条件,查询一条记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return T
-	 */
-	T selectOne(@Param("ew") T entity);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper 条件,查询总记录数
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象
-	 * @return int
-	 */
-	Integer selectCount(@Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 entity 条件,查询全部记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return List<T>
-	 */
-	List<T> selectList(@Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper 条件,查询全部记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return List<T>
-	 */
-	List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper 条件,查询全部记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return List<Object>
-	 */
-	List<Object> selectObjs(@Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 entity 条件,查询全部记录(并翻页)
-	 * </p>
-	 *
-	 * @param rowBounds
-	 *            分页查询条件(可以为 RowBounds.DEFAULT)
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return List<T>
-	 */
-	List<T> selectPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper 条件,查询全部记录(并翻页)
-	 * </p>
-	 *
-	 * @param rowBounds
-	 *            分页查询条件(可以为 RowBounds.DEFAULT)
-	 * @param wrapper
-	 *            实体对象封装操作类
-	 * @return List<Map<String, Object>>
-	 */
-	List<Map<String, Object>> selectMapsPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
+    /**
+     * <p>
+     * 插入一条记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return int
+     */
+    Integer insert(T entity);
+
+    /**
+     * <p>
+     * 插入一条记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return int
+     */
+    Integer insertAllColumn(T entity);
+
+    /**
+     * <p>
+     * 根据 ID 删除
+     * </p>
+     *
+     * @param id
+     *            主键ID
+     * @return int
+     */
+    Integer deleteById(Serializable id);
+
+    /**
+     * <p>
+     * 根据 columnMap 条件,删除记录
+     * </p>
+     *
+     * @param columnMap
+     *            表字段 map 对象
+     * @return int
+     */
+    Integer deleteByMap(@Param("cm") Map<String, Object> columnMap);
+
+    /**
+     * <p>
+     * 根据 entity 条件,删除记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return int
+     */
+    Integer delete(@Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 删除(根据ID 批量删除)
+     * </p>
+     *
+     * @param idList
+     *            主键ID列表
+     * @return int
+     */
+    Integer deleteBatchIds(List<? extends Serializable> idList);
+
+    /**
+     * <p>
+     * 根据 ID 修改
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return int
+     */
+    Integer updateById(T entity);
+
+    /**
+     * <p>
+     * 根据 ID 修改
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return int
+     */
+    Integer updateAllColumnById(T entity);
+
+    /**
+     * <p>
+     * 根据 whereEntity 条件,更新记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return
+     */
+    Integer update(@Param("et") T entity, @Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 ID 查询
+     * </p>
+     *
+     * @param id
+     *            主键ID
+     * @return T
+     */
+    T selectById(Serializable id);
+
+    /**
+     * <p>
+     * 查询(根据ID 批量查询)
+     * </p>
+     *
+     * @param idList
+     *            主键ID列表
+     * @return List<T>
+     */
+    List<T> selectBatchIds(List<? extends Serializable> idList);
+
+    /**
+     * <p>
+     * 查询(根据 columnMap 条件)
+     * </p>
+     *
+     * @param columnMap
+     *            表字段 map 对象
+     * @return List<T>
+     */
+    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
+
+    /**
+     * <p>
+     * 根据 entity 条件,查询一条记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return T
+     */
+    T selectOne(@Param("ew") T entity);
+
+    /**
+     * <p>
+     * 根据 Wrapper 条件,查询总记录数
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象
+     * @return int
+     */
+    Integer selectCount(@Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 entity 条件,查询全部记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return List<T>
+     */
+    List<T> selectList(@Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper 条件,查询全部记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return List<T>
+     */
+    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper 条件,查询全部记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return List<Object>
+     */
+    List<Object> selectObjs(@Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 entity 条件,查询全部记录(并翻页)
+     * </p>
+     *
+     * @param rowBounds
+     *            分页查询条件(可以为 RowBounds.DEFAULT)
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return List<T>
+     */
+    List<T> selectPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper 条件,查询全部记录(并翻页)
+     * </p>
+     *
+     * @param rowBounds
+     *            分页查询条件(可以为 RowBounds.DEFAULT)
+     * @param wrapper
+     *            实体对象封装操作类
+     * @return List<Map<String, Object>>
+     */
+    List<Map<String, Object>> selectMapsPage(RowBounds rowBounds, @Param("ew") Wrapper<T> wrapper);
 
 }

+ 28 - 28
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/Condition.java

@@ -25,42 +25,42 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @author hubin Caratacus
  * @date 2016-11-7
  */
-@SuppressWarnings({ "rawtypes", "serial" })
+@SuppressWarnings({"rawtypes", "serial"})
 public class Condition extends Wrapper {
 
-	/**
-	 * 构建一个Empty条件构造 避免传递参数使用null
-	 */
-	public static Condition Empty() {
-		return Condition.instance();
-	}
+    /**
+     * 构建一个Empty条件构造 避免传递参数使用null
+     */
+    public static Condition Empty() {
+        return Condition.instance();
+    }
 
-	/**
-	 * 获取实例
-	 */
-	public static Condition instance() {
-		return new Condition();
-	}
+    /**
+     * 获取实例
+     */
+    public static Condition instance() {
+        return new Condition();
+    }
 
-	/**
-	 * SQL 片段
-	 */
-	@Override
-	public String getSqlSegment() {
-		/*
+    /**
+     * SQL 片段
+     */
+    @Override
+    public String getSqlSegment() {
+        /*
 		 * 无条件
 		 */
-		String sqlWhere = sql.toString();
-		if (StringUtils.isEmpty(sqlWhere)) {
-			return null;
-		}
+        String sqlWhere = sql.toString();
+        if (StringUtils.isEmpty(sqlWhere)) {
+            return null;
+        }
 		/*
 		 * 根据当前实体判断是否需要将WHERE替换成 AND 增加实体不为空但所有属性为空的情况
 		 */
-		if (isWhere != null) {
-			sqlWhere = isWhere ? sqlWhere : sqlWhere.replaceFirst("WHERE", AND_OR);
-		}
-		return sqlWhere;
-	}
+        if (isWhere != null) {
+            sqlWhere = isWhere ? sqlWhere : sqlWhere.replaceFirst("WHERE", AND_OR);
+        }
+        return sqlWhere;
+    }
 
 }

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

@@ -29,54 +29,54 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
 @SuppressWarnings("serial")
 public class EntityWrapper<T> extends Wrapper<T> {
 
-	/**
-	 * 数据库表映射实体类
-	 */
-	protected T entity = null;
+    /**
+     * 数据库表映射实体类
+     */
+    protected T entity = null;
 
-	public EntityWrapper() {
-		/* 注意,传入查询参数 */
-	}
+    public EntityWrapper() {
+        /* 注意,传入查询参数 */
+    }
 
-	public EntityWrapper(T entity) {
-		this.entity = entity;
-	}
+    public EntityWrapper(T entity) {
+        this.entity = entity;
+    }
 
-	public EntityWrapper(T entity, String sqlSelect) {
-		this.entity = entity;
-		this.sqlSelect = sqlSelect;
-	}
+    public EntityWrapper(T entity, String sqlSelect) {
+        this.entity = entity;
+        this.sqlSelect = sqlSelect;
+    }
 
-	public T getEntity() {
-		return entity;
-	}
+    public T getEntity() {
+        return entity;
+    }
 
-	public void setEntity(T entity) {
-		this.entity = entity;
-	}
+    public void setEntity(T entity) {
+        this.entity = entity;
+    }
 
-	/**
-	 * SQL 片段
-	 */
-	@Override
-	public String getSqlSegment() {
+    /**
+     * SQL 片段
+     */
+    @Override
+    public String getSqlSegment() {
 		/*
 		 * 无条件
 		 */
-		String sqlWhere = sql.toString();
-		if (StringUtils.isEmpty(sqlWhere)) {
-			return null;
-		}
+        String sqlWhere = sql.toString();
+        if (StringUtils.isEmpty(sqlWhere)) {
+            return null;
+        }
 
 		/*
 		 * 根据当前实体判断是否需要将WHERE替换成 AND 增加实体不为空但所有属性为空的情况
 		 */
-		if (isWhere != null) {
-			sqlWhere = isWhere ? sqlWhere : sqlWhere.replaceFirst("WHERE", AND_OR);
-		} else {
-			sqlWhere = ReflectionKit.checkFieldValueNotNull(entity) ? sqlWhere.replaceFirst("WHERE", AND_OR) : sqlWhere;
-		}
-		return sqlWhere;
-	}
+        if (isWhere != null) {
+            sqlWhere = isWhere ? sqlWhere : sqlWhere.replaceFirst("WHERE", AND_OR);
+        } else {
+            sqlWhere = ReflectionKit.checkFieldValueNotNull(entity) ? sqlWhere.replaceFirst("WHERE", AND_OR) : sqlWhere;
+        }
+        return sqlWhere;
+    }
 
 }

+ 14 - 14
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/IMetaObjectHandler.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -21,21 +21,21 @@ import org.apache.ibatis.reflection.MetaObject;
  * <p>
  * 元对象字段填充控制器抽象类,实现公共字段自动写入
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-08-28
  */
 public interface IMetaObjectHandler {
 
-	/**
-	 * <p>
-	 * 插入元对象字段填充
-	 * </p>
-	 * 
-	 * @param metaObject
-	 *            元对象
-	 * @return
-	 */
-	void insertFill(MetaObject metaObject);
+    /**
+     * <p>
+     * 插入元对象字段填充
+     * </p>
+     *
+     * @param metaObject
+     *            元对象
+     * @return
+     */
+    void insertFill(MetaObject metaObject);
 
 }

+ 25 - 25
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/ISqlInjector.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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
@@ -22,34 +22,34 @@ import org.apache.ibatis.session.Configuration;
  * <p>
  * SQL 自动注入器接口
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-07-24
  */
 public interface ISqlInjector {
 
-	/**
-	 * 根据mapperClass注入SQL
-	 * 
-	 * @param builderAssistant
-	 * @param mapperClass
-	 */
-	void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
+    /**
+     * 根据mapperClass注入SQL
+     *
+     * @param builderAssistant
+     * @param mapperClass
+     */
+    void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
 
-	/**
-	 * 检查SQL是否注入(已经注入过不再注入)
-	 * 
-	 * @param builderAssistant
-	 * @param mapperClass
-	 */
-	void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
+    /**
+     * 检查SQL是否注入(已经注入过不再注入)
+     *
+     * @param builderAssistant
+     * @param mapperClass
+     */
+    void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
 
-	/**
-	 * 注入SqlRunner相关
-	 * 
-	 * @param configuration
-	 * @see com.baomidou.mybatisplus.mapper.SqlRunner
-	 */
-	void injectSqlRunner(Configuration configuration);
+    /**
+     * 注入SqlRunner相关
+     *
+     * @param configuration
+     * @see com.baomidou.mybatisplus.mapper.SqlRunner
+     */
+    void injectSqlRunner(Configuration configuration);
 
 }

+ 138 - 137
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/SqlHelper.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,12 +15,8 @@
  */
 package com.baomidou.mybatisplus.mapper;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-import com.baomidou.mybatisplus.entity.TableInfo;
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
-import com.baomidou.mybatisplus.plugins.Page;
-import com.baomidou.mybatisplus.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.toolkit.TableInfoHelper;
+import java.util.List;
+
 import org.apache.ibatis.logging.Log;
 import org.apache.ibatis.logging.LogFactory;
 import org.apache.ibatis.session.Configuration;
@@ -28,7 +24,12 @@ import org.apache.ibatis.session.ExecutorType;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSessionFactory;
 
-import java.util.List;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.entity.TableInfo;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.toolkit.TableInfoHelper;
 
 /**
  * <p>
@@ -40,140 +41,140 @@ import java.util.List;
  */
 public class SqlHelper {
 
-	private static final Log logger = LogFactory.getLog(SqlHelper.class);
+    private static final Log logger = LogFactory.getLog(SqlHelper.class);
 
-	/**
-	 * 获取Session 默认自动提交
-	 * <p>
-	 * 特别说明:这里获取SqlSession时这里虽然设置了自动提交但是如果事务托管了的话 是不起作用的 切记!!
-	 * <p/>
-	 *
-	 * @return SqlSession
-	 */
-	public static SqlSession sqlSession(Class<?> clazz) {
-		return sqlSession(clazz, true);
-	}
+    /**
+     * 获取Session 默认自动提交
+     * <p>
+     * 特别说明:这里获取SqlSession时这里虽然设置了自动提交但是如果事务托管了的话 是不起作用的 切记!!
+     * <p/>
+     *
+     * @return SqlSession
+     */
+    public static SqlSession sqlSession(Class<?> clazz) {
+        return sqlSession(clazz, true);
+    }
 
-	/**
-	 * <p>
-	 * 批量操作 SqlSession
-	 * </p>
-	 *
-	 * @param clazz
-	 *            实体类
-	 * @return SqlSession
-	 */
-	public static SqlSession sqlSessionBatch(Class<?> clazz) {
-		return GlobalConfiguration.currentSessionFactory(clazz).openSession(ExecutorType.BATCH);
-	}
+    /**
+     * <p>
+     * 批量操作 SqlSession
+     * </p>
+     *
+     * @param clazz
+     *            实体类
+     * @return SqlSession
+     */
+    public static SqlSession sqlSessionBatch(Class<?> clazz) {
+        return GlobalConfiguration.currentSessionFactory(clazz).openSession(ExecutorType.BATCH);
+    }
 
-	/**
-	 * 获取sqlSessionå
-	 *
-	 * @param clazz
-	 * @return
-	 */
-	private static SqlSession getSqlSession(Class<?> clazz) {
-		SqlSession session = null;
-		try {
-			SqlSessionFactory sqlSessionFactory = GlobalConfiguration.currentSessionFactory(clazz);
-			Configuration configuration = sqlSessionFactory.getConfiguration();
-			session = GlobalConfiguration.getGlobalConfig(configuration).getSqlSession();
-		} catch (Exception e) {
-			// ignored
-		}
-		return session;
-	}
+    /**
+     * 获取sqlSessionå
+     *
+     * @param clazz
+     * @return
+     */
+    private static SqlSession getSqlSession(Class<?> clazz) {
+        SqlSession session = null;
+        try {
+            SqlSessionFactory sqlSessionFactory = GlobalConfiguration.currentSessionFactory(clazz);
+            Configuration configuration = sqlSessionFactory.getConfiguration();
+            session = GlobalConfiguration.getGlobalConfig(configuration).getSqlSession();
+        } catch (Exception e) {
+            // ignored
+        }
+        return session;
+    }
 
-	/**
-	 * <p>
-	 * 获取Session
-	 * </p>
-	 *
-	 * @param clazz
-	 *            实体类
-	 * @param autoCommit
-	 *            true自动提交false则相反
-	 * @return SqlSession
-	 */
-	public static SqlSession sqlSession(Class<?> clazz, boolean autoCommit) {
-		SqlSession sqlSession = getSqlSession(clazz);
-		return (sqlSession != null) ? sqlSession : GlobalConfiguration.currentSessionFactory(clazz).openSession(autoCommit);
-	}
+    /**
+     * <p>
+     * 获取Session
+     * </p>
+     *
+     * @param clazz
+     *            实体类
+     * @param autoCommit
+     *            true自动提交false则相反
+     * @return SqlSession
+     */
+    public static SqlSession sqlSession(Class<?> clazz, boolean autoCommit) {
+        SqlSession sqlSession = getSqlSession(clazz);
+        return (sqlSession != null) ? sqlSession : GlobalConfiguration.currentSessionFactory(clazz).openSession(autoCommit);
+    }
 
-	/**
-	 * 获取TableInfo
-	 *
-	 * @return TableInfo
-	 */
-	public static TableInfo table(Class<?> clazz) {
-		TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
-		if (null == tableInfo) {
-			throw new MybatisPlusException("Error: Cannot execute table Method, ClassGenricType not found .");
-		}
-		return tableInfo;
-	}
+    /**
+     * 获取TableInfo
+     *
+     * @return TableInfo
+     */
+    public static TableInfo table(Class<?> clazz) {
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        if (null == tableInfo) {
+            throw new MybatisPlusException("Error: Cannot execute table Method, ClassGenricType not found .");
+        }
+        return tableInfo;
+    }
 
-	/**
-	 * <p>
-	 * 判断数据库操作是否成功
-	 * </p>
-	 *
-	 * @param result
-	 *            数据库操作返回影响条数
-	 * @return boolean
-	 */
-	public static boolean retBool(Integer result) {
-		return null != result && result >= 1;
-	}
+    /**
+     * <p>
+     * 判断数据库操作是否成功
+     * </p>
+     *
+     * @param result
+     *            数据库操作返回影响条数
+     * @return boolean
+     */
+    public static boolean retBool(Integer result) {
+        return null != result && result >= 1;
+    }
 
-	/**
-	 * <p>
-	 * 返回SelectCount执行结果
-	 * </p>
-	 *
-	 * @param result
-	 * @return int
-	 */
-	public static int retCount(Integer result) {
-		return (null == result) ? 0 : result;
-	}
+    /**
+     * <p>
+     * 返回SelectCount执行结果
+     * </p>
+     *
+     * @param result
+     * @return int
+     */
+    public static int retCount(Integer result) {
+        return (null == result) ? 0 : result;
+    }
 
-	/**
-	 * <p>
-	 * 从list中取第一条数据返回对应List中泛型的单个结果
-	 * </p>
-	 *
-	 * @param list
-	 * @param <E>
-	 * @return
-	 */
-	public static <E> E getObject(List<E> list) {
-		if (CollectionUtils.isNotEmpty(list)) {
-			int size = list.size();
-			if (size > 1) {
-				logger.warn(String.format("Warn: execute Method There are  %s results.", size));
-			}
-			return list.get(0);
-		}
-		return null;
-	}
+    /**
+     * <p>
+     * 从list中取第一条数据返回对应List中泛型的单个结果
+     * </p>
+     *
+     * @param list
+     * @param <E>
+     * @return
+     */
+    public static <E> E getObject(List<E> list) {
+        if (CollectionUtils.isNotEmpty(list)) {
+            int size = list.size();
+            if (size > 1) {
+                logger.warn(String.format("Warn: execute Method There are  %s results.", size));
+            }
+            return list.get(0);
+        }
+        return null;
+    }
 
-	/**
-	 * 填充Wrapper
-	 *
-	 * @param page
-	 * @param wrapper
-	 */
-	public static void fillWrapper(Page<?> page, Wrapper<?> wrapper) {
-		if (null == page) {
-			return;
-		}
-		if (null != wrapper) {
-			if (page.isOpenSort()) {
-				wrapper.orderBy(page.getOrderByField(), page.isAsc());
-			}
-			wrapper.allEq(page.getCondition());
-		}
-	}
+    /**
+     * 填充Wrapper
+     *
+     * @param page
+     * @param wrapper
+     */
+    public static void fillWrapper(Page<?> page, Wrapper<?> wrapper) {
+        if (null == page) {
+            return;
+        }
+        if (null != wrapper) {
+            if (page.isOpenSort()) {
+                wrapper.orderBy(page.getOrderByField(), page.isAsc());
+            }
+            wrapper.allEq(page.getCondition());
+        }
+    }
 }

+ 78 - 83
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/SqlPlus.java

@@ -29,94 +29,89 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
 @SuppressWarnings("serial")
 public class SqlPlus extends MybatisAbstractSQL<SqlPlus> {
 
-	private final String IS_NOT_NULL = " IS NOT NULL";
-	private final String IS_NULL = " IS NULL";
+    private final String IS_NOT_NULL = " IS NOT NULL";
+    private final String IS_NULL = " IS NULL";
 
-	@Override
-	public SqlPlus getSelf() {
-		return this;
-	}
+    @Override
+    public SqlPlus getSelf() {
+        return this;
+    }
 
-	/**
-	 * IS NOT NULL查询
-	 *
-	 * @param columns
-	 *            以逗号分隔的字段名称
-	 * @return this
-	 */
-	public SqlPlus IS_NOT_NULL(String columns) {
-		handerNull(columns, IS_NOT_NULL);
-		return this;
-	}
+    /**
+     * IS NOT NULL查询
+     *
+     * @param columns 以逗号分隔的字段名称
+     * @return this
+     */
+    public SqlPlus IS_NOT_NULL(String columns) {
+        handerNull(columns, IS_NOT_NULL);
+        return this;
+    }
 
-	/**
-	 * IS NULL查询
-	 *
-	 * @param columns
-	 *            以逗号分隔的字段名称
-	 * @return
-	 */
-	public SqlPlus IS_NULL(String columns) {
-		handerNull(columns, IS_NULL);
-		return this;
-	}
+    /**
+     * IS NULL查询
+     *
+     * @param columns 以逗号分隔的字段名称
+     * @return
+     */
+    public SqlPlus IS_NULL(String columns) {
+        handerNull(columns, IS_NULL);
+        return this;
+    }
 
-	/**
-	 * 将EXISTS语句添加到WHERE条件中
-	 *
-	 * @param value
-	 * @return
-	 */
-	public SqlPlus EXISTS(String value) {
-		handerExists(value, false);
-		return this;
-	}
+    /**
+     * 将EXISTS语句添加到WHERE条件中
+     *
+     * @param value
+     * @return
+     */
+    public SqlPlus EXISTS(String value) {
+        handerExists(value, false);
+        return this;
+    }
 
-	/**
-	 * 处理EXISTS操作
-	 *
-	 * @param value
-	 * @param isNot
-	 *            是否为NOT EXISTS操作
-	 */
-	private void handerExists(String value, boolean isNot) {
-		if (StringUtils.isNotEmpty(value)) {
-			StringBuilder inSql = new StringBuilder();
-			if (isNot) {
-				inSql.append(" NOT");
-			}
-			inSql.append(" EXISTS (").append(value).append(")");
-			WHERE(inSql.toString());
-		}
-	}
+    /**
+     * 处理EXISTS操作
+     *
+     * @param value
+     * @param isNot 是否为NOT EXISTS操作
+     */
+    private void handerExists(String value, boolean isNot) {
+        if (StringUtils.isNotEmpty(value)) {
+            StringBuilder inSql = new StringBuilder();
+            if (isNot) {
+                inSql.append(" NOT");
+            }
+            inSql.append(" EXISTS (").append(value).append(")");
+            WHERE(inSql.toString());
+        }
+    }
 
-	/**
-	 * 将NOT_EXISTS语句添加到WHERE条件中
-	 *
-	 * @param value
-	 * @return
-	 */
-	public SqlPlus NOT_EXISTS(String value) {
-		handerExists(value, true);
-		return this;
-	}
+    /**
+     * 将NOT_EXISTS语句添加到WHERE条件中
+     *
+     * @param value
+     * @return
+     */
+    public SqlPlus NOT_EXISTS(String value) {
+        handerExists(value, true);
+        return this;
+    }
 
-	/**
-	 * 以相同的方式处理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);
-				}
-			}
-		}
-	}
+    /**
+     * 以相同的方式处理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);
+                }
+            }
+        }
+    }
 }

+ 119 - 121
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/SqlRunner.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,16 +15,17 @@
  */
 package com.baomidou.mybatisplus.mapper;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-import com.baomidou.mybatisplus.plugins.Page;
-import com.baomidou.mybatisplus.toolkit.StringUtils;
-import org.apache.ibatis.session.SqlSession;
-import org.apache.ibatis.session.SqlSessionFactory;
-
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.ibatis.session.SqlSession;
+import org.apache.ibatis.session.SqlSessionFactory;
+
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.plugins.Page;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+
 /**
  * <p>
  * SqlRunner 执行 SQL
@@ -35,117 +36,114 @@ import java.util.Map;
  */
 public class SqlRunner {
 
-	// 默认FACTORY
-	public static SqlSessionFactory FACTORY;
-
-	public static final String INSERT = "com.baomidou.mybatisplus.mapper.SqlRunner.Insert";
-	public static final String DELETE = "com.baomidou.mybatisplus.mapper.SqlRunner.Delete";
-	public static final String UPDATE = "com.baomidou.mybatisplus.mapper.SqlRunner.Update";
-	public static final String SELECT_LIST = "com.baomidou.mybatisplus.mapper.SqlRunner.SelectList";
-	public static final String SELECT_OBJS = "com.baomidou.mybatisplus.mapper.SqlRunner.SelectObjs";
-	public static final String COUNT = "com.baomidou.mybatisplus.mapper.SqlRunner.Count";
-	public static final String SQLScript = "${sql}";
-	public static final String SQL = "sql";
-
-	// 单例Query
-	public static final SqlRunner DEFAULT = new SqlRunner();
-
-	private SqlSessionFactory sqlSessionFactory;
-
-	private Class<?> clazz;
-
-	public SqlRunner() {
-		this.sqlSessionFactory = FACTORY;
-	}
-
-	public SqlRunner(Class<?> clazz) {
-		this.clazz = clazz;
-	}
-
-	public boolean insert(String sql, Object... args) {
-		return SqlHelper.retBool(sqlSession().insert(INSERT, sqlMap(sql, args)));
-	}
-
-	public boolean delete(String sql, Object... args) {
-		return SqlHelper.retBool(sqlSession().delete(DELETE, sqlMap(sql, args)));
-	}
-
-	/**
-	 * 获取sqlMap参数
-	 * 
-	 * @param sql
-	 * @param args
-	 * @return
-	 */
-	private Map<String, String> sqlMap(String sql, Object... args) {
-		Map<String, String> sqlMap = new HashMap<String, String>();
-		sqlMap.put(SQL, StringUtils.sqlArgsFill(sql, args));
-		return sqlMap;
-	}
-
-	public boolean update(String sql, Object... args) {
-		return SqlHelper.retBool(sqlSession().update(UPDATE, sqlMap(sql, args)));
-	}
-
-	public List<Map<String, Object>> selectList(String sql, Object... args) {
-		return sqlSession().selectList(SELECT_LIST, sqlMap(sql, args));
-	}
-
-	public List<Object> selectObjs(String sql, Object... args) {
-		return sqlSession().selectList(SELECT_OBJS, sqlMap(sql, args));
-	}
-
-	public Object selectObj(String sql, Object... args) {
-		return SqlHelper.getObject(selectObjs(sql, args));
-	}
-
-	public int selectCount(String sql, Object... args) {
-		return SqlHelper.retCount(sqlSession().<Integer> selectOne(COUNT, sqlMap(sql, args)));
-	}
-
-	public Map<String, Object> selectOne(String sql, Object... args) {
-		return SqlHelper.getObject(selectList(sql, args));
-	}
-
-	@SuppressWarnings({ "unchecked", "rawtypes" })
-	public Page<Map<String, Object>> selectPage(Page page, String sql, Object... args) {
-		if (null == page) {
-			return null;
-		}
-		page.setRecords(sqlSession().selectList(SELECT_LIST, sqlMap(sql, args), page));
-		return page;
-	}
-
-	/**
-	 * 获取默认的SqlQuery(适用于单库)
-	 * 
-	 * @return
-	 */
-	public static SqlRunner db() {
-		// 初始化的静态变量 还是有前后加载的问题 该判断只会执行一次
-		if (DEFAULT.sqlSessionFactory == null) {
-			DEFAULT.sqlSessionFactory = FACTORY;
-		}
-		return DEFAULT;
-	}
-
-	/**
-	 * 根据当前class对象获取SqlQuery(适用于多库)
-	 * 
-	 * @param clazz
-	 * @return
-	 */
-	public static SqlRunner db(Class<?> clazz) {
-		return new SqlRunner(clazz);
-	}
-
-	/**
-	 * <p>
-	 * 获取Session 默认自动提交
-	 * <p/>
-	 */
-	private SqlSession sqlSession() {
-		return (clazz != null) ? SqlHelper.sqlSession(clazz) : GlobalConfiguration.getSqlSession(FACTORY.getConfiguration());
-	}
+    public static final String INSERT = "com.baomidou.mybatisplus.mapper.SqlRunner.Insert";
+    public static final String DELETE = "com.baomidou.mybatisplus.mapper.SqlRunner.Delete";
+    public static final String UPDATE = "com.baomidou.mybatisplus.mapper.SqlRunner.Update";
+    public static final String SELECT_LIST = "com.baomidou.mybatisplus.mapper.SqlRunner.SelectList";
+    public static final String SELECT_OBJS = "com.baomidou.mybatisplus.mapper.SqlRunner.SelectObjs";
+    public static final String COUNT = "com.baomidou.mybatisplus.mapper.SqlRunner.Count";
+    public static final String SQLScript = "${sql}";
+    public static final String SQL = "sql";
+    // 单例Query
+    public static final SqlRunner DEFAULT = new SqlRunner();
+    // 默认FACTORY
+    public static SqlSessionFactory FACTORY;
+    private SqlSessionFactory sqlSessionFactory;
+
+    private Class<?> clazz;
+
+    public SqlRunner() {
+        this.sqlSessionFactory = FACTORY;
+    }
+
+    public SqlRunner(Class<?> clazz) {
+        this.clazz = clazz;
+    }
+
+    /**
+     * 获取默认的SqlQuery(适用于单库)
+     *
+     * @return
+     */
+    public static SqlRunner db() {
+        // 初始化的静态变量 还是有前后加载的问题 该判断只会执行一次
+        if (DEFAULT.sqlSessionFactory == null) {
+            DEFAULT.sqlSessionFactory = FACTORY;
+        }
+        return DEFAULT;
+    }
+
+    /**
+     * 根据当前class对象获取SqlQuery(适用于多库)
+     *
+     * @param clazz
+     * @return
+     */
+    public static SqlRunner db(Class<?> clazz) {
+        return new SqlRunner(clazz);
+    }
+
+    public boolean insert(String sql, Object... args) {
+        return SqlHelper.retBool(sqlSession().insert(INSERT, sqlMap(sql, args)));
+    }
+
+    public boolean delete(String sql, Object... args) {
+        return SqlHelper.retBool(sqlSession().delete(DELETE, sqlMap(sql, args)));
+    }
+
+    /**
+     * 获取sqlMap参数
+     *
+     * @param sql
+     * @param args
+     * @return
+     */
+    private Map<String, String> sqlMap(String sql, Object... args) {
+        Map<String, String> sqlMap = new HashMap<String, String>();
+        sqlMap.put(SQL, StringUtils.sqlArgsFill(sql, args));
+        return sqlMap;
+    }
+
+    public boolean update(String sql, Object... args) {
+        return SqlHelper.retBool(sqlSession().update(UPDATE, sqlMap(sql, args)));
+    }
+
+    public List<Map<String, Object>> selectList(String sql, Object... args) {
+        return sqlSession().selectList(SELECT_LIST, sqlMap(sql, args));
+    }
+
+    public List<Object> selectObjs(String sql, Object... args) {
+        return sqlSession().selectList(SELECT_OBJS, sqlMap(sql, args));
+    }
+
+    public Object selectObj(String sql, Object... args) {
+        return SqlHelper.getObject(selectObjs(sql, args));
+    }
+
+    public int selectCount(String sql, Object... args) {
+        return SqlHelper.retCount(sqlSession().<Integer>selectOne(COUNT, sqlMap(sql, args)));
+    }
+
+    public Map<String, Object> selectOne(String sql, Object... args) {
+        return SqlHelper.getObject(selectList(sql, args));
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    public Page<Map<String, Object>> selectPage(Page page, String sql, Object... args) {
+        if (null == page) {
+            return null;
+        }
+        page.setRecords(sqlSession().selectList(SELECT_LIST, sqlMap(sql, args), page));
+        return page;
+    }
+
+    /**
+     * <p>
+     * 获取Session 默认自动提交
+     * <p/>
+     */
+    private SqlSession sqlSession() {
+        return (clazz != null) ? SqlHelper.sqlSession(clazz) : GlobalConfiguration.getSqlSession(FACTORY.getConfiguration());
+    }
 
 }

+ 746 - 811
mybatis-plus/src/main/java/com/baomidou/mybatisplus/mapper/Wrapper.java

@@ -15,14 +15,6 @@
  */
 package com.baomidou.mybatisplus.mapper;
 
-import com.baomidou.mybatisplus.enums.SqlLike;
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
-import com.baomidou.mybatisplus.toolkit.ArrayUtils;
-import com.baomidou.mybatisplus.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.toolkit.MapUtils;
-import com.baomidou.mybatisplus.toolkit.SqlUtils;
-import com.baomidou.mybatisplus.toolkit.StringUtils;
-
 import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Collection;
@@ -31,6 +23,14 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import com.baomidou.mybatisplus.enums.SqlLike;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.toolkit.ArrayUtils;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.toolkit.MapUtils;
+import com.baomidou.mybatisplus.toolkit.SqlUtils;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+
 /**
  * <p>
  * 条件构造抽象类,定义T-SQL语法
@@ -42,807 +42,742 @@ import java.util.concurrent.atomic.AtomicInteger;
 @SuppressWarnings("serial")
 public abstract class Wrapper<T> implements Serializable {
 
-	/**
-	 * 占位符
-	 */
-	private static final String PLACE_HOLDER = "{%s}";
-
-	private static final String MYBATIS_PLUS_TOKEN = "#{%s.paramNameValuePairs.%s}";
-
-	private static final String MP_GENERAL_PARAMNAME = "MPGENVAL";
-
-	private static final String DEFAULT_PARAM_ALIAS = "ew";
-
-	private Map<String, Object> paramNameValuePairs = new HashMap<String, Object>(4);
-
-	private AtomicInteger paramNameSeq = new AtomicInteger(0);
-
-	protected String paramAlias = null;
-	/**
-	 * SQL 查询字段内容,例如:id,name,age
-	 */
-	protected String sqlSelect = null;
-
-	/**
-	 * 实现了TSQL语法的SQL实体
-	 */
-	protected SqlPlus sql = new SqlPlus();
-
-	/**
-	 * 自定义是否输出sql为 WHERE OR AND OR OR
-	 */
-	protected Boolean isWhere;
-
-	/**
-	 * 拼接WHERE后应该是AND还是OR
-	 */
-	protected String AND_OR = "AND";
-
-	/**
-	 * 兼容EntityWrapper
-	 *
-	 * @return
-	 */
-	public T getEntity() {
-		return null;
-	}
-
-	public String getSqlSelect() {
-		if (StringUtils.isEmpty(sqlSelect)) {
-			return null;
-		}
-		return stripSqlInjection(sqlSelect);
-	}
-
-	public Wrapper<T> setSqlSelect(String sqlSelect) {
-		if (StringUtils.isNotEmpty(sqlSelect)) {
-			this.sqlSelect = sqlSelect;
-		}
-		return this;
-	}
-
-	/**
-	 * SQL 片段 (子类实现)
-	 */
-	public abstract String getSqlSegment();
-
-	public String toString() {
-		String sqlSegment = getSqlSegment();
-		if (StringUtils.isNotEmpty(sqlSegment)) {
-			sqlSegment = sqlSegment.replaceAll("#\\{" + getParamAlias() + ".paramNameValuePairs.MPGENVAL[0-9]+\\}", "\\?");
-		}
-		return sqlSegment;
-	}
-
-	/**
-	 * <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 Wrapper<T> where(String sqlWhere, Object... params) {
-		sql.WHERE(formatSql(sqlWhere, params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field=value"表达式
-	 * </p>
-	 *
-	 * @param column
-	 * @param params
-	 * @return
-	 */
-	public Wrapper<T> eq(String column, Object params) {
-		sql.WHERE(formatSql(String.format("%s = {0}", column), params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field <> value"表达式
-	 * </p>
-	 *
-	 * @param column
-	 * @param params
-	 * @return
-	 */
-	public Wrapper<T> ne(String column, Object params) {
-		sql.WHERE(formatSql(String.format("%s <> {0}", column), params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field=value"表达式
-	 * </p>
-	 *
-	 * @param params
-	 * @return
-	 */
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	public Wrapper<T> allEq(Map<String, Object> params) {
-		if (MapUtils.isNotEmpty(params)) {
-			Iterator iterator = params.entrySet().iterator();
-			while (iterator.hasNext()) {
-				Map.Entry<String, Object> entry = (Map.Entry<String, Object>) iterator.next();
-				Object value = entry.getValue();
-				if (StringUtils.checkValNotNull(value)) {
-					sql.WHERE(formatSql(String.format("%s = {0}", entry.getKey()), entry.getValue()));
-				}
-
-			}
-
-		}
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field>value"表达式
-	 * </p>
-	 *
-	 * @param column
-	 * @param params
-	 * @return
-	 */
-	public Wrapper<T> gt(String column, Object params) {
-		sql.WHERE(formatSql(String.format("%s > {0}", column), params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field>=value"表达式
-	 * </p>
-	 *
-	 * @param column
-	 * @param params
-	 * @return
-	 */
-	public Wrapper<T> ge(String column, Object params) {
-		sql.WHERE(formatSql(String.format("%s >= {0}", column), params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field<value"表达式
-	 * </p>
-	 *
-	 * @param column
-	 * @param params
-	 * @return
-	 */
-	public Wrapper<T> lt(String column, Object params) {
-		sql.WHERE(formatSql(String.format("%s < {0}", column), params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 等同于SQL的"field<=value"表达式
-	 * </p>
-	 *
-	 * @param column
-	 * @param params
-	 * @return
-	 */
-	public Wrapper<T> le(String column, Object params) {
-		sql.WHERE(formatSql(String.format("%s <= {0}", column), params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * AND 连接后续条件
-	 * </p>
-	 *
-	 * @param sqlAnd
-	 *            and条件语句
-	 * @param params
-	 *            参数集
-	 * @return this
-	 */
-	public Wrapper<T> and(String sqlAnd, Object... params) {
-		sql.AND().WHERE(formatSql(sqlAnd, params));
-		return 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 Wrapper<T> andNew(String sqlAnd, Object... params) {
-		sql.AND_NEW().WHERE(formatSql(sqlAnd, params));
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 使用AND连接并换行
-	 * </p>
-	 * <p>
-	 * 
-	 * @return this
-	 */
-	public Wrapper<T> and() {
-		sql.AND_NEW();
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 使用OR连接并换行
-	 * </p>
-	 *
-	 * @return this
-	 */
-	public Wrapper<T> or() {
-		sql.OR_NEW();
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * 添加OR条件
-	 * </p>
-	 *
-	 * @param sqlOr
-	 *            or 条件语句
-	 * @param params
-	 *            参数集
-	 * @return this
-	 */
-	public Wrapper<T> or(String sqlOr, Object... params) {
-		if (StringUtils.isEmpty(sql.toString())) {
-			AND_OR = "OR";
-		}
-		sql.OR().WHERE(formatSql(sqlOr, params));
-		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 Wrapper<T> orNew(String sqlOr, Object... params) {
-		if (StringUtils.isEmpty(sql.toString())) {
-			AND_OR = "OR";
-		}
-		sql.OR_NEW().WHERE(formatSql(sqlOr, params));
-		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 Wrapper<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<T>
-	 */
-	public Wrapper<T> having(String sqlHaving, Object... params) {
-		sql.HAVING(formatSql(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 columns
-	 *            SQL 中的 order by 语句,无需输入 Order By 关键字
-	 * @return this
-	 */
-	public Wrapper<T> orderBy(String columns) {
-		sql.ORDER_BY(columns);
-		return this;
-	}
-
-	/**
-	 * <p>
-	 * SQL中orderby关键字跟的条件语句,可根据变更动态排序
-	 * </p>
-	 *
-	 * @param columns
-	 *            SQL 中的 order by 语句,无需输入 Order By 关键字
-	 * @param isAsc
-	 *            是否为升序
-	 * @return this
-	 */
-	public Wrapper<T> orderBy(String columns, boolean isAsc) {
-		if (StringUtils.isNotEmpty(columns)) {
-			sql.ORDER_BY(columns + (isAsc ? " ASC" : " DESC"));
-		}
-		return this;
-	}
-
-	/**
-	 * LIKE条件语句,value中无需前后%
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值
-	 * @return this
-	 */
-	public Wrapper<T> like(String column, String value) {
-		handerLike(column, value, SqlLike.DEFAULT, false);
-		return this;
-	}
-
-	/**
-	 * NOT LIKE条件语句,value中无需前后%
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值
-	 * @return this
-	 */
-	public Wrapper<T> notLike(String column, String value) {
-		handerLike(column, value, SqlLike.DEFAULT, true);
-		return this;
-	}
-
-	/**
-	 * 处理LIKE操作
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            like匹配值
-	 * @param isNot
-	 *            是否为NOT LIKE操作
-	 */
-	private void handerLike(String column, String value, SqlLike type, boolean isNot) {
-		if (StringUtils.isNotEmpty(column) && StringUtils.isNotEmpty(value)) {
-			StringBuilder inSql = new StringBuilder();
-			inSql.append(column);
-			if (isNot) {
-				inSql.append(" NOT");
-			}
-			inSql.append(" LIKE {0}");
-			sql.WHERE(formatSql(inSql.toString(), SqlUtils.concatLike(value, type)));
-		}
-	}
-
-	/**
-	 * LIKE条件语句,value中无需前后%
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值
-	 * @param type
-	 * @return this
-	 */
-	public Wrapper<T> like(String column, String value, SqlLike type) {
-		handerLike(column, value, type, false);
-		return this;
-	}
-
-	/**
-	 * NOT LIKE条件语句,value中无需前后%
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值
-	 * @param type
-	 * @return this
-	 */
-	public Wrapper<T> notLike(String column, String value, SqlLike type) {
-		handerLike(column, value, type, true);
-		return this;
-	}
-
-	/**
-	 * is not null 条件
-	 *
-	 * @param columns
-	 *            字段名称。多个字段以逗号分隔。
-	 * @return this
-	 */
-	public Wrapper<T> isNotNull(String columns) {
-		sql.IS_NOT_NULL(columns);
-		return this;
-	}
-
-	/**
-	 * is not null 条件
-	 *
-	 * @param columns
-	 *            字段名称。多个字段以逗号分隔。
-	 * @return this
-	 */
-	public Wrapper<T> isNull(String columns) {
-		sql.IS_NULL(columns);
-		return this;
-	}
-
-	/**
-	 * EXISTS 条件语句,目前适配mysql及oracle
-	 *
-	 * @param value
-	 *            匹配值
-	 * @return this
-	 */
-	public Wrapper<T> exists(String value) {
-		sql.EXISTS(value);
-		return this;
-	}
-
-	/**
-	 * NOT EXISTS条件语句
-	 *
-	 * @param value
-	 *            匹配值
-	 * @return this
-	 */
-	public Wrapper<T> notExists(String value) {
-		sql.NOT_EXISTS(value);
-		return this;
-	}
-
-	/**
-	 * IN 条件语句,目前适配mysql及oracle
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            逗号拼接的字符串
-	 * @return this
-	 */
-	public Wrapper<T> in(String column, String value) {
-		if (StringUtils.isNotEmpty(value)) {
-			in(column, StringUtils.splitWorker(value, ",", -1, false));
-		}
-		return this;
-	}
-
-	/**
-	 * NOT IN条件语句
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            逗号拼接的字符串
-	 * @return this
-	 */
-	public Wrapper<T> notIn(String column, String value) {
-		if (StringUtils.isNotEmpty(value)) {
-			notIn(column, StringUtils.splitWorker(value, ",", -1, false));
-		}
-		return this;
-	}
-
-	/**
-	 * IN 条件语句,目前适配mysql及oracle
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值 List集合
-	 * @return this
-	 */
-	public Wrapper<T> in(String column, Collection<?> value) {
-		if (CollectionUtils.isNotEmpty(value))
-			sql.WHERE(formatSql(inExpression(column, value, false), value.toArray()));
-		return this;
-	}
-
-	/**
-	 * NOT IN 条件语句,目前适配mysql及oracle
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值 List集合
-	 * @return this
-	 */
-	public Wrapper<T> notIn(String column, Collection<?> value) {
-		if (CollectionUtils.isNotEmpty(value))
-			sql.WHERE(formatSql(inExpression(column, value, true), value.toArray()));
-		return this;
-	}
-
-	/**
-	 * IN 条件语句,目前适配mysql及oracle
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值 object数组
-	 * @return this
-	 */
-	public Wrapper<T> in(String column, Object[] value) {
-		if (ArrayUtils.isNotEmpty(value))
-			sql.WHERE(formatSql(inExpression(column, Arrays.asList(value), false), value));
-		return this;
-	}
-
-	/**
-	 * NOT IN 条件语句,目前适配mysql及oracle
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            匹配值 object数组
-	 * @return this
-	 */
-	public Wrapper<T> notIn(String column, Object... value) {
-		if (ArrayUtils.isNotEmpty(value))
-			sql.WHERE(formatSql(inExpression(column, Arrays.asList(value), true), value));
-		return this;
-	}
-
-	/**
-	 * 获取in表达式
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param value
-	 *            集合List
-	 * @param isNot
-	 *            是否为NOT IN操作
-	 */
-	private String inExpression(String column, Collection<?> value, boolean isNot) {
-		if (StringUtils.isNotEmpty(column) && CollectionUtils.isNotEmpty(value)) {
-			StringBuilder inSql = new StringBuilder();
-			inSql.append(column);
-			if (isNot) {
-				inSql.append(" NOT");
-			}
-			inSql.append(" IN ");
-			inSql.append("(");
-			int size = value.size();
-			for (int i = 0; i < size; i++) {
-				inSql.append(String.format(PLACE_HOLDER, i));
-				if (i + 1 < size) {
-					inSql.append(",");
-				}
-			}
-			inSql.append(")");
-			return inSql.toString();
-		}
-		return null;
-	}
-
-	/**
-	 * betwwee 条件语句
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param val1
-	 * @param val2
-	 * @return this
-	 */
-	public Wrapper<T> between(String column, Object val1, Object val2) {
-		sql.WHERE(formatSql(String.format("%s BETWEEN {0} AND {1}", column), val1, val2));
-		return this;
-	}
-
-	/**
-	 * NOT betwwee 条件语句
-	 *
-	 * @param column
-	 *            字段名称
-	 * @param val1
-	 * @param val2
-	 * @return this
-	 */
-	public Wrapper<T> notBetween(String column, Object val1, Object val2) {
-		sql.WHERE(formatSql(String.format("%s NOT BETWEEN {0} AND {1}", column), val1, val2));
-		return this;
-	}
-
-	/**
-	 * 为了兼容之前的版本,可使用where()或and()替代
-	 *
-	 * @param sqlWhere
-	 *            where sql部分
-	 * @param params
-	 *            参数集
-	 * @return this
-	 */
-	public Wrapper<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
-	 */
-	public Wrapper<T> addFilterIfNeed(boolean need, String sqlWhere, Object... params) {
-		return need ? where(sqlWhere, params) : this;
-	}
-
-	/**
-	 * <p>
-	 * SQL注入内容剥离
-	 * </p>
-	 *
-	 * @param value
-	 *            待处理内容
-	 * @return this
-	 */
-	protected String stripSqlInjection(String value) {
-		return value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
-	}
-
-	/**
-	 * <p>
-	 * 格式化SQL
-	 * </p>
-	 *
-	 * @param sqlStr
-	 *            SQL语句部分
-	 * @param params
-	 *            参数集
-	 * @return this
-	 */
-	protected String formatSql(String sqlStr, Object... params) {
-		return formatSqlIfNeed(true, sqlStr, params);
-	}
-
-	/**
-	 * <p>
-	 * 根据需要格式化SQL<BR>
-	 * <BR>
-	 * Format SQL for methods: EntityWrapper.where/and/or...("name={0}", value);
-	 * ALL the {<b>i</b>} will be replaced with #{MPGENVAL<b>i</b>}<BR>
-	 * <BR>
-	 * ew.where("sample_name=<b>{0}</b>", "haha").and("sample_age &gt;<b>{0}</b>
-	 * and sample_age&lt;<b>{1}</b>", 18, 30) <b>TO</b>
-	 * sample_name=<b>#{MPGENVAL1}</b> and sample_age&gt;#<b>{MPGENVAL2}</b> and
-	 * sample_age&lt;<b>#{MPGENVAL3}</b><BR>
-	 * </p>
-	 *
-	 * @param need
-	 *            是否需要格式化
-	 * @param sqlStr
-	 *            SQL语句部分
-	 * @param params
-	 *            参数集
-	 * @return this
-	 */
-	protected String formatSqlIfNeed(boolean need, String sqlStr, Object... params) {
-		if (!need || StringUtils.isEmpty(sqlStr)) {
-			return null;
-		}
-		// #200
-		if (ArrayUtils.isNotEmpty(params)) {
-			for (int i = 0; i < params.length; ++i) {
-				String genParamName = MP_GENERAL_PARAMNAME + paramNameSeq.incrementAndGet();
-				sqlStr = sqlStr.replace(String.format(PLACE_HOLDER, i),
-						String.format(MYBATIS_PLUS_TOKEN, getParamAlias(), genParamName));
-				paramNameValuePairs.put(genParamName, params[i]);
-			}
-		}
-		return sqlStr;
-	}
-
-	/**
-	 * <p>
-	 * 自定义是否输出sql开头为 `WHERE` OR `AND` OR `OR`
-	 * </p>
-	 *
-	 * @param bool
-	 * @return this
-	 */
-	public Wrapper<T> isWhere(Boolean bool) {
-		this.isWhere = bool;
-		return this;
-	}
-
-	/**
-	 * Fix issue 200.
-	 * 
-	 * @since 2.0.3
-	 * @return
-	 */
-	public Map<String, Object> getParamNameValuePairs() {
-		return paramNameValuePairs;
-	}
-
-	public String getParamAlias() {
-		return StringUtils.isEmpty(paramAlias) ? DEFAULT_PARAM_ALIAS : paramAlias;
-	}
-
-	/**
-	 * <p>
-	 * 调用该方法时 应当在吃初始化时优先设置该值 不要重复设置该值 要不然我就给你抛异常了
-	 * </p>
-	 * 
-	 * @param paramAlias
-	 * @return
-	 */
-	public Wrapper<T> setParamAlias(String paramAlias) {
-		if (StringUtils.isNotEmpty(getSqlSegment())) {
-			throw new MybatisPlusException("Error: Please call this method when initializing!");
-		}
-		if (StringUtils.isNotEmpty(this.paramAlias)) {
-			throw new MybatisPlusException("Error: Please do not call the method repeatedly!");
-		}
-		this.paramAlias = paramAlias;
-		return this;
-	}
+    /**
+     * 占位符
+     */
+    private static final String PLACE_HOLDER = "{%s}";
+
+    private static final String MYBATIS_PLUS_TOKEN = "#{%s.paramNameValuePairs.%s}";
+
+    private static final String MP_GENERAL_PARAMNAME = "MPGENVAL";
+
+    private static final String DEFAULT_PARAM_ALIAS = "ew";
+    protected String paramAlias = null;
+    /**
+     * SQL 查询字段内容,例如:id,name,age
+     */
+    protected String sqlSelect = null;
+    /**
+     * 实现了TSQL语法的SQL实体
+     */
+    protected SqlPlus sql = new SqlPlus();
+    /**
+     * 自定义是否输出sql为 WHERE OR AND OR OR
+     */
+    protected Boolean isWhere;
+    /**
+     * 拼接WHERE后应该是AND还是OR
+     */
+    protected String AND_OR = "AND";
+    private Map<String, Object> paramNameValuePairs = new HashMap<String, Object>(4);
+    private AtomicInteger paramNameSeq = new AtomicInteger(0);
+
+    /**
+     * 兼容EntityWrapper
+     *
+     * @return
+     */
+    public T getEntity() {
+        return null;
+    }
+
+    public String getSqlSelect() {
+        if (StringUtils.isEmpty(sqlSelect)) {
+            return null;
+        }
+        return stripSqlInjection(sqlSelect);
+    }
+
+    public Wrapper<T> setSqlSelect(String sqlSelect) {
+        if (StringUtils.isNotEmpty(sqlSelect)) {
+            this.sqlSelect = sqlSelect;
+        }
+        return this;
+    }
+
+    /**
+     * SQL 片段 (子类实现)
+     */
+    public abstract String getSqlSegment();
+
+    public String toString() {
+        String sqlSegment = getSqlSegment();
+        if (StringUtils.isNotEmpty(sqlSegment)) {
+            sqlSegment = sqlSegment.replaceAll("#\\{" + getParamAlias() + ".paramNameValuePairs.MPGENVAL[0-9]+}", "\\?");
+        }
+        return sqlSegment;
+    }
+
+    /**
+     * <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 Wrapper<T> where(String sqlWhere, Object... params) {
+        sql.WHERE(formatSql(sqlWhere, params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field=value"表达式
+     * </p>
+     *
+     * @param column
+     * @param params
+     * @return
+     */
+    public Wrapper<T> eq(String column, Object params) {
+        sql.WHERE(formatSql(String.format("%s = {0}", column), params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field <> value"表达式
+     * </p>
+     *
+     * @param column
+     * @param params
+     * @return
+     */
+    public Wrapper<T> ne(String column, Object params) {
+        sql.WHERE(formatSql(String.format("%s <> {0}", column), params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field=value"表达式
+     * </p>
+     *
+     * @param params
+     * @return
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public Wrapper<T> allEq(Map<String, Object> params) {
+        if (MapUtils.isNotEmpty(params)) {
+            Iterator iterator = params.entrySet().iterator();
+            while (iterator.hasNext()) {
+                Map.Entry<String, Object> entry = (Map.Entry<String, Object>) iterator.next();
+                Object value = entry.getValue();
+                if (StringUtils.checkValNotNull(value)) {
+                    sql.WHERE(formatSql(String.format("%s = {0}", entry.getKey()), entry.getValue()));
+                }
+
+            }
+
+        }
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field>value"表达式
+     * </p>
+     *
+     * @param column
+     * @param params
+     * @return
+     */
+    public Wrapper<T> gt(String column, Object params) {
+        sql.WHERE(formatSql(String.format("%s > {0}", column), params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field>=value"表达式
+     * </p>
+     *
+     * @param column
+     * @param params
+     * @return
+     */
+    public Wrapper<T> ge(String column, Object params) {
+        sql.WHERE(formatSql(String.format("%s >= {0}", column), params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field<value"表达式
+     * </p>
+     *
+     * @param column
+     * @param params
+     * @return
+     */
+    public Wrapper<T> lt(String column, Object params) {
+        sql.WHERE(formatSql(String.format("%s < {0}", column), params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 等同于SQL的"field<=value"表达式
+     * </p>
+     *
+     * @param column
+     * @param params
+     * @return
+     */
+    public Wrapper<T> le(String column, Object params) {
+        sql.WHERE(formatSql(String.format("%s <= {0}", column), params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * AND 连接后续条件
+     * </p>
+     *
+     * @param sqlAnd and条件语句
+     * @param params 参数集
+     * @return this
+     */
+    public Wrapper<T> and(String sqlAnd, Object... params) {
+        sql.AND().WHERE(formatSql(sqlAnd, params));
+        return 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 Wrapper<T> andNew(String sqlAnd, Object... params) {
+        sql.AND_NEW().WHERE(formatSql(sqlAnd, params));
+        return this;
+    }
+
+    /**
+     * <p>
+     * 使用AND连接并换行
+     * </p>
+     * <p>
+     *
+     * @return this
+     */
+    public Wrapper<T> and() {
+        sql.AND_NEW();
+        return this;
+    }
+
+    /**
+     * <p>
+     * 使用OR连接并换行
+     * </p>
+     *
+     * @return this
+     */
+    public Wrapper<T> or() {
+        sql.OR_NEW();
+        return this;
+    }
+
+    /**
+     * <p>
+     * 添加OR条件
+     * </p>
+     *
+     * @param sqlOr  or 条件语句
+     * @param params 参数集
+     * @return this
+     */
+    public Wrapper<T> or(String sqlOr, Object... params) {
+        if (StringUtils.isEmpty(sql.toString())) {
+            AND_OR = "OR";
+        }
+        sql.OR().WHERE(formatSql(sqlOr, params));
+        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 Wrapper<T> orNew(String sqlOr, Object... params) {
+        if (StringUtils.isEmpty(sql.toString())) {
+            AND_OR = "OR";
+        }
+        sql.OR_NEW().WHERE(formatSql(sqlOr, params));
+        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 Wrapper<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<T>
+     */
+    public Wrapper<T> having(String sqlHaving, Object... params) {
+        sql.HAVING(formatSql(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 columns SQL 中的 order by 语句,无需输入 Order By 关键字
+     * @return this
+     */
+    public Wrapper<T> orderBy(String columns) {
+        sql.ORDER_BY(columns);
+        return this;
+    }
+
+    /**
+     * <p>
+     * SQL中orderby关键字跟的条件语句,可根据变更动态排序
+     * </p>
+     *
+     * @param columns SQL 中的 order by 语句,无需输入 Order By 关键字
+     * @param isAsc   是否为升序
+     * @return this
+     */
+    public Wrapper<T> orderBy(String columns, boolean isAsc) {
+        if (StringUtils.isNotEmpty(columns)) {
+            sql.ORDER_BY(columns + (isAsc ? " ASC" : " DESC"));
+        }
+        return this;
+    }
+
+    /**
+     * LIKE条件语句,value中无需前后%
+     *
+     * @param column 字段名称
+     * @param value  匹配值
+     * @return this
+     */
+    public Wrapper<T> like(String column, String value) {
+        handerLike(column, value, SqlLike.DEFAULT, false);
+        return this;
+    }
+
+    /**
+     * NOT LIKE条件语句,value中无需前后%
+     *
+     * @param column 字段名称
+     * @param value  匹配值
+     * @return this
+     */
+    public Wrapper<T> notLike(String column, String value) {
+        handerLike(column, value, SqlLike.DEFAULT, true);
+        return this;
+    }
+
+    /**
+     * 处理LIKE操作
+     *
+     * @param column 字段名称
+     * @param value  like匹配值
+     * @param isNot  是否为NOT LIKE操作
+     */
+    private void handerLike(String column, String value, SqlLike type, boolean isNot) {
+        if (StringUtils.isNotEmpty(column) && StringUtils.isNotEmpty(value)) {
+            StringBuilder inSql = new StringBuilder();
+            inSql.append(column);
+            if (isNot) {
+                inSql.append(" NOT");
+            }
+            inSql.append(" LIKE {0}");
+            sql.WHERE(formatSql(inSql.toString(), SqlUtils.concatLike(value, type)));
+        }
+    }
+
+    /**
+     * LIKE条件语句,value中无需前后%
+     *
+     * @param column 字段名称
+     * @param value  匹配值
+     * @param type
+     * @return this
+     */
+    public Wrapper<T> like(String column, String value, SqlLike type) {
+        handerLike(column, value, type, false);
+        return this;
+    }
+
+    /**
+     * NOT LIKE条件语句,value中无需前后%
+     *
+     * @param column 字段名称
+     * @param value  匹配值
+     * @param type
+     * @return this
+     */
+    public Wrapper<T> notLike(String column, String value, SqlLike type) {
+        handerLike(column, value, type, true);
+        return this;
+    }
+
+    /**
+     * is not null 条件
+     *
+     * @param columns 字段名称。多个字段以逗号分隔。
+     * @return this
+     */
+    public Wrapper<T> isNotNull(String columns) {
+        sql.IS_NOT_NULL(columns);
+        return this;
+    }
+
+    /**
+     * is not null 条件
+     *
+     * @param columns 字段名称。多个字段以逗号分隔。
+     * @return this
+     */
+    public Wrapper<T> isNull(String columns) {
+        sql.IS_NULL(columns);
+        return this;
+    }
+
+    /**
+     * EXISTS 条件语句,目前适配mysql及oracle
+     *
+     * @param value 匹配值
+     * @return this
+     */
+    public Wrapper<T> exists(String value) {
+        sql.EXISTS(value);
+        return this;
+    }
+
+    /**
+     * NOT EXISTS条件语句
+     *
+     * @param value 匹配值
+     * @return this
+     */
+    public Wrapper<T> notExists(String value) {
+        sql.NOT_EXISTS(value);
+        return this;
+    }
+
+    /**
+     * IN 条件语句,目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  逗号拼接的字符串
+     * @return this
+     */
+    public Wrapper<T> in(String column, String value) {
+        if (StringUtils.isNotEmpty(value)) {
+            in(column, StringUtils.splitWorker(value, ",", -1, false));
+        }
+        return this;
+    }
+
+    /**
+     * NOT IN条件语句
+     *
+     * @param column 字段名称
+     * @param value  逗号拼接的字符串
+     * @return this
+     */
+    public Wrapper<T> notIn(String column, String value) {
+        if (StringUtils.isNotEmpty(value)) {
+            notIn(column, StringUtils.splitWorker(value, ",", -1, false));
+        }
+        return this;
+    }
+
+    /**
+     * IN 条件语句,目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  匹配值 List集合
+     * @return this
+     */
+    public Wrapper<T> in(String column, Collection<?> value) {
+        if (CollectionUtils.isNotEmpty(value))
+            sql.WHERE(formatSql(inExpression(column, value, false), value.toArray()));
+        return this;
+    }
+
+    /**
+     * NOT IN 条件语句,目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  匹配值 List集合
+     * @return this
+     */
+    public Wrapper<T> notIn(String column, Collection<?> value) {
+        if (CollectionUtils.isNotEmpty(value))
+            sql.WHERE(formatSql(inExpression(column, value, true), value.toArray()));
+        return this;
+    }
+
+    /**
+     * IN 条件语句,目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  匹配值 object数组
+     * @return this
+     */
+    public Wrapper<T> in(String column, Object[] value) {
+        if (ArrayUtils.isNotEmpty(value))
+            sql.WHERE(formatSql(inExpression(column, Arrays.asList(value), false), value));
+        return this;
+    }
+
+    /**
+     * NOT IN 条件语句,目前适配mysql及oracle
+     *
+     * @param column 字段名称
+     * @param value  匹配值 object数组
+     * @return this
+     */
+    public Wrapper<T> notIn(String column, Object... value) {
+        if (ArrayUtils.isNotEmpty(value))
+            sql.WHERE(formatSql(inExpression(column, Arrays.asList(value), true), value));
+        return this;
+    }
+
+    /**
+     * 获取in表达式
+     *
+     * @param column 字段名称
+     * @param value  集合List
+     * @param isNot  是否为NOT IN操作
+     */
+    private String inExpression(String column, Collection<?> value, boolean isNot) {
+        if (StringUtils.isNotEmpty(column) && CollectionUtils.isNotEmpty(value)) {
+            StringBuilder inSql = new StringBuilder();
+            inSql.append(column);
+            if (isNot) {
+                inSql.append(" NOT");
+            }
+            inSql.append(" IN ");
+            inSql.append("(");
+            int size = value.size();
+            for (int i = 0; i < size; i++) {
+                inSql.append(String.format(PLACE_HOLDER, i));
+                if (i + 1 < size) {
+                    inSql.append(",");
+                }
+            }
+            inSql.append(")");
+            return inSql.toString();
+        }
+        return null;
+    }
+
+    /**
+     * betwwee 条件语句
+     *
+     * @param column 字段名称
+     * @param val1
+     * @param val2
+     * @return this
+     */
+    public Wrapper<T> between(String column, Object val1, Object val2) {
+        sql.WHERE(formatSql(String.format("%s BETWEEN {0} AND {1}", column), val1, val2));
+        return this;
+    }
+
+    /**
+     * NOT betwwee 条件语句
+     *
+     * @param column 字段名称
+     * @param val1
+     * @param val2
+     * @return this
+     */
+    public Wrapper<T> notBetween(String column, Object val1, Object val2) {
+        sql.WHERE(formatSql(String.format("%s NOT BETWEEN {0} AND {1}", column), val1, val2));
+        return this;
+    }
+
+    /**
+     * 为了兼容之前的版本,可使用where()或and()替代
+     *
+     * @param sqlWhere where sql部分
+     * @param params   参数集
+     * @return this
+     */
+    public Wrapper<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
+     */
+    public Wrapper<T> addFilterIfNeed(boolean need, String sqlWhere, Object... params) {
+        return need ? where(sqlWhere, params) : this;
+    }
+
+    /**
+     * <p>
+     * SQL注入内容剥离
+     * </p>
+     *
+     * @param value 待处理内容
+     * @return this
+     */
+    protected String stripSqlInjection(String value) {
+        return value.replaceAll("('.+--)|(--)|(\\|)|(%7C)", "");
+    }
+
+    /**
+     * <p>
+     * 格式化SQL
+     * </p>
+     *
+     * @param sqlStr SQL语句部分
+     * @param params 参数集
+     * @return this
+     */
+    protected String formatSql(String sqlStr, Object... params) {
+        return formatSqlIfNeed(true, sqlStr, params);
+    }
+
+    /**
+     * <p>
+     * 根据需要格式化SQL<BR>
+     * <BR>
+     * Format SQL for methods: EntityWrapper.where/and/or...("name={0}", value);
+     * ALL the {<b>i</b>} will be replaced with #{MPGENVAL<b>i</b>}<BR>
+     * <BR>
+     * ew.where("sample_name=<b>{0}</b>", "haha").and("sample_age &gt;<b>{0}</b>
+     * and sample_age&lt;<b>{1}</b>", 18, 30) <b>TO</b>
+     * sample_name=<b>#{MPGENVAL1}</b> and sample_age&gt;#<b>{MPGENVAL2}</b> and
+     * sample_age&lt;<b>#{MPGENVAL3}</b><BR>
+     * </p>
+     *
+     * @param need   是否需要格式化
+     * @param sqlStr SQL语句部分
+     * @param params 参数集
+     * @return this
+     */
+    protected String formatSqlIfNeed(boolean need, String sqlStr, Object... params) {
+        if (!need || StringUtils.isEmpty(sqlStr)) {
+            return null;
+        }
+        // #200
+        if (ArrayUtils.isNotEmpty(params)) {
+            for (int i = 0; i < params.length; ++i) {
+                String genParamName = MP_GENERAL_PARAMNAME + paramNameSeq.incrementAndGet();
+                sqlStr = sqlStr.replace(String.format(PLACE_HOLDER, i),
+                        String.format(MYBATIS_PLUS_TOKEN, getParamAlias(), genParamName));
+                paramNameValuePairs.put(genParamName, params[i]);
+            }
+        }
+        return sqlStr;
+    }
+
+    /**
+     * <p>
+     * 自定义是否输出sql开头为 `WHERE` OR `AND` OR `OR`
+     * </p>
+     *
+     * @param bool
+     * @return this
+     */
+    public Wrapper<T> isWhere(Boolean bool) {
+        this.isWhere = bool;
+        return this;
+    }
+
+    /**
+     * Fix issue 200.
+     *
+     * @return
+     * @since 2.0.3
+     */
+    public Map<String, Object> getParamNameValuePairs() {
+        return paramNameValuePairs;
+    }
+
+    public String getParamAlias() {
+        return StringUtils.isEmpty(paramAlias) ? DEFAULT_PARAM_ALIAS : paramAlias;
+    }
+
+    /**
+     * <p>
+     * 调用该方法时 应当在吃初始化时优先设置该值 不要重复设置该值 要不然我就给你抛异常了
+     * </p>
+     *
+     * @param paramAlias
+     * @return
+     */
+    public Wrapper<T> setParamAlias(String paramAlias) {
+        if (StringUtils.isNotEmpty(getSqlSegment())) {
+            throw new MybatisPlusException("Error: Please call this method when initializing!");
+        }
+        if (StringUtils.isNotEmpty(this.paramAlias)) {
+            throw new MybatisPlusException("Error: Please do not call the method repeatedly!");
+        }
+        this.paramAlias = paramAlias;
+        return this;
+    }
 }

+ 103 - 102
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/CachePaginationInterceptor.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -48,105 +48,106 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @Date 2016-01-23
  */
 @Intercepts({
-		@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class,
-				ResultHandler.class }),
-		@Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
+        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class,
+                ResultHandler.class}),
+        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
 public class CachePaginationInterceptor extends PaginationInterceptor implements Interceptor {
-	/* Count优化方式 */
-	private String optimizeType = "default";
-	/* 方言类型 */
-	private String dialectType;
-	/* 方言实现类 */
-	private String dialectClazz;
-
-	/**
-	 * Physical Pagination Interceptor for all the queries with parameter
-	 * {@link org.apache.ibatis.session.RowBounds}
-	 */
-	public Object intercept(Invocation invocation) throws Throwable {
-
-		Object target = invocation.getTarget();
-		if (target instanceof StatementHandler) {
-			StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
-			MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
-			RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
-
-			if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
-				return invocation.proceed();
-			}
-			BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
-			String originalSql = (String) boundSql.getSql();
-
-			if (rowBounds instanceof Pagination) {
-				Pagination page = (Pagination) rowBounds;
-				boolean orderBy = true;
-				if (page.isSearchCount()) {
-					CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, optimizeType, dialectType,
-							page.isOptimizeCount());
-					orderBy = countOptimize.isOrderBy();
-				}
-				String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
-				originalSql = DialectFactory.buildPaginationSql(page, buildSql, dialectType, dialectClazz);
-			} else {
-				// support physical Pagination for RowBounds
-				originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dialectType, dialectClazz);
-			}
-
-			metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
-			metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
-			metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
-		} else {
-			MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
-			Object parameterObject = invocation.getArgs()[1];
-			RowBounds rowBounds = (RowBounds) invocation.getArgs()[2];
-			if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
-				return invocation.proceed();
-			}
-
-			BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
-			String originalSql = (String) boundSql.getSql();
-			if (rowBounds instanceof Pagination) {
-				Pagination page = (Pagination) rowBounds;
-				if (page.isSearchCount()) {
-					CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, optimizeType, dialectType,
-							page.isOptimizeCount());
-					super.count(countOptimize.getCountSQL(), mappedStatement, boundSql, page);
-					if (page.getTotal() <= 0) {
-						return invocation.proceed();
-					}
-				}
-			}
-		}
-		return invocation.proceed();
-	}
-
-	public Object plugin(Object target) {
-		if (target instanceof Executor) {
-			return Plugin.wrap(target, this);
-		}
-		if (target instanceof StatementHandler) {
-			return Plugin.wrap(target, this);
-		}
-		return target;
-	}
-
-	public void setProperties(Properties prop) {
-		String dialectType = prop.getProperty("dialectType");
-		String dialectClazz = prop.getProperty("dialectClazz");
-		if (StringUtils.isNotEmpty(dialectType)) {
-			this.dialectType = dialectType;
-		}
-		if (StringUtils.isNotEmpty(dialectClazz)) {
-			this.dialectClazz = dialectClazz;
-		}
-	}
-
-	public void setDialectType(String dialectType) {
-		this.dialectType = dialectType;
-	}
-
-	public void setOptimizeType(String optimizeType) {
-		this.optimizeType = optimizeType;
-	}
+
+    /* Count优化方式 */
+    private String optimizeType = "default";
+    /* 方言类型 */
+    private String dialectType;
+    /* 方言实现类 */
+    private String dialectClazz;
+
+    /**
+     * Physical Pagination Interceptor for all the queries with parameter
+     * {@link org.apache.ibatis.session.RowBounds}
+     */
+    public Object intercept(Invocation invocation) throws Throwable {
+
+        Object target = invocation.getTarget();
+        if (target instanceof StatementHandler) {
+            StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
+            MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
+            RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
+
+            if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
+                return invocation.proceed();
+            }
+            BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
+            String originalSql = boundSql.getSql();
+
+            if (rowBounds instanceof Pagination) {
+                Pagination page = (Pagination) rowBounds;
+                boolean orderBy = true;
+                if (page.isSearchCount()) {
+                    CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, optimizeType, dialectType,
+                            page.isOptimizeCount());
+                    orderBy = countOptimize.isOrderBy();
+                }
+                String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
+                originalSql = DialectFactory.buildPaginationSql(page, buildSql, dialectType, dialectClazz);
+            } else {
+                // support physical Pagination for RowBounds
+                originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dialectType, dialectClazz);
+            }
+
+            metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
+            metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
+            metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
+        } else {
+            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
+            Object parameterObject = invocation.getArgs()[1];
+            RowBounds rowBounds = (RowBounds) invocation.getArgs()[2];
+            if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
+                return invocation.proceed();
+            }
+
+            BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
+            String originalSql = boundSql.getSql();
+            if (rowBounds instanceof Pagination) {
+                Pagination page = (Pagination) rowBounds;
+                if (page.isSearchCount()) {
+                    CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, optimizeType, dialectType,
+                            page.isOptimizeCount());
+                    super.count(countOptimize.getCountSQL(), mappedStatement, boundSql, page);
+                    if (page.getTotal() <= 0) {
+                        return invocation.proceed();
+                    }
+                }
+            }
+        }
+        return invocation.proceed();
+    }
+
+    public Object plugin(Object target) {
+        if (target instanceof Executor) {
+            return Plugin.wrap(target, this);
+        }
+        if (target instanceof StatementHandler) {
+            return Plugin.wrap(target, this);
+        }
+        return target;
+    }
+
+    public void setProperties(Properties prop) {
+        String dialectType = prop.getProperty("dialectType");
+        String dialectClazz = prop.getProperty("dialectClazz");
+        if (StringUtils.isNotEmpty(dialectType)) {
+            this.dialectType = dialectType;
+        }
+        if (StringUtils.isNotEmpty(dialectClazz)) {
+            this.dialectClazz = dialectClazz;
+        }
+    }
+
+    public void setDialectType(String dialectType) {
+        this.dialectType = dialectType;
+    }
+
+    public void setOptimizeType(String optimizeType) {
+        this.optimizeType = optimizeType;
+    }
 
 }

+ 231 - 233
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/OptimisticLockerInterceptor.java

@@ -37,7 +37,6 @@ import com.baomidou.mybatisplus.mapper.EntityWrapper;
 import com.baomidou.mybatisplus.toolkit.PluginUtils;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 
-import net.sf.jsqlparser.JSQLParserException;
 import net.sf.jsqlparser.expression.BinaryExpression;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
@@ -49,7 +48,7 @@ import net.sf.jsqlparser.statement.update.Update;
 /**
  * MyBatis乐观锁插件
  * <p>
- * 
+ * <p>
  * <pre>
  * 之前:update user set name = ?, password = ? where id = ?
  * 之后:update user set name = ?, password = ?, version = version+1 where id = ? and version = ?
@@ -61,237 +60,236 @@ import net.sf.jsqlparser.statement.update.Update;
  *
  * @author TaoYu
  */
-@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
 public final class OptimisticLockerInterceptor implements Interceptor {
 
-	/**
-	 * 根据对象类型缓存version基本信息
-	 */
-	private static final Map<Class<?>, CachePo> versionCache = new ConcurrentHashMap<Class<?>, CachePo>();
-
-	/**
-	 * 根据version字段类型缓存的处理器
-	 */
-	private static final Map<Class<?>, VersionHandler<?>> typeHandlers = new HashMap<Class<?>, VersionHandler<?>>();
-
-	static {
-		ShortTypeHandler shortTypeHandler = new ShortTypeHandler();
-		typeHandlers.put(short.class, shortTypeHandler);
-		typeHandlers.put(Short.class, shortTypeHandler);
-
-		IntegerTypeHandler integerTypeHandler = new IntegerTypeHandler();
-		typeHandlers.put(int.class, integerTypeHandler);
-		typeHandlers.put(Integer.class, integerTypeHandler);
-
-		LongTypeHandler longTypeHandler = new LongTypeHandler();
-		typeHandlers.put(long.class, longTypeHandler);
-		typeHandlers.put(Long.class, longTypeHandler);
-
-		typeHandlers.put(Date.class, new DateTypeHandler());
-		typeHandlers.put(Timestamp.class, new TimestampTypeHandler());
-	}
-
-	public Object intercept(Invocation invocation) throws Exception {
-		StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
-		MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
-		// 先判断入参为null或者不是真正的UPDATE语句
-		MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
-		if (!ms.getSqlCommandType().equals(SqlCommandType.UPDATE)) {
-			return invocation.proceed();
-		}
-		BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
-		// 获得参数类型,去缓存中快速判断是否有version注解才继续执行
-		Class<?> parameterClass = ms.getParameterMap().getType();
-		CachePo versionPo = versionCache.get(parameterClass);
-		if (versionPo != null) {
-			if (versionPo.isVersionControl) {
-				processChangeSql(ms, boundSql, versionPo);
-			}
-		} else {
-			String versionColumn = null;
-			Field versionField = null;
-			for (final Field field : parameterClass.getDeclaredFields()) {
-				if (field.isAnnotationPresent(Version.class)) {
-					if (!typeHandlers.containsKey(field.getType())) {
-						throw new TypeException("乐观锁不支持" + field.getType().getName() + "类型,请自定义实现");
-					}
-					versionField = field;
-					final TableField tableField = field.getAnnotation(TableField.class);
-					if (tableField != null) {
-						versionColumn = tableField.value();
-					} else {
-						versionColumn = field.getName();
-					}
-					break;
-				}
-			}
-			if (versionField != null) {
-				versionField.setAccessible(true);
-				CachePo cachePo = new CachePo(true, versionColumn, versionField);
-				versionCache.put(parameterClass, cachePo);
-				processChangeSql(ms, boundSql, cachePo);
-			} else {
-				versionCache.put(parameterClass, new CachePo(false));
-			}
-		}
-		return invocation.proceed();
-
-	}
-
-	private static final Expression RIGHTEXPRESSION = new Column("?");
-
-	private void processChangeSql(MappedStatement ms, BoundSql boundSql, CachePo cachePo) throws Exception {
-		Field versionField = cachePo.versionField;
-		String versionColumn = cachePo.versionColumn;
-		Object parameterObject = boundSql.getParameterObject();
-		if (parameterObject instanceof ParamMap) {
-			ParamMap<?> paramMap = (ParamMap<?>) parameterObject;
-			parameterObject = paramMap.get("et");
-			EntityWrapper<?> entityWrapper = (EntityWrapper<?>) paramMap.get("ew");
-			if (entityWrapper != null) {
-				Object entity = entityWrapper.getEntity();
-				if (entity != null && versionField.get(entity) == null) {
-					changSql(ms, boundSql, versionField, versionColumn, parameterObject);
-				}
-			}
-		} else {
-			changSql(ms, boundSql, versionField, versionColumn, parameterObject);
-		}
-	}
-
-	@SuppressWarnings({ "unchecked", "rawtypes" })
-	private void changSql(MappedStatement ms, BoundSql boundSql, Field versionField, String versionColumn, Object parameterObject)
-			throws IllegalAccessException, Exception, JSQLParserException {
-		final Object versionValue = versionField.get(parameterObject);
-		if (versionValue != null) {// 先判断传参是否携带version,没带跳过插件
-			Configuration configuration = ms.getConfiguration();
-			// 给字段赋新值
-			VersionHandler targetHandler = typeHandlers.get(versionField.getType());
-			targetHandler.plusVersion(parameterObject, versionField, versionValue);
-			// 处理where条件,添加?
-			Update jsqlSql = (Update) CCJSqlParserUtil.parse(boundSql.getSql());
-			BinaryExpression expression = (BinaryExpression) jsqlSql.getWhere();
-			if (expression != null && !expression.toString().contains(versionColumn)) {
-				EqualsTo equalsTo = new EqualsTo();
-				equalsTo.setLeftExpression(new Column(versionColumn));
-				equalsTo.setRightExpression(RIGHTEXPRESSION);
-				jsqlSql.setWhere(new AndExpression(equalsTo, expression));
-				List<ParameterMapping> parameterMappings = new LinkedList<ParameterMapping>(boundSql.getParameterMappings());
-				parameterMappings.add(jsqlSql.getExpressions().size(), getVersionMappingInstance(configuration));
-				MetaObject boundSqlMeta = configuration.newMetaObject(boundSql);
-				boundSqlMeta.setValue("sql", jsqlSql.toString());
-				boundSqlMeta.setValue("parameterMappings", parameterMappings);
-			}
-			// 设置参数
-			boundSql.setAdditionalParameter("originVersionValue", versionValue);
-		}
-	}
-
-	private volatile ParameterMapping parameterMapping;
-
-	private ParameterMapping getVersionMappingInstance(Configuration configuration) {
-		if (parameterMapping == null) {
-			synchronized (OptimisticLockerInterceptor.class) {
-				if (parameterMapping == null) {
-					parameterMapping = new ParameterMapping.Builder(configuration, "originVersionValue", new UnknownTypeHandler(configuration.getTypeHandlerRegistry())).build();
-				}
-			}
-		}
-		return parameterMapping;
-	}
-
-	@Override
-	public Object plugin(Object target) {
-		if (target instanceof StatementHandler) {
-			return Plugin.wrap(target, this);
-		}
-		return target;
-	}
-
-	@Override
-	public void setProperties(Properties properties) {
-		String versionHandlers = properties.getProperty("versionHandlers");
-		if (StringUtils.isNotEmpty(versionHandlers)) {
-			String[] userHandlers = versionHandlers.split(",");
-			for (String handlerClazz : userHandlers) {
-				try {
-					VersionHandler<?> versionHandler = (VersionHandler<?>) Class.forName(handlerClazz).newInstance();
-					registerHandler(versionHandler);
-				} catch (Exception e) {
-					throw ExceptionFactory.wrapException("乐观锁插件自定义处理器注册失败", e);
-				}
-			}
-		}
-	}
-
-	/**
-	 * 注册处理器
-	 */
-	private static void registerHandler(VersionHandler<?> versionHandler) {
-		Type[] genericInterfaces = versionHandler.getClass().getGenericInterfaces();
-		ParameterizedType parameterizedType = (ParameterizedType) genericInterfaces[0];
-		Class<?> type = (Class<?>) parameterizedType.getActualTypeArguments()[0];
-		typeHandlers.put(type, versionHandler);
-	}
-
-	/**
-	 * 缓存对象
-	 */
-	private class CachePo {
-
-		private Boolean isVersionControl;
-
-		private String versionColumn;
-
-		private Field versionField;
-
-		public CachePo(Boolean isVersionControl) {
-			this.isVersionControl = isVersionControl;
-		}
-
-		public CachePo(Boolean isVersionControl, String versionColumn, Field versionField) {
-			this.isVersionControl = isVersionControl;
-			this.versionColumn = versionColumn;
-			this.versionField = versionField;
-		}
-
-	}
-
-	// *****************************基本类型处理器*****************************
-
-	private static class ShortTypeHandler implements VersionHandler<Short> {
-
-		public void plusVersion(Object paramObj, Field field, Short versionValue) throws Exception {
-			field.set(paramObj, (short) (versionValue + 1));
-		}
-	}
-
-	private static class IntegerTypeHandler implements VersionHandler<Integer> {
-
-		public void plusVersion(Object paramObj, Field field, Integer versionValue) throws Exception {
-			field.set(paramObj, versionValue + 1);
-		}
-	}
-
-	private static class LongTypeHandler implements VersionHandler<Long> {
-
-		public void plusVersion(Object paramObj, Field field, Long versionValue) throws Exception {
-			field.set(paramObj, versionValue + 1);
-		}
-	}
-
-	// ***************************** 时间类型处理器*****************************
-	private static class DateTypeHandler implements VersionHandler<Date> {
-
-		public void plusVersion(Object paramObj, Field field, Date versionValue) throws Exception {
-			field.set(paramObj, new Date());
-		}
-	}
-
-	private static class TimestampTypeHandler implements VersionHandler<Timestamp> {
-
-		public void plusVersion(Object paramObj, Field field, Timestamp versionValue) throws Exception {
-			field.set(paramObj, new Timestamp(new Date().getTime()));
-		}
-	}
+    /**
+     * 根据对象类型缓存version基本信息
+     */
+    private static final Map<Class<?>, CachePo> versionCache = new ConcurrentHashMap<Class<?>, CachePo>();
+
+    /**
+     * 根据version字段类型缓存的处理器
+     */
+    private static final Map<Class<?>, VersionHandler<?>> typeHandlers = new HashMap<Class<?>, VersionHandler<?>>();
+    private static final Expression RIGHTEXPRESSION = new Column("?");
+
+    static {
+        ShortTypeHandler shortTypeHandler = new ShortTypeHandler();
+        typeHandlers.put(short.class, shortTypeHandler);
+        typeHandlers.put(Short.class, shortTypeHandler);
+
+        IntegerTypeHandler integerTypeHandler = new IntegerTypeHandler();
+        typeHandlers.put(int.class, integerTypeHandler);
+        typeHandlers.put(Integer.class, integerTypeHandler);
+
+        LongTypeHandler longTypeHandler = new LongTypeHandler();
+        typeHandlers.put(long.class, longTypeHandler);
+        typeHandlers.put(Long.class, longTypeHandler);
+
+        typeHandlers.put(Date.class, new DateTypeHandler());
+        typeHandlers.put(Timestamp.class, new TimestampTypeHandler());
+    }
+
+    private volatile ParameterMapping parameterMapping;
+
+    /**
+     * 注册处理器
+     */
+    private static void registerHandler(VersionHandler<?> versionHandler) {
+        Type[] genericInterfaces = versionHandler.getClass().getGenericInterfaces();
+        ParameterizedType parameterizedType = (ParameterizedType) genericInterfaces[0];
+        Class<?> type = (Class<?>) parameterizedType.getActualTypeArguments()[0];
+        typeHandlers.put(type, versionHandler);
+    }
+
+    public Object intercept(Invocation invocation) throws Exception {
+        StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
+        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
+        // 先判断入参为null或者不是真正的UPDATE语句
+        MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
+        if (!ms.getSqlCommandType().equals(SqlCommandType.UPDATE)) {
+            return invocation.proceed();
+        }
+        BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
+        // 获得参数类型,去缓存中快速判断是否有version注解才继续执行
+        Class<?> parameterClass = ms.getParameterMap().getType();
+        CachePo versionPo = versionCache.get(parameterClass);
+        if (versionPo != null) {
+            if (versionPo.isVersionControl) {
+                processChangeSql(ms, boundSql, versionPo);
+            }
+        } else {
+            String versionColumn = null;
+            Field versionField = null;
+            for (final Field field : parameterClass.getDeclaredFields()) {
+                if (field.isAnnotationPresent(Version.class)) {
+                    if (!typeHandlers.containsKey(field.getType())) {
+                        throw new TypeException("乐观锁不支持" + field.getType().getName() + "类型,请自定义实现");
+                    }
+                    versionField = field;
+                    final TableField tableField = field.getAnnotation(TableField.class);
+                    if (tableField != null) {
+                        versionColumn = tableField.value();
+                    } else {
+                        versionColumn = field.getName();
+                    }
+                    break;
+                }
+            }
+            if (versionField != null) {
+                versionField.setAccessible(true);
+                CachePo cachePo = new CachePo(true, versionColumn, versionField);
+                versionCache.put(parameterClass, cachePo);
+                processChangeSql(ms, boundSql, cachePo);
+            } else {
+                versionCache.put(parameterClass, new CachePo(false));
+            }
+        }
+        return invocation.proceed();
+
+    }
+
+    private void processChangeSql(MappedStatement ms, BoundSql boundSql, CachePo cachePo) throws Exception {
+        Field versionField = cachePo.versionField;
+        String versionColumn = cachePo.versionColumn;
+        Object parameterObject = boundSql.getParameterObject();
+        if (parameterObject instanceof ParamMap) {
+            ParamMap<?> paramMap = (ParamMap<?>) parameterObject;
+            parameterObject = paramMap.get("et");
+            EntityWrapper<?> entityWrapper = (EntityWrapper<?>) paramMap.get("ew");
+            if (entityWrapper != null) {
+                Object entity = entityWrapper.getEntity();
+                if (entity != null && versionField.get(entity) == null) {
+                    changSql(ms, boundSql, versionField, versionColumn, parameterObject);
+                }
+            }
+        } else {
+            changSql(ms, boundSql, versionField, versionColumn, parameterObject);
+        }
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private void changSql(MappedStatement ms, BoundSql boundSql, Field versionField, String versionColumn, Object parameterObject)
+            throws Exception {
+        final Object versionValue = versionField.get(parameterObject);
+        if (versionValue != null) {// 先判断传参是否携带version,没带跳过插件
+            Configuration configuration = ms.getConfiguration();
+            // 给字段赋新值
+            VersionHandler targetHandler = typeHandlers.get(versionField.getType());
+            targetHandler.plusVersion(parameterObject, versionField, versionValue);
+            // 处理where条件,添加?
+            Update jsqlSql = (Update) CCJSqlParserUtil.parse(boundSql.getSql());
+            BinaryExpression expression = (BinaryExpression) jsqlSql.getWhere();
+            if (expression != null && !expression.toString().contains(versionColumn)) {
+                EqualsTo equalsTo = new EqualsTo();
+                equalsTo.setLeftExpression(new Column(versionColumn));
+                equalsTo.setRightExpression(RIGHTEXPRESSION);
+                jsqlSql.setWhere(new AndExpression(equalsTo, expression));
+                List<ParameterMapping> parameterMappings = new LinkedList<ParameterMapping>(boundSql.getParameterMappings());
+                parameterMappings.add(jsqlSql.getExpressions().size(), getVersionMappingInstance(configuration));
+                MetaObject boundSqlMeta = configuration.newMetaObject(boundSql);
+                boundSqlMeta.setValue("sql", jsqlSql.toString());
+                boundSqlMeta.setValue("parameterMappings", parameterMappings);
+            }
+            // 设置参数
+            boundSql.setAdditionalParameter("originVersionValue", versionValue);
+        }
+    }
+
+    private ParameterMapping getVersionMappingInstance(Configuration configuration) {
+        if (parameterMapping == null) {
+            synchronized (OptimisticLockerInterceptor.class) {
+                if (parameterMapping == null) {
+                    parameterMapping = new ParameterMapping.Builder(configuration, "originVersionValue", new UnknownTypeHandler(configuration.getTypeHandlerRegistry())).build();
+                }
+            }
+        }
+        return parameterMapping;
+    }
+
+    @Override
+    public Object plugin(Object target) {
+        if (target instanceof StatementHandler) {
+            return Plugin.wrap(target, this);
+        }
+        return target;
+    }
+
+    @Override
+    public void setProperties(Properties properties) {
+        String versionHandlers = properties.getProperty("versionHandlers");
+        if (StringUtils.isNotEmpty(versionHandlers)) {
+            String[] userHandlers = versionHandlers.split(",");
+            for (String handlerClazz : userHandlers) {
+                try {
+                    VersionHandler<?> versionHandler = (VersionHandler<?>) Class.forName(handlerClazz).newInstance();
+                    registerHandler(versionHandler);
+                } catch (Exception e) {
+                    throw ExceptionFactory.wrapException("乐观锁插件自定义处理器注册失败", e);
+                }
+            }
+        }
+    }
+
+    private static class ShortTypeHandler implements VersionHandler<Short> {
+
+        public void plusVersion(Object paramObj, Field field, Short versionValue) throws Exception {
+            field.set(paramObj, (short) (versionValue + 1));
+        }
+    }
+
+    // *****************************基本类型处理器*****************************
+
+    private static class IntegerTypeHandler implements VersionHandler<Integer> {
+
+        public void plusVersion(Object paramObj, Field field, Integer versionValue) throws Exception {
+            field.set(paramObj, versionValue + 1);
+        }
+    }
+
+    private static class LongTypeHandler implements VersionHandler<Long> {
+
+        public void plusVersion(Object paramObj, Field field, Long versionValue) throws Exception {
+            field.set(paramObj, versionValue + 1);
+        }
+    }
+
+    // ***************************** 时间类型处理器*****************************
+    private static class DateTypeHandler implements VersionHandler<Date> {
+
+        public void plusVersion(Object paramObj, Field field, Date versionValue) throws Exception {
+            field.set(paramObj, new Date());
+        }
+    }
+
+    private static class TimestampTypeHandler implements VersionHandler<Timestamp> {
+
+        public void plusVersion(Object paramObj, Field field, Timestamp versionValue) throws Exception {
+            field.set(paramObj, new Timestamp(new Date().getTime()));
+        }
+    }
+
+    /**
+     * 缓存对象
+     */
+    private class CachePo {
+
+        private Boolean isVersionControl;
+
+        private String versionColumn;
+
+        private Field versionField;
+
+        public CachePo(Boolean isVersionControl) {
+            this.isVersionControl = isVersionControl;
+        }
+
+        public CachePo(Boolean isVersionControl, String versionColumn, Field versionField) {
+            this.isVersionControl = isVersionControl;
+            this.versionColumn = versionColumn;
+            this.versionField = versionField;
+        }
+
+    }
 }

+ 44 - 44
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/Page.java

@@ -15,13 +15,13 @@
  */
 package com.baomidou.mybatisplus.plugins;
 
-import com.baomidou.mybatisplus.plugins.pagination.Pagination;
-
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
+import com.baomidou.mybatisplus.plugins.pagination.Pagination;
+
 /**
  * <p>
  * 实现分页辅助类
@@ -32,57 +32,57 @@ import java.util.concurrent.ConcurrentHashMap;
  */
 public class Page<T> extends Pagination {
 
-	private static final long serialVersionUID = 1L;
+    private static final long serialVersionUID = 1L;
 
-	/**
-	 * 查询数据列表
-	 */
-	private List<T> records = Collections.emptyList();
+    /**
+     * 查询数据列表
+     */
+    private List<T> records = Collections.emptyList();
 
-	/**
-	 * 查询参数
-	 */
-	private Map<String, Object> condition = new ConcurrentHashMap<String, Object>();
+    /**
+     * 查询参数
+     */
+    private Map<String, Object> condition = new ConcurrentHashMap<String, Object>();
 
-	public Page() {
-		/* 注意,传入翻页参数 */
-	}
+    public Page() {
+        /* 注意,传入翻页参数 */
+    }
 
-	public Page(int current, int size) {
-		super(current, size);
-	}
+    public Page(int current, int size) {
+        super(current, size);
+    }
 
-	public Page(int current, int size, String orderByField) {
-		super(current, size);
-		this.setOrderByField(orderByField);
-	}
+    public Page(int current, int size, String orderByField) {
+        super(current, size);
+        this.setOrderByField(orderByField);
+    }
 
-	public List<T> getRecords() {
-		return records;
-	}
+    public List<T> getRecords() {
+        return records;
+    }
 
-	public void setRecords(List<T> records) {
-		this.records = records;
-	}
+    public void setRecords(List<T> records) {
+        this.records = records;
+    }
 
-	public Map<String, Object> getCondition() {
-		return condition;
-	}
+    public Map<String, Object> getCondition() {
+        return condition;
+    }
 
-	public void setCondition(Map<String, Object> condition) {
-		this.condition = condition;
-	}
+    public void setCondition(Map<String, Object> condition) {
+        this.condition = condition;
+    }
 
-	@Override
-	public String toString() {
-		StringBuilder pg = new StringBuilder();
-		pg.append(" Page:{ [").append(super.toString()).append("], ");
-		if (records != null) {
-			pg.append("records-size:").append(records.size());
-		} else {
-			pg.append("records is null");
-		}
-		return pg.append(" }").toString();
-	}
+    @Override
+    public String toString() {
+        StringBuilder pg = new StringBuilder();
+        pg.append(" Page:{ [").append(super.toString()).append("], ");
+        if (records != null) {
+            pg.append("records-size:").append(records.size());
+        } else {
+            pg.append("records is null");
+        }
+        return pg.append(" }").toString();
+    }
 
 }

+ 141 - 140
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/PaginationInterceptor.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,14 +15,11 @@
  */
 package com.baomidou.mybatisplus.plugins;
 
-import com.baomidou.mybatisplus.MybatisDefaultParameterHandler;
-import com.baomidou.mybatisplus.entity.CountOptimize;
-import com.baomidou.mybatisplus.plugins.pagination.DialectFactory;
-import com.baomidou.mybatisplus.plugins.pagination.Pagination;
-import com.baomidou.mybatisplus.toolkit.IOUtils;
-import com.baomidou.mybatisplus.toolkit.PluginUtils;
-import com.baomidou.mybatisplus.toolkit.SqlUtils;
-import com.baomidou.mybatisplus.toolkit.StringUtils;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Properties;
+
 import org.apache.ibatis.executor.statement.StatementHandler;
 import org.apache.ibatis.logging.Log;
 import org.apache.ibatis.logging.LogFactory;
@@ -38,10 +35,14 @@ import org.apache.ibatis.reflection.SystemMetaObject;
 import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
 import org.apache.ibatis.session.RowBounds;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.Properties;
+import com.baomidou.mybatisplus.MybatisDefaultParameterHandler;
+import com.baomidou.mybatisplus.entity.CountOptimize;
+import com.baomidou.mybatisplus.plugins.pagination.DialectFactory;
+import com.baomidou.mybatisplus.plugins.pagination.Pagination;
+import com.baomidou.mybatisplus.toolkit.IOUtils;
+import com.baomidou.mybatisplus.toolkit.PluginUtils;
+import com.baomidou.mybatisplus.toolkit.SqlUtils;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
 
 /**
  * <p>
@@ -51,140 +52,140 @@ import java.util.Properties;
  * @author hubin
  * @Date 2016-01-23
  */
-@Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class, Integer.class }) })
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
 public class PaginationInterceptor implements Interceptor {
 
-	private static final Log logger = LogFactory.getLog(PaginationInterceptor.class);
-
-	/* 溢出总页数,设置第一页 */
-	private boolean overflowCurrent = false;
-	/* Count优化方式 */
-	private String optimizeType = "default";
-	/* 方言类型 */
-	private String dialectType;
-	/* 方言实现类 */
-	private String dialectClazz;
-
-	/**
-	 * Physical Pagination Interceptor for all the queries with parameter
-	 * {@link org.apache.ibatis.session.RowBounds}
-	 */
-	public Object intercept(Invocation invocation) throws Throwable {
-		Object target = invocation.getTarget();
-		if (target instanceof StatementHandler) {
-			StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
-			MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
-			RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
+    private static final Log logger = LogFactory.getLog(PaginationInterceptor.class);
+
+    /* 溢出总页数,设置第一页 */
+    private boolean overflowCurrent = false;
+    /* Count优化方式 */
+    private String optimizeType = "default";
+    /* 方言类型 */
+    private String dialectType;
+    /* 方言实现类 */
+    private String dialectClazz;
+
+    /**
+     * Physical Pagination Interceptor for all the queries with parameter
+     * {@link org.apache.ibatis.session.RowBounds}
+     */
+    public Object intercept(Invocation invocation) throws Throwable {
+        Object target = invocation.getTarget();
+        if (target instanceof StatementHandler) {
+            StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
+            MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
+            RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
 
 			/* 不需要分页的场合 */
-			if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
-				return invocation.proceed();
-			}
-			BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
-			String originalSql = (String) boundSql.getSql();
-
-			if (rowBounds instanceof Pagination) {
-				MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
-				Pagination page = (Pagination) rowBounds;
-				boolean orderBy = true;
-				if (page.isSearchCount()) {
-					CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, optimizeType, dialectType,
-							page.isOptimizeCount());
-					orderBy = countOptimize.isOrderBy();
-					this.count(countOptimize.getCountSQL(), mappedStatement, boundSql, page);
-					if (page.getTotal() <= 0) {
-						return invocation.proceed();
-					}
-				}
-				String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
-				originalSql = DialectFactory.buildPaginationSql(page, buildSql, dialectType, dialectClazz);
-			} else {
-				// support physical Pagination for RowBounds
-				originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dialectType, dialectClazz);
-			}
+            if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
+                return invocation.proceed();
+            }
+            BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
+            String originalSql = boundSql.getSql();
+
+            if (rowBounds instanceof Pagination) {
+                MappedStatement mappedStatement = (MappedStatement) metaStatementHandler.getValue("delegate.mappedStatement");
+                Pagination page = (Pagination) rowBounds;
+                boolean orderBy = true;
+                if (page.isSearchCount()) {
+                    CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, optimizeType, dialectType,
+                            page.isOptimizeCount());
+                    orderBy = countOptimize.isOrderBy();
+                    this.count(countOptimize.getCountSQL(), mappedStatement, boundSql, page);
+                    if (page.getTotal() <= 0) {
+                        return invocation.proceed();
+                    }
+                }
+                String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
+                originalSql = DialectFactory.buildPaginationSql(page, buildSql, dialectType, dialectClazz);
+            } else {
+                // support physical Pagination for RowBounds
+                originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dialectType, dialectClazz);
+            }
 
 			/*
-			 * <p> 禁用内存分页 </p> <p> 内存分页会查询所有结果出来处理(这个很吓人的),如果结果变化频繁这个数据还会不准。</p>
+             * <p> 禁用内存分页 </p> <p> 内存分页会查询所有结果出来处理(这个很吓人的),如果结果变化频繁这个数据还会不准。</p>
 			 */
-			metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
-			metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
-			metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
-		}
-		return invocation.proceed();
-	}
-
-	/**
-	 * 查询总记录条数
-	 *
-	 * @param sql
-	 * @param mappedStatement
-	 * @param boundSql
-	 * @param page
-	 */
-	protected void count(String sql, MappedStatement mappedStatement, BoundSql boundSql, Pagination page) {
-		PreparedStatement statement = null;
-		ResultSet resultSet = null;
-		Connection connection = null;
-		try {
-			connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
-			statement = connection.prepareStatement(sql);
-			DefaultParameterHandler parameterHandler = new MybatisDefaultParameterHandler(mappedStatement,
-					boundSql.getParameterObject(), boundSql);
-			parameterHandler.setParameters(statement);
-			resultSet = statement.executeQuery();
-			int total = 0;
-			if (resultSet.next()) {
-				total = resultSet.getInt(1);
-			}
-			page.setTotal(total);
+            metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
+            metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
+            metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
+        }
+        return invocation.proceed();
+    }
+
+    /**
+     * 查询总记录条数
+     *
+     * @param sql
+     * @param mappedStatement
+     * @param boundSql
+     * @param page
+     */
+    protected void count(String sql, MappedStatement mappedStatement, BoundSql boundSql, Pagination page) {
+        PreparedStatement statement = null;
+        ResultSet resultSet = null;
+        Connection connection = null;
+        try {
+            connection = mappedStatement.getConfiguration().getEnvironment().getDataSource().getConnection();
+            statement = connection.prepareStatement(sql);
+            DefaultParameterHandler parameterHandler = new MybatisDefaultParameterHandler(mappedStatement,
+                    boundSql.getParameterObject(), boundSql);
+            parameterHandler.setParameters(statement);
+            resultSet = statement.executeQuery();
+            int total = 0;
+            if (resultSet.next()) {
+                total = resultSet.getInt(1);
+            }
+            page.setTotal(total);
 			/*
 			 * 溢出总页数,设置第一页
 			 */
-			if (overflowCurrent && (page.getCurrent() > page.getPages())) {
-				page = new Pagination(1, page.getSize());
-				page.setTotal(total);
-			}
-		} catch (Exception e) {
-			logger.error("Error: query page count total fail!", e);
-		} finally {
-			IOUtils.closeQuietly(statement);
-			IOUtils.closeQuietly(resultSet);
-			IOUtils.closeQuietly(connection);
-		}
-	}
-
-	public Object plugin(Object target) {
-		if (target instanceof StatementHandler) {
-			return Plugin.wrap(target, this);
-		}
-		return target;
-	}
-
-	public void setProperties(Properties prop) {
-		String dialectType = prop.getProperty("dialectType");
-		String dialectClazz = prop.getProperty("dialectClazz");
-		if (StringUtils.isNotEmpty(dialectType)) {
-			this.dialectType = dialectType;
-		}
-		if (StringUtils.isNotEmpty(dialectClazz)) {
-			this.dialectClazz = dialectClazz;
-		}
-	}
-
-	public void setDialectType(String dialectType) {
-		this.dialectType = dialectType;
-	}
-
-	public void setDialectClazz(String dialectClazz) {
-		this.dialectClazz = dialectClazz;
-	}
-
-	public void setOverflowCurrent(boolean overflowCurrent) {
-		this.overflowCurrent = overflowCurrent;
-	}
-
-	public void setOptimizeType(String optimizeType) {
-		this.optimizeType = optimizeType;
-	}
+            if (overflowCurrent && (page.getCurrent() > page.getPages())) {
+                page = new Pagination(1, page.getSize());
+                page.setTotal(total);
+            }
+        } catch (Exception e) {
+            logger.error("Error: query page count total fail!", e);
+        } finally {
+            IOUtils.closeQuietly(statement);
+            IOUtils.closeQuietly(resultSet);
+            IOUtils.closeQuietly(connection);
+        }
+    }
+
+    public Object plugin(Object target) {
+        if (target instanceof StatementHandler) {
+            return Plugin.wrap(target, this);
+        }
+        return target;
+    }
+
+    public void setProperties(Properties prop) {
+        String dialectType = prop.getProperty("dialectType");
+        String dialectClazz = prop.getProperty("dialectClazz");
+        if (StringUtils.isNotEmpty(dialectType)) {
+            this.dialectType = dialectType;
+        }
+        if (StringUtils.isNotEmpty(dialectClazz)) {
+            this.dialectClazz = dialectClazz;
+        }
+    }
+
+    public void setDialectType(String dialectType) {
+        this.dialectType = dialectType;
+    }
+
+    public void setDialectClazz(String dialectClazz) {
+        this.dialectClazz = dialectClazz;
+    }
+
+    public void setOverflowCurrent(boolean overflowCurrent) {
+        this.overflowCurrent = overflowCurrent;
+    }
+
+    public void setOptimizeType(String optimizeType) {
+        this.optimizeType = optimizeType;
+    }
 
 }

+ 74 - 74
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/PerformanceInterceptor.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
@@ -40,88 +40,88 @@ import com.baomidou.mybatisplus.toolkit.SystemClock;
  * <p>
  * 性能分析拦截器,用于输出每条 SQL 语句及其执行时间
  * </p>
- * 
+ *
  * @author hubin nieqiurong TaoYu
  * @Date 2016-07-07
  */
-@Intercepts({ @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class }),
-		@Signature(type = StatementHandler.class, method = "update", args = { Statement.class }),
-		@Signature(type = StatementHandler.class, method = "batch", args = { Statement.class }) })
+@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
+        @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
+        @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})})
 public class PerformanceInterceptor implements Interceptor {
 
-	/**
-	 * SQL 执行最大时长,超过自动停止运行,有助于发现问题。
-	 */
-	private long maxTime = 0;
+    /**
+     * SQL 执行最大时长,超过自动停止运行,有助于发现问题。
+     */
+    private long maxTime = 0;
 
-	private boolean format = false;
+    private boolean format = false;
 
-	public Object intercept(Invocation invocation) throws Throwable {
-		Statement statement;
-		Object firstArg = invocation.getArgs()[0];
-		if (Proxy.isProxyClass(firstArg.getClass())) {
-			statement = (Statement) SystemMetaObject.forObject(firstArg).getValue("h.statement");
-		} else {
-			statement = (Statement) firstArg;
-		}
-		try {
-			statement.getClass().getDeclaredField("stmt");
-			statement = (Statement) SystemMetaObject.forObject(statement).getValue("stmt.statement");
-		} catch (Exception e) {
-			// do nothing
-		}
-		String originalSql = statement.toString();
-		int index = originalSql.indexOf(':');
-		String sql = originalSql;
-		if (index > 0) {
-			sql = originalSql.substring(index + 1, originalSql.length());
-		}
-		long start = SystemClock.now();
-		Object result = invocation.proceed();
-		long end = SystemClock.now();
-		long timing = end - start;
-		String formatSql = SqlUtils.sqlFormat(sql, format);
-		Object target = PluginUtils.realTarget(invocation.getTarget());
-		MetaObject metaObject = SystemMetaObject.forObject(target);
-		MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
-		System.err.println(" Time:" + timing + " ms" + " - ID:" + ms.getId() + "\n Execute SQL:" + formatSql + "\n");
-		if (maxTime >= 1 && timing > maxTime) {
-			throw new MybatisPlusException(" The SQL execution time is too large, please optimize ! ");
-		}
-		return result;
-	}
+    public Object intercept(Invocation invocation) throws Throwable {
+        Statement statement;
+        Object firstArg = invocation.getArgs()[0];
+        if (Proxy.isProxyClass(firstArg.getClass())) {
+            statement = (Statement) SystemMetaObject.forObject(firstArg).getValue("h.statement");
+        } else {
+            statement = (Statement) firstArg;
+        }
+        try {
+            statement.getClass().getDeclaredField("stmt");
+            statement = (Statement) SystemMetaObject.forObject(statement).getValue("stmt.statement");
+        } catch (Exception e) {
+            // do nothing
+        }
+        String originalSql = statement.toString();
+        int index = originalSql.indexOf(':');
+        String sql = originalSql;
+        if (index > 0) {
+            sql = originalSql.substring(index + 1, originalSql.length());
+        }
+        long start = SystemClock.now();
+        Object result = invocation.proceed();
+        long end = SystemClock.now();
+        long timing = end - start;
+        String formatSql = SqlUtils.sqlFormat(sql, format);
+        Object target = PluginUtils.realTarget(invocation.getTarget());
+        MetaObject metaObject = SystemMetaObject.forObject(target);
+        MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
+        System.err.println(" Time:" + timing + " ms" + " - ID:" + ms.getId() + "\n Execute SQL:" + formatSql + "\n");
+        if (maxTime >= 1 && timing > maxTime) {
+            throw new MybatisPlusException(" The SQL execution time is too large, please optimize ! ");
+        }
+        return result;
+    }
 
-	public Object plugin(Object target) {
-		if (target instanceof StatementHandler) {
-			return Plugin.wrap(target, this);
-		}
-		return target;
-	}
+    public Object plugin(Object target) {
+        if (target instanceof StatementHandler) {
+            return Plugin.wrap(target, this);
+        }
+        return target;
+    }
 
-	public void setProperties(Properties prop) {
-		String maxTime = prop.getProperty("maxTime");
-		String format = prop.getProperty("format");
-		if (StringUtils.isNotEmpty(maxTime)) {
-			this.maxTime = Long.parseLong(maxTime);
-		}
-		if (StringUtils.isNotEmpty(format)) {
-			this.format = Boolean.valueOf(format);
-		}
-	}
+    public void setProperties(Properties prop) {
+        String maxTime = prop.getProperty("maxTime");
+        String format = prop.getProperty("format");
+        if (StringUtils.isNotEmpty(maxTime)) {
+            this.maxTime = Long.parseLong(maxTime);
+        }
+        if (StringUtils.isNotEmpty(format)) {
+            this.format = Boolean.valueOf(format);
+        }
+    }
 
-	public long getMaxTime() {
-		return maxTime;
-	}
+    public long getMaxTime() {
+        return maxTime;
+    }
 
-	public void setMaxTime(long maxTime) {
-		this.maxTime = maxTime;
-	}
+    public void setMaxTime(long maxTime) {
+        this.maxTime = maxTime;
+    }
 
-	public boolean isFormat() {
-		return format;
-	}
+    public boolean isFormat() {
+        return format;
+    }
 
-	public void setFormat(boolean format) {
-		this.format = format;
-	}
+    public void setFormat(boolean format) {
+        this.format = format;
+    }
 }

+ 117 - 117
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/SqlExplainInterceptor.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,12 +15,11 @@
  */
 package com.baomidou.mybatisplus.plugins;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-import com.baomidou.mybatisplus.enums.DBType;
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
-import com.baomidou.mybatisplus.toolkit.IOUtils;
-import com.baomidou.mybatisplus.toolkit.StringUtils;
-import com.baomidou.mybatisplus.toolkit.VersionUtils;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.Properties;
+
 import org.apache.ibatis.builder.StaticSqlSource;
 import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.logging.Log;
@@ -36,130 +35,131 @@ import org.apache.ibatis.plugin.Signature;
 import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
 import org.apache.ibatis.session.Configuration;
 
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.Properties;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.enums.DBType;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.toolkit.IOUtils;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
+import com.baomidou.mybatisplus.toolkit.VersionUtils;
 
 /**
  * <p>
  * SQL 执行分析拦截器【 目前只支持 MYSQL-5.6.3 以上版本 】
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-08-16
  */
-@Intercepts({ @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }) })
+@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
 public class SqlExplainInterceptor implements Interceptor {
 
-	private static final Log logger = LogFactory.getLog(SqlExplainInterceptor.class);
-
-	/**
-	 * 发现执行全表 delete update 语句是否停止执行
-	 */
-	private boolean stopProceed = false;
-	/**
-	 * Mysql支持分析SQL的最小版本
-	 */
-	private final String minMySQLVersion = "5.6.3";
+    private static final Log logger = LogFactory.getLog(SqlExplainInterceptor.class);
+    /**
+     * Mysql支持分析SQL的最小版本
+     */
+    private final String minMySQLVersion = "5.6.3";
+    /**
+     * 发现执行全表 delete update 语句是否停止执行
+     */
+    private boolean stopProceed = false;
 
-	public Object intercept(Invocation invocation) throws Throwable {
-		/**
-		 * 处理 DELETE UPDATE 语句
-		 */
-		MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
-		if (ms.getSqlCommandType() == SqlCommandType.DELETE || ms.getSqlCommandType() == SqlCommandType.UPDATE) {
-			Configuration configuration = ms.getConfiguration();
-			Object parameter = invocation.getArgs()[1];
-			BoundSql boundSql = ms.getBoundSql(parameter);
-			Connection connection = configuration.getEnvironment().getDataSource().getConnection();
-			String databaseVersion = connection.getMetaData().getDatabaseProductVersion();
-			if (GlobalConfiguration.getDbType(configuration).equals(DBType.MYSQL)
-					&& VersionUtils.compare(minMySQLVersion, databaseVersion)) {
-				logger.warn("Warn: Your mysql version needs to be greater than '5.6.3' to execute of Sql Explain!");
-				IOUtils.closeQuietly(connection);
-				return invocation.proceed();
-			}
-			/**
-			 * 执行 SQL 分析
-			 */
-			sqlExplain(configuration, ms, boundSql, connection, parameter);
-		}
-		return invocation.proceed();
-	}
+    public Object intercept(Invocation invocation) throws Throwable {
+        /**
+         * 处理 DELETE UPDATE 语句
+         */
+        MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
+        if (ms.getSqlCommandType() == SqlCommandType.DELETE || ms.getSqlCommandType() == SqlCommandType.UPDATE) {
+            Configuration configuration = ms.getConfiguration();
+            Object parameter = invocation.getArgs()[1];
+            BoundSql boundSql = ms.getBoundSql(parameter);
+            Connection connection = configuration.getEnvironment().getDataSource().getConnection();
+            String databaseVersion = connection.getMetaData().getDatabaseProductVersion();
+            if (GlobalConfiguration.getDbType(configuration).equals(DBType.MYSQL)
+                    && VersionUtils.compare(minMySQLVersion, databaseVersion)) {
+                logger.warn("Warn: Your mysql version needs to be greater than '5.6.3' to execute of Sql Explain!");
+                IOUtils.closeQuietly(connection);
+                return invocation.proceed();
+            }
+            /**
+             * 执行 SQL 分析
+             */
+            sqlExplain(configuration, ms, boundSql, connection, parameter);
+        }
+        return invocation.proceed();
+    }
 
-	/**
-	 * <p>
-	 * 判断是否执行 SQL
-	 * </p>
-	 * 
-	 * @param configuration
-	 * @param mappedStatement
-	 * @param boundSql
-	 * @param connection
-	 * @param parameter
-	 * @return
-	 * @throws Exception
-	 */
-	@SuppressWarnings("resource")
-	protected void sqlExplain(Configuration configuration, MappedStatement mappedStatement, BoundSql boundSql,
-			Connection connection, Object parameter) {
-		PreparedStatement stmt = null;
-		ResultSet rs = null;
-		try {
-			StringBuilder explain = new StringBuilder("EXPLAIN ");
-			explain.append(boundSql.getSql());
-			String sqlExplain = explain.toString();
-			StaticSqlSource sqlsource = new StaticSqlSource(configuration, sqlExplain, boundSql.getParameterMappings());
-			MappedStatement.Builder builder = new MappedStatement.Builder(configuration, "explain_sql", sqlsource,
-					SqlCommandType.SELECT);
-			builder.resultMaps(mappedStatement.getResultMaps()).resultSetType(mappedStatement.getResultSetType())
-					.statementType(mappedStatement.getStatementType());
-			MappedStatement query_statement = builder.build();
-			DefaultParameterHandler handler = new DefaultParameterHandler(query_statement, parameter, boundSql);
-			stmt = connection.prepareStatement(sqlExplain);
-			handler.setParameters(stmt);
-			rs = stmt.executeQuery();
-			while (rs.next()) {
-				if (!"Using where".equals(rs.getString("Extra"))) {
-					String tip = " Full table operation is prohibited. SQL: " + boundSql.getSql();
-					if (this.isStopProceed()) {
-						throw new MybatisPlusException(tip);
-					}
-					logger.error(tip);
-					break;
-				}
-			}
+    /**
+     * <p>
+     * 判断是否执行 SQL
+     * </p>
+     *
+     * @param configuration
+     * @param mappedStatement
+     * @param boundSql
+     * @param connection
+     * @param parameter
+     * @return
+     * @throws Exception
+     */
+    @SuppressWarnings("resource")
+    protected void sqlExplain(Configuration configuration, MappedStatement mappedStatement, BoundSql boundSql,
+                              Connection connection, Object parameter) {
+        PreparedStatement stmt = null;
+        ResultSet rs = null;
+        try {
+            StringBuilder explain = new StringBuilder("EXPLAIN ");
+            explain.append(boundSql.getSql());
+            String sqlExplain = explain.toString();
+            StaticSqlSource sqlsource = new StaticSqlSource(configuration, sqlExplain, boundSql.getParameterMappings());
+            MappedStatement.Builder builder = new MappedStatement.Builder(configuration, "explain_sql", sqlsource,
+                    SqlCommandType.SELECT);
+            builder.resultMaps(mappedStatement.getResultMaps()).resultSetType(mappedStatement.getResultSetType())
+                    .statementType(mappedStatement.getStatementType());
+            MappedStatement query_statement = builder.build();
+            DefaultParameterHandler handler = new DefaultParameterHandler(query_statement, parameter, boundSql);
+            stmt = connection.prepareStatement(sqlExplain);
+            handler.setParameters(stmt);
+            rs = stmt.executeQuery();
+            while (rs.next()) {
+                if (!"Using where".equals(rs.getString("Extra"))) {
+                    String tip = " Full table operation is prohibited. SQL: " + boundSql.getSql();
+                    if (this.isStopProceed()) {
+                        throw new MybatisPlusException(tip);
+                    }
+                    logger.error(tip);
+                    break;
+                }
+            }
 
-		} catch (Exception e) {
-			throw new MybatisPlusException(e);
-		} finally {
-			IOUtils.closeQuietly(rs);
-			IOUtils.closeQuietly(stmt);
-			IOUtils.closeQuietly(connection);
-		}
-	}
+        } catch (Exception e) {
+            throw new MybatisPlusException(e);
+        } finally {
+            IOUtils.closeQuietly(rs);
+            IOUtils.closeQuietly(stmt);
+            IOUtils.closeQuietly(connection);
+        }
+    }
 
-	public Object plugin(Object target) {
-		if (target instanceof Executor) {
-			return Plugin.wrap(target, this);
-		}
-		return target;
-	}
+    public Object plugin(Object target) {
+        if (target instanceof Executor) {
+            return Plugin.wrap(target, this);
+        }
+        return target;
+    }
 
-	public void setProperties(Properties prop) {
-		String stopProceed = prop.getProperty("stopProceed");
-		if (StringUtils.isNotEmpty(stopProceed)) {
-			this.stopProceed = Boolean.valueOf(stopProceed);
-		}
-	}
+    public void setProperties(Properties prop) {
+        String stopProceed = prop.getProperty("stopProceed");
+        if (StringUtils.isNotEmpty(stopProceed)) {
+            this.stopProceed = Boolean.valueOf(stopProceed);
+        }
+    }
 
-	public boolean isStopProceed() {
-		return stopProceed;
-	}
+    public boolean isStopProceed() {
+        return stopProceed;
+    }
 
-	public void setStopProceed(boolean stopProceed) {
-		this.stopProceed = stopProceed;
-	}
+    public void setStopProceed(boolean stopProceed) {
+        this.stopProceed = stopProceed;
+    }
 
 }

+ 4 - 4
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/VersionHandler.java

@@ -9,8 +9,8 @@ import java.lang.reflect.Field;
  */
 public interface VersionHandler<T> {
 
-	/**
-	 * 根据类型,使得对象对应的字段+1
-	 */
-	void plusVersion(Object paramObj, Field field, T versionValue) throws Exception;
+    /**
+     * 根据类型,使得对象对应的字段+1
+     */
+    void plusVersion(Object paramObj, Field field, T versionValue) throws Exception;
 }

+ 124 - 123
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/DialectFactory.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
@@ -15,6 +15,10 @@
  */
 package com.baomidou.mybatisplus.plugins.pagination;
 
+import static com.baomidou.mybatisplus.enums.DBType.getDBType;
+
+import org.apache.ibatis.session.RowBounds;
+
 import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.plugins.pagination.dialects.DB2Dialect;
 import com.baomidou.mybatisplus.plugins.pagination.dialects.H2Dialect;
@@ -26,138 +30,135 @@ import com.baomidou.mybatisplus.plugins.pagination.dialects.SQLServer2005Dialect
 import com.baomidou.mybatisplus.plugins.pagination.dialects.SQLServerDialect;
 import com.baomidou.mybatisplus.plugins.pagination.dialects.SQLiteDialect;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
-import org.apache.ibatis.session.RowBounds;
-
-import static com.baomidou.mybatisplus.enums.DBType.getDBType;
 
 /**
  * <p>
  * 分页方言工厂类
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class DialectFactory {
 
-	/**
-	 * <p>
-	 * 生成翻页执行 SQL
-	 * </p>
-	 * 
-	 * @param page
-	 *            翻页对象
-	 * @param buildSql
-	 *            执行 SQL
-	 * @param dialectType
-	 *            方言类型
-	 * @param dialectClazz
-	 *            自定义方言实现类
-	 * @return
-	 * @throws Exception
-	 */
-	public static String buildPaginationSql(Pagination page, String buildSql, String dialectType, String dialectClazz)
-			throws Exception {
-		// fix #172, 196
-		return getiDialect(dialectType, dialectClazz).buildPaginationSql(buildSql, page.getOffsetCurrent(), page.getSize());
-	}
+    /**
+     * <p>
+     * 生成翻页执行 SQL
+     * </p>
+     *
+     * @param page
+     *            翻页对象
+     * @param buildSql
+     *            执行 SQL
+     * @param dialectType
+     *            方言类型
+     * @param dialectClazz
+     *            自定义方言实现类
+     * @return
+     * @throws Exception
+     */
+    public static String buildPaginationSql(Pagination page, String buildSql, String dialectType, String dialectClazz)
+            throws Exception {
+        // fix #172, 196
+        return getiDialect(dialectType, dialectClazz).buildPaginationSql(buildSql, page.getOffsetCurrent(), page.getSize());
+    }
 
-	/**
-	 * Physical Pagination Interceptor for all the queries with parameter
-	 * {@link org.apache.ibatis.session.RowBounds}
-	 * 
-	 * @param rowBounds
-	 * @param buildSql
-	 * @param dialectType
-	 * @param dialectClazz
-	 * @return
-	 * @throws Exception
-	 */
-	public static String buildPaginationSql(RowBounds rowBounds, String buildSql, String dialectType, String dialectClazz)
-			throws Exception {
-		// fix #196
-		return getiDialect(dialectType, dialectClazz).buildPaginationSql(buildSql, rowBounds.getOffset(), rowBounds.getLimit());
-	}
+    /**
+     * Physical Pagination Interceptor for all the queries with parameter
+     * {@link org.apache.ibatis.session.RowBounds}
+     *
+     * @param rowBounds
+     * @param buildSql
+     * @param dialectType
+     * @param dialectClazz
+     * @return
+     * @throws Exception
+     */
+    public static String buildPaginationSql(RowBounds rowBounds, String buildSql, String dialectType, String dialectClazz)
+            throws Exception {
+        // fix #196
+        return getiDialect(dialectType, dialectClazz).buildPaginationSql(buildSql, rowBounds.getOffset(), rowBounds.getLimit());
+    }
 
-	/**
-	 * <p>
-	 * 获取数据库方言
-	 * </p>
-	 * 
-	 * @param dialectType
-	 *            方言类型
-	 * @param dialectClazz
-	 *            自定义方言实现类
-	 * @return
-	 * @throws Exception
-	 */
-	private static IDialect getiDialect(String dialectType, String dialectClazz) throws Exception {
-		IDialect dialect = null;
-		if (StringUtils.isNotEmpty(dialectType)) {
-			dialect = getDialectByDbtype(dialectType);
-		} else {
-			if (StringUtils.isNotEmpty(dialectClazz)) {
-				try {
-					Class<?> clazz = Class.forName(dialectClazz);
-					if (IDialect.class.isAssignableFrom(clazz)) {
-						dialect = (IDialect) clazz.newInstance();
-					}
-				} catch (ClassNotFoundException e) {
-					throw new MybatisPlusException("Class :" + dialectClazz + " is not found");
-				}
-			}
-		}
-		/* 未配置方言则抛出异常 */
-		if (dialect == null) {
-			throw new MybatisPlusException("The value of the dialect property in mybatis configuration.xml is not defined.");
-		}
-		return dialect;
-	}
+    /**
+     * <p>
+     * 获取数据库方言
+     * </p>
+     *
+     * @param dialectType
+     *            方言类型
+     * @param dialectClazz
+     *            自定义方言实现类
+     * @return
+     * @throws Exception
+     */
+    private static IDialect getiDialect(String dialectType, String dialectClazz) throws Exception {
+        IDialect dialect = null;
+        if (StringUtils.isNotEmpty(dialectType)) {
+            dialect = getDialectByDbtype(dialectType);
+        } else {
+            if (StringUtils.isNotEmpty(dialectClazz)) {
+                try {
+                    Class<?> clazz = Class.forName(dialectClazz);
+                    if (IDialect.class.isAssignableFrom(clazz)) {
+                        dialect = (IDialect) clazz.newInstance();
+                    }
+                } catch (ClassNotFoundException e) {
+                    throw new MybatisPlusException("Class :" + dialectClazz + " is not found");
+                }
+            }
+        }
+        /* 未配置方言则抛出异常 */
+        if (dialect == null) {
+            throw new MybatisPlusException("The value of the dialect property in mybatis configuration.xml is not defined.");
+        }
+        return dialect;
+    }
 
-	/**
-	 * <p>
-	 * 根据数据库类型选择不同分页方言
-	 * </p>
-	 * 
-	 * @param dbType
-	 *            数据库类型
-	 * @return
-	 * @throws Exception
-	 */
-	private static IDialect getDialectByDbtype(String dbType) {
-		IDialect dialect;
-		switch (getDBType(dbType)) {
-		case MYSQL:
-			dialect = MySqlDialect.INSTANCE;
-			break;
-		case ORACLE:
-			dialect = OracleDialect.INSTANCE;
-			break;
-		case DB2:
-			dialect = DB2Dialect.INSTANCE;
-			break;
-		case H2:
-			dialect = H2Dialect.INSTANCE;
-			break;
-		case SQLSERVER:
-			dialect = SQLServerDialect.INSTANCE;
-			break;
-		case SQLSERVER2005:
-			dialect = SQLServer2005Dialect.INSTANCE;
-			break;
-		case POSTGRE:
-			dialect = PostgreDialect.INSTANCE;
-			break;
-		case HSQL:
-			dialect = HSQLDialect.INSTANCE;
-			break;
-		case SQLITE:
-			dialect = SQLiteDialect.INSTANCE;
-			break;
-		default:
-			throw new MybatisPlusException("The Database's Not Supported! DBType:" + dbType);
-		}
-		return dialect;
-	}
+    /**
+     * <p>
+     * 根据数据库类型选择不同分页方言
+     * </p>
+     *
+     * @param dbType
+     *            数据库类型
+     * @return
+     * @throws Exception
+     */
+    private static IDialect getDialectByDbtype(String dbType) {
+        IDialect dialect;
+        switch (getDBType(dbType)) {
+            case MYSQL:
+                dialect = MySqlDialect.INSTANCE;
+                break;
+            case ORACLE:
+                dialect = OracleDialect.INSTANCE;
+                break;
+            case DB2:
+                dialect = DB2Dialect.INSTANCE;
+                break;
+            case H2:
+                dialect = H2Dialect.INSTANCE;
+                break;
+            case SQLSERVER:
+                dialect = SQLServerDialect.INSTANCE;
+                break;
+            case SQLSERVER2005:
+                dialect = SQLServer2005Dialect.INSTANCE;
+                break;
+            case POSTGRE:
+                dialect = PostgreDialect.INSTANCE;
+                break;
+            case HSQL:
+                dialect = HSQLDialect.INSTANCE;
+                break;
+            case SQLITE:
+                dialect = SQLiteDialect.INSTANCE;
+                break;
+            default:
+                throw new MybatisPlusException("The Database's Not Supported! DBType:" + dbType);
+        }
+        return dialect;
+    }
 
 }

+ 16 - 16
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/IDialect.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
@@ -19,22 +19,22 @@ package com.baomidou.mybatisplus.plugins.pagination;
  * <p>
  * 数据库 分页语句组装接口
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public interface IDialect {
 
-	/**
-	 * 组装分页语句
-	 * 
-	 * @param originalSql
-	 *            原始语句
-	 * @param offset
-	 *            偏移量
-	 * @param limit
-	 *            界限
-	 * @return 分页语句
-	 */
-	public String buildPaginationSql(String originalSql, int offset, int limit);
+    /**
+     * 组装分页语句
+     *
+     * @param originalSql
+     *            原始语句
+     * @param offset
+     *            偏移量
+     * @param limit
+     *            界限
+     * @return 分页语句
+     */
+    String buildPaginationSql(String originalSql, int offset, int limit);
 }

+ 187 - 186
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/Pagination.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
@@ -15,10 +15,11 @@
  */
 package com.baomidou.mybatisplus.plugins.pagination;
 
-import com.baomidou.mybatisplus.toolkit.StringUtils;
+import java.io.Serializable;
+
 import org.apache.ibatis.session.RowBounds;
 
-import java.io.Serializable;
+import com.baomidou.mybatisplus.toolkit.StringUtils;
 
 /**
  * <p>
@@ -26,191 +27,191 @@ import java.io.Serializable;
  * </p>
  * 用户可以通过继承 org.apache.ibatis.session.RowBounds实现自己的分页模型<br>
  * 注意:插件仅支持RowBounds及其子类作为分页参数
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class Pagination extends RowBounds implements Serializable {
 
-	private static final long serialVersionUID = 1L;
-
-	/* 总数 */
-	private int total;
-
-	/* 每页显示条数,默认 10 */
-	private int size = 10;
-
-	/* 总页数 */
-	private int pages;
-
-	/* 当前页 */
-	private int current = 1;
-
-	/* 查询总记录数(默认 true) */
-	private boolean searchCount = true;
-
-	/**
-	 * 开启排序(默认 true) 只在代码逻辑判断 并不截取sql分析
-	 * 
-	 * @see com.baomidou.mybatisplus.mapper.SqlHelper fillWrapper
-	 **/
-	private boolean openSort = true;
-
-	/**
-	 * 查询总数优化(默认 false 该属性只针对于Optimize.DEFAULT有效)
-	 * 
-	 * @see com.baomidou.mybatisplus.enums.Optimize
-	 *
-	 */
-	private boolean optimizeCount = false;
-
-	/**
-	 * <p>
-	 * SQL 排序 ORDER BY 字段,例如: id DESC(根据id倒序查询)
-	 * </p>
-	 * <p>
-	 * DESC 表示按倒序排序(即:从大到小排序)<br>
-	 * ASC 表示按正序排序(即:从小到大排序)
-	 * </p>
-	 */
-	private String orderByField;
-
-	/**
-	 * 是否为升序 ASC( 默认: true )
-	 */
-	private boolean isAsc = true;
-
-	public Pagination() {
-		super();
-	}
-
-	/**
-	 * <p>
-	 * 分页构造函数
-	 * </p>
-	 * 
-	 * @param current
-	 *            当前页
-	 * @param size
-	 *            每页显示条数
-	 */
-	public Pagination(int current, int size) {
-		this(current, size, true);
-	}
-
-	public Pagination(int current, int size, boolean searchCount) {
-		this(current, size, searchCount, true);
-	}
-
-	public Pagination(int current, int size, boolean searchCount, boolean openSort) {
-		super(offsetCurrent(current, size), size);
-		if (current > 1) {
-			this.current = current;
-		}
-		this.size = size;
-		this.searchCount = searchCount;
-		this.openSort = openSort;
-	}
-
-	protected static int offsetCurrent(int current, int size) {
-		if (current > 0) {
-			return (current - 1) * size;
-		}
-		return 0;
-	}
-
-	public int getOffsetCurrent() {
-		return offsetCurrent(this.current, this.size);
-	}
-
-	public boolean hasPrevious() {
-		return this.current > 1;
-	}
-
-	public boolean hasNext() {
-		return this.current < this.pages;
-	}
-
-	public int getTotal() {
-		return total;
-	}
-
-	public void setTotal(int total) {
-		this.total = total;
-	}
-
-	public int getSize() {
-		return size;
-	}
-
-	public void setSize(int size) {
-		this.size = size;
-	}
-
-	public int getPages() {
-		if (this.size == 0) {
-			return 0;
-		}
-		this.pages = this.total / this.size;
-		if (this.total % this.size != 0) {
-			this.pages++;
-		}
-		return this.pages;
-	}
-
-	public void setCurrent(int current) {
-		this.current = current;
-	}
-
-	public int getCurrent() {
-		return current;
-	}
-
-	public boolean isSearchCount() {
-		return searchCount;
-	}
-
-	public void setSearchCount(boolean searchCount) {
-		this.searchCount = searchCount;
-	}
-
-	public boolean isOptimizeCount() {
-		return optimizeCount;
-	}
-
-	public void setOptimizeCount(boolean optimizeCount) {
-		this.optimizeCount = optimizeCount;
-	}
-
-	public String getOrderByField() {
-		return orderByField;
-	}
-
-	public void setOrderByField(String orderByField) {
-		if (StringUtils.isNotEmpty(orderByField)) {
-			this.orderByField = orderByField;
-		}
-	}
-
-	public boolean isOpenSort() {
-		return openSort;
-	}
-
-	public void setOpenSort(boolean openSort) {
-		this.openSort = openSort;
-	}
-
-	public boolean isAsc() {
-		return isAsc;
-	}
-
-	public void setAsc(boolean isAsc) {
-		this.isAsc = isAsc;
-	}
-
-	@Override
-	public String toString() {
-		return "Pagination { total=" + total + " ,size=" + size + " ,pages=" + pages + " ,current=" + current + " }";
-	}
+    private static final long serialVersionUID = 1L;
+
+    /* 总数 */
+    private int total;
+
+    /* 每页显示条数,默认 10 */
+    private int size = 10;
+
+    /* 总页数 */
+    private int pages;
+
+    /* 当前页 */
+    private int current = 1;
+
+    /* 查询总记录数(默认 true) */
+    private boolean searchCount = true;
+
+    /**
+     * 开启排序(默认 true) 只在代码逻辑判断 并不截取sql分析
+     *
+     * @see com.baomidou.mybatisplus.mapper.SqlHelper fillWrapper
+     **/
+    private boolean openSort = true;
+
+    /**
+     * 查询总数优化(默认 false 该属性只针对于Optimize.DEFAULT有效)
+     *
+     * @see com.baomidou.mybatisplus.enums.Optimize
+     *
+     */
+    private boolean optimizeCount = false;
+
+    /**
+     * <p>
+     * SQL 排序 ORDER BY 字段,例如: id DESC(根据id倒序查询)
+     * </p>
+     * <p>
+     * DESC 表示按倒序排序(即:从大到小排序)<br>
+     * ASC 表示按正序排序(即:从小到大排序)
+     * </p>
+     */
+    private String orderByField;
+
+    /**
+     * 是否为升序 ASC( 默认: true )
+     */
+    private boolean isAsc = true;
+
+    public Pagination() {
+        super();
+    }
+
+    /**
+     * <p>
+     * 分页构造函数
+     * </p>
+     *
+     * @param current
+     *            当前页
+     * @param size
+     *            每页显示条数
+     */
+    public Pagination(int current, int size) {
+        this(current, size, true);
+    }
+
+    public Pagination(int current, int size, boolean searchCount) {
+        this(current, size, searchCount, true);
+    }
+
+    public Pagination(int current, int size, boolean searchCount, boolean openSort) {
+        super(offsetCurrent(current, size), size);
+        if (current > 1) {
+            this.current = current;
+        }
+        this.size = size;
+        this.searchCount = searchCount;
+        this.openSort = openSort;
+    }
+
+    protected static int offsetCurrent(int current, int size) {
+        if (current > 0) {
+            return (current - 1) * size;
+        }
+        return 0;
+    }
+
+    public int getOffsetCurrent() {
+        return offsetCurrent(this.current, this.size);
+    }
+
+    public boolean hasPrevious() {
+        return this.current > 1;
+    }
+
+    public boolean hasNext() {
+        return this.current < this.pages;
+    }
+
+    public int getTotal() {
+        return total;
+    }
+
+    public void setTotal(int total) {
+        this.total = total;
+    }
+
+    public int getSize() {
+        return size;
+    }
+
+    public void setSize(int size) {
+        this.size = size;
+    }
+
+    public int getPages() {
+        if (this.size == 0) {
+            return 0;
+        }
+        this.pages = this.total / this.size;
+        if (this.total % this.size != 0) {
+            this.pages++;
+        }
+        return this.pages;
+    }
+
+    public int getCurrent() {
+        return current;
+    }
+
+    public void setCurrent(int current) {
+        this.current = current;
+    }
+
+    public boolean isSearchCount() {
+        return searchCount;
+    }
+
+    public void setSearchCount(boolean searchCount) {
+        this.searchCount = searchCount;
+    }
+
+    public boolean isOptimizeCount() {
+        return optimizeCount;
+    }
+
+    public void setOptimizeCount(boolean optimizeCount) {
+        this.optimizeCount = optimizeCount;
+    }
+
+    public String getOrderByField() {
+        return orderByField;
+    }
+
+    public void setOrderByField(String orderByField) {
+        if (StringUtils.isNotEmpty(orderByField)) {
+            this.orderByField = orderByField;
+        }
+    }
+
+    public boolean isOpenSort() {
+        return openSort;
+    }
+
+    public void setOpenSort(boolean openSort) {
+        this.openSort = openSort;
+    }
+
+    public boolean isAsc() {
+        return isAsc;
+    }
+
+    public void setAsc(boolean isAsc) {
+        this.isAsc = isAsc;
+    }
+
+    @Override
+    public String toString() {
+        return "Pagination { total=" + total + " ,size=" + size + " ,pages=" + pages + " ,current=" + current + " }";
+    }
 
 }

+ 48 - 34
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/DB2Dialect.java

@@ -1,5 +1,19 @@
 /**
  * Copyright &copy; 2015-2015  Jeedcp All rights reserved.
+ * <p>
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
  */
 /**
  * Copyright (c) 2011-2014, hubin (jobob@qq.com).
@@ -24,47 +38,47 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * DB2 数据库分页方言
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-11-10
  */
 public class DB2Dialect implements IDialect {
 
-	public static final DB2Dialect INSTANCE = new DB2Dialect();
+    public static final DB2Dialect INSTANCE = new DB2Dialect();
 
-	private static String getRowNumber(String originalSql) {
-		StringBuilder rownumber = new StringBuilder(50).append("rownumber() over(");
-		int orderByIndex = originalSql.toLowerCase().indexOf("order by");
-		if (orderByIndex > 0 && !hasDistinct(originalSql)) {
-			rownumber.append(originalSql.substring(orderByIndex));
-		}
-		rownumber.append(") as rownumber_,");
-		return rownumber.toString();
-	}
+    private static String getRowNumber(String originalSql) {
+        StringBuilder rownumber = new StringBuilder(50).append("rownumber() over(");
+        int orderByIndex = originalSql.toLowerCase().indexOf("order by");
+        if (orderByIndex > 0 && !hasDistinct(originalSql)) {
+            rownumber.append(originalSql.substring(orderByIndex));
+        }
+        rownumber.append(") as rownumber_,");
+        return rownumber.toString();
+    }
 
-	private static boolean hasDistinct(String originalSql) {
-		return originalSql.toLowerCase().contains("select distinct");
-	}
+    private static boolean hasDistinct(String originalSql) {
+        return originalSql.toLowerCase().contains("select distinct");
+    }
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		int startOfSelect = originalSql.toLowerCase().indexOf("select");
-		StringBuilder pagingSelect = new StringBuilder(originalSql.length() + 100)
-				.append(originalSql.substring(0, startOfSelect)).append("select * from ( select ")
-				.append(getRowNumber(originalSql));
-		if (hasDistinct(originalSql)) {
-			pagingSelect.append(" row_.* from ( ").append(originalSql.substring(startOfSelect)).append(" ) as row_");
-		} else {
-			pagingSelect.append(originalSql.substring(startOfSelect + 6));
-		}
-		pagingSelect.append(" ) as temp_ where rownumber_ ");
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        int startOfSelect = originalSql.toLowerCase().indexOf("select");
+        StringBuilder pagingSelect = new StringBuilder(originalSql.length() + 100)
+                .append(originalSql.substring(0, startOfSelect)).append("select * from ( select ")
+                .append(getRowNumber(originalSql));
+        if (hasDistinct(originalSql)) {
+            pagingSelect.append(" row_.* from ( ").append(originalSql.substring(startOfSelect)).append(" ) as row_");
+        } else {
+            pagingSelect.append(originalSql.substring(startOfSelect + 6));
+        }
+        pagingSelect.append(" ) as temp_ where rownumber_ ");
 
-		// add the restriction to the outer select
-		if (offset > 0) {
-			String endString = offset + "+" + limit;
-			pagingSelect.append("between ").append(offset).append("+1 and ").append(endString);
-		} else {
-			pagingSelect.append("<= ").append(limit);
-		}
-		return null;
-	}
+        // add the restriction to the outer select
+        if (offset > 0) {
+            String endString = offset + "+" + limit;
+            pagingSelect.append("between ").append(offset).append("+1 and ").append(endString);
+        } else {
+            pagingSelect.append("<= ").append(limit);
+        }
+        return null;
+    }
 }

+ 14 - 14
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/H2Dialect.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
@@ -21,20 +21,20 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * H2 数据库分页方言
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-11-10
  */
 public class H2Dialect implements IDialect {
 
-	public static final H2Dialect INSTANCE = new H2Dialect();
+    public static final H2Dialect INSTANCE = new H2Dialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder(originalSql);
-		sql.append(" limit ").append(limit);
-		if (offset > 0) {
-			sql.append(" offset ").append(offset);
-		}
-		return sql.toString();
-	}
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder(originalSql);
+        sql.append(" limit ").append(limit);
+        if (offset > 0) {
+            sql.append(" offset ").append(offset);
+        }
+        return sql.toString();
+    }
+}

+ 10 - 10
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/HSQLDialect.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
@@ -21,17 +21,17 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * HSQL 数据库分页语句组装实现
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class HSQLDialect implements IDialect {
 
-	public static final HSQLDialect INSTANCE = new HSQLDialect();
+    public static final HSQLDialect INSTANCE = new HSQLDialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder(originalSql);
-		sql.append(" limit ").append(offset).append(",").append(limit);
-		return sql.toString();
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder(originalSql);
+        sql.append(" limit ").append(offset).append(",").append(limit);
+        return sql.toString();
+    }
 }

+ 10 - 10
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/MySqlDialect.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
@@ -21,17 +21,17 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * MYSQL 数据库分页语句组装实现
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class MySqlDialect implements IDialect {
 
-	public static final MySqlDialect INSTANCE = new MySqlDialect();
+    public static final MySqlDialect INSTANCE = new MySqlDialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder(originalSql);
-		sql.append(" LIMIT ").append(offset).append(",").append(limit);
-		return sql.toString();
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder(originalSql);
+        sql.append(" LIMIT ").append(offset).append(",").append(limit);
+        return sql.toString();
+    }
 }

+ 12 - 12
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/OracleDialect.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
@@ -21,19 +21,19 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * ORACLE 数据库分页语句组装实现
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class OracleDialect implements IDialect {
 
-	public static final OracleDialect INSTANCE = new OracleDialect();
+    public static final OracleDialect INSTANCE = new OracleDialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder();
-		sql.append("SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( ");
-		sql.append(originalSql).append(" ) TMP WHERE ROWNUM <=").append((offset >= 1) ? (offset + limit) : limit);
-		sql.append(") WHERE ROW_ID > ").append(offset);
-		return sql.toString();
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder();
+        sql.append("SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( ");
+        sql.append(originalSql).append(" ) TMP WHERE ROWNUM <=").append((offset >= 1) ? (offset + limit) : limit);
+        sql.append(") WHERE ROW_ID > ").append(offset);
+        return sql.toString();
+    }
 }

+ 10 - 10
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/PostgreDialect.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
@@ -21,17 +21,17 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * Postgre 数据库分页语句组装实现
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class PostgreDialect implements IDialect {
 
-	public static final PostgreDialect INSTANCE = new PostgreDialect();
+    public static final PostgreDialect INSTANCE = new PostgreDialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder(originalSql);
-		sql.append(" limit ").append(limit).append(" offset ").append(offset);
-		return sql.toString();
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder(originalSql);
+        sql.append(" limit ").append(limit).append(" offset ").append(offset);
+        return sql.toString();
+    }
 }

+ 40 - 40
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/SQLServer2005Dialect.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
@@ -22,51 +22,51 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * <p>
  * SQLServer 2005 数据库分页方言
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-11-10
  */
 public class SQLServer2005Dialect implements IDialect {
 
-	public static final SQLServer2005Dialect INSTANCE = new SQLServer2005Dialect();
+    public static final SQLServer2005Dialect INSTANCE = new SQLServer2005Dialect();
 
-	private static String getOrderByPart(String sql) {
-		String loweredString = sql.toLowerCase();
-		int orderByIndex = loweredString.indexOf("order by");
-		if (orderByIndex != -1) {
-			return sql.substring(orderByIndex);
-		} else {
-			return "";
-		}
-	}
+    private static String getOrderByPart(String sql) {
+        String loweredString = sql.toLowerCase();
+        int orderByIndex = loweredString.indexOf("order by");
+        if (orderByIndex != -1) {
+            return sql.substring(orderByIndex);
+        } else {
+            return "";
+        }
+    }
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder pagingBuilder = new StringBuilder();
-		String orderby = getOrderByPart(originalSql);
-		String distinctStr = "";
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder pagingBuilder = new StringBuilder();
+        String orderby = getOrderByPart(originalSql);
+        String distinctStr = "";
 
-		String loweredString = originalSql.toLowerCase();
-		String sqlPartString = originalSql;
-		if (loweredString.trim().startsWith("select")) {
-			int index = 6;
-			if (loweredString.startsWith("select distinct")) {
-				distinctStr = "DISTINCT ";
-				index = 15;
-			}
-			sqlPartString = sqlPartString.substring(index);
-		}
-		pagingBuilder.append(sqlPartString);
+        String loweredString = originalSql.toLowerCase();
+        String sqlPartString = originalSql;
+        if (loweredString.trim().startsWith("select")) {
+            int index = 6;
+            if (loweredString.startsWith("select distinct")) {
+                distinctStr = "DISTINCT ";
+                index = 15;
+            }
+            sqlPartString = sqlPartString.substring(index);
+        }
+        pagingBuilder.append(sqlPartString);
 
-		// if no ORDER BY is specified use fake ORDER BY field to avoid errors
-		if (StringUtils.isEmpty(orderby)) {
-			orderby = "ORDER BY CURRENT_TIMESTAMP";
-		}
+        // if no ORDER BY is specified use fake ORDER BY field to avoid errors
+        if (StringUtils.isEmpty(orderby)) {
+            orderby = "ORDER BY CURRENT_TIMESTAMP";
+        }
 
-		StringBuilder sql = new StringBuilder();
-		sql.append("WITH query AS (SELECT ").append(distinctStr).append("TOP 100 PERCENT ")
-				.append(" ROW_NUMBER() OVER (").append(orderby).append(") as __row_number__, ").append(pagingBuilder)
-				.append(") SELECT * FROM query WHERE __row_number__ BETWEEN ").append(offset).append(" AND ")
-				.append(offset + limit).append(" ORDER BY __row_number__");
-		return sql.toString();
-	}
+        StringBuilder sql = new StringBuilder();
+        sql.append("WITH query AS (SELECT ").append(distinctStr).append("TOP 100 PERCENT ")
+                .append(" ROW_NUMBER() OVER (").append(orderby).append(") as __row_number__, ").append(pagingBuilder)
+                .append(") SELECT * FROM query WHERE __row_number__ BETWEEN ").append(offset).append(" AND ")
+                .append(offset + limit).append(" ORDER BY __row_number__");
+        return sql.toString();
+    }
 }

+ 11 - 11
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/SQLServerDialect.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
@@ -21,18 +21,18 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * SQLServer 数据库分页语句组装实现
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-03-23
  */
 public class SQLServerDialect implements IDialect {
 
-	public static final SQLServerDialect INSTANCE = new SQLServerDialect();
+    public static final SQLServerDialect INSTANCE = new SQLServerDialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder(originalSql);
-		sql.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ");
-		sql.append(limit).append(" ROWS ONLY");
-		return sql.toString();
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder(originalSql);
+        sql.append(" OFFSET ").append(offset).append(" ROWS FETCH NEXT ");
+        sql.append(limit).append(" ROWS ONLY");
+        return sql.toString();
+    }
 }

+ 10 - 10
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/pagination/dialects/SQLiteDialect.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
@@ -21,17 +21,17 @@ import com.baomidou.mybatisplus.plugins.pagination.IDialect;
  * <p>
  * SQLite 数据库分页语句组装实现
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-01-23
  */
 public class SQLiteDialect implements IDialect {
 
-	public static final SQLiteDialect INSTANCE = new SQLiteDialect();
+    public static final SQLiteDialect INSTANCE = new SQLiteDialect();
 
-	public String buildPaginationSql(String originalSql, int offset, int limit) {
-		StringBuilder sql = new StringBuilder(originalSql);
-		sql.append(" limit ").append(limit).append(" offset ").append(offset);
-		return sql.toString();
-	}
+    public String buildPaginationSql(String originalSql, int offset, int limit) {
+        StringBuilder sql = new StringBuilder(originalSql);
+        sql.append(" limit ").append(limit).append(" offset ").append(offset);
+        return sql.toString();
+    }
 }

+ 334 - 334
mybatis-plus/src/main/java/com/baomidou/mybatisplus/service/IService.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2016, 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
@@ -32,336 +32,336 @@ import com.baomidou.mybatisplus.plugins.Page;
  */
 public interface IService<T> {
 
-	/**
-	 * <p>
-	 * 插入一条记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return boolean
-	 */
-	boolean insert(T entity);
-
-	/**
-	 * <p>
-	 * 插入一条记录(选择字段, null 字段不插入)
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return boolean
-	 */
-	boolean insertAllColumn(T entity);
-
-	/**
-	 * <p>
-	 * 插入(批量),该方法不适合 Oracle
-	 * </p>
-	 *
-	 * @param entityList
-	 *            实体对象列表
-	 * @return boolean
-	 */
-	boolean insertBatch(List<T> entityList);
-
-	/**
-	 * <p>
-	 * 插入(批量)
-	 * </p>
-	 *
-	 * @param entityList
-	 *            实体对象列表
-	 * @param batchSize
-	 *            插入批次数量
-	 * @return boolean
-	 */
-	boolean insertBatch(List<T> entityList, int batchSize);
-
-	/**
-	 * <p>
-	 * 批量修改插入
-	 * </p>
-	 *
-	 * @param entityList
-	 *            实体对象列表
-	 * @return boolean
-	 */
-	boolean insertOrUpdateBatch(List<T> entityList);
-
-	/**
-	 * <p>
-	 * 批量修改插入
-	 * </p>
-	 *
-	 * @param entityList
-	 *            实体对象列表
-	 * @param batchSize
-	 *
-	 * @return boolean
-	 */
-	boolean insertOrUpdateBatch(List<T> entityList, int batchSize);
-
-	/**
-	 * <p>
-	 * 根据 ID 删除
-	 * </p>
-	 *
-	 * @param id
-	 *            主键ID
-	 * @return boolean
-	 */
-	boolean deleteById(Serializable id);
-
-	/**
-	 * <p>
-	 * 根据 columnMap 条件,删除记录
-	 * </p>
-	 *
-	 * @param columnMap
-	 *            表字段 map 对象
-	 * @return boolean
-	 */
-	boolean deleteByMap(Map<String, Object> columnMap);
-
-	/**
-	 * <p>
-	 * 根据 entity 条件,删除记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体包装类 {@link Wrapper}
-	 * @return boolean
-	 */
-	boolean delete(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 删除(根据ID 批量删除)
-	 * </p>
-	 *
-	 * @param idList
-	 *            主键ID列表
-	 * @return boolean
-	 */
-	boolean deleteBatchIds(List<? extends Serializable> idList);
-
-	/**
-	 * <p>
-	 * 根据 ID 修改
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return boolean
-	 */
-	boolean updateById(T entity);
-
-	/**
-	 * <p>
-	 * 根据 ID 选择修改
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return boolean
-	 */
-	boolean updateAllColumnById(T entity);
-
-	/**
-	 * <p>
-	 * 根据 whereEntity 条件,更新记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @param wrapper
-	 *            实体包装类 {@link Wrapper}
-	 * @return boolean
-	 */
-	boolean update(T entity, Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据ID 批量更新
-	 * </p>
-	 *
-	 * @param entityList
-	 *            实体对象列表
-	 * @return boolean
-	 */
-	boolean updateBatchById(List<T> entityList);
-
-	/**
-	 * <p>
-	 * 根据ID 批量更新
-	 * </p>
-	 *
-	 * @param entityList
-	 *            实体对象列表
-	 * @param batchSize
-	 *            更新批次数量
-	 * @return boolean
-	 */
-	boolean updateBatchById(List<T> entityList, int batchSize);
-
-	/**
-	 * <p>
-	 * TableId 注解存在更新记录,否插入一条记录
-	 * </p>
-	 *
-	 * @param entity
-	 *            实体对象
-	 * @return boolean
-	 */
-	boolean insertOrUpdate(T entity);
-
-	/**
-	 * <p>
-	 * 根据 ID 查询
-	 * </p>
-	 *
-	 * @param id
-	 *            主键ID
-	 * @return T
-	 */
-	T selectById(Serializable id);
-
-	/**
-	 * <p>
-	 * 查询(根据ID 批量查询)
-	 * </p>
-	 *
-	 * @param idList
-	 *            主键ID列表
-	 * @return List<T>
-	 */
-	List<T> selectBatchIds(List<? extends Serializable> idList);
-
-	/**
-	 * <p>
-	 * 查询(根据 columnMap 条件)
-	 * </p>
-	 *
-	 * @param columnMap
-	 *            表字段 map 对象
-	 * @return List<T>
-	 */
-	List<T> selectByMap(Map<String, Object> columnMap);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper,查询一条记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象
-	 * @return T
-	 */
-	T selectOne(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper,查询一条记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            {@link Wrapper}
-	 * @return Map<String,Object>
-	 */
-	Map<String, Object> selectMap(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper,查询一条记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            {@link Wrapper}
-	 * @return Object
-	 */
-	Object selectObj(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper 条件,查询总记录数
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象
-	 * @return int
-	 */
-	int selectCount(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 查询列表
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体包装类 {@link Wrapper}
-	 * @return
-	 */
-	List<T> selectList(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 翻页查询
-	 * </p>
-	 *
-	 * @param page
-	 *            翻页对象
-	 * @return
-	 */
-	Page<T> selectPage(Page<T> page);
-
-	/**
-	 * <p>
-	 * 查询列表
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            {@link Wrapper}
-	 * @return
-	 */
-	List<Map<String, Object>> selectMaps(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 根据 Wrapper 条件,查询全部记录
-	 * </p>
-	 *
-	 * @param wrapper
-	 *            实体对象封装操作类(可以为 null)
-	 * @return List<Object>
-	 */
-	List<Object> selectObjs(Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 翻页查询
-	 * </p>
-	 *
-	 * @param page
-	 *            翻页对象
-	 * @param wrapper
-	 *            {@link Wrapper}
-	 * @return
-	 */
-	@SuppressWarnings("rawtypes")
-	Page<Map<String, Object>> selectMapsPage(Page page, Wrapper<T> wrapper);
-
-	/**
-	 * <p>
-	 * 翻页查询
-	 * </p>
-	 *
-	 * @param page
-	 *            翻页对象
-	 * @param wrapper
-	 *            实体包装类 {@link Wrapper}
-	 * @return
-	 */
-	Page<T> selectPage(Page<T> page, Wrapper<T> wrapper);
+    /**
+     * <p>
+     * 插入一条记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return boolean
+     */
+    boolean insert(T entity);
+
+    /**
+     * <p>
+     * 插入一条记录(选择字段, null 字段不插入)
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return boolean
+     */
+    boolean insertAllColumn(T entity);
+
+    /**
+     * <p>
+     * 插入(批量),该方法不适合 Oracle
+     * </p>
+     *
+     * @param entityList
+     *            实体对象列表
+     * @return boolean
+     */
+    boolean insertBatch(List<T> entityList);
+
+    /**
+     * <p>
+     * 插入(批量)
+     * </p>
+     *
+     * @param entityList
+     *            实体对象列表
+     * @param batchSize
+     *            插入批次数量
+     * @return boolean
+     */
+    boolean insertBatch(List<T> entityList, int batchSize);
+
+    /**
+     * <p>
+     * 批量修改插入
+     * </p>
+     *
+     * @param entityList
+     *            实体对象列表
+     * @return boolean
+     */
+    boolean insertOrUpdateBatch(List<T> entityList);
+
+    /**
+     * <p>
+     * 批量修改插入
+     * </p>
+     *
+     * @param entityList
+     *            实体对象列表
+     * @param batchSize
+     *
+     * @return boolean
+     */
+    boolean insertOrUpdateBatch(List<T> entityList, int batchSize);
+
+    /**
+     * <p>
+     * 根据 ID 删除
+     * </p>
+     *
+     * @param id
+     *            主键ID
+     * @return boolean
+     */
+    boolean deleteById(Serializable id);
+
+    /**
+     * <p>
+     * 根据 columnMap 条件,删除记录
+     * </p>
+     *
+     * @param columnMap
+     *            表字段 map 对象
+     * @return boolean
+     */
+    boolean deleteByMap(Map<String, Object> columnMap);
+
+    /**
+     * <p>
+     * 根据 entity 条件,删除记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体包装类 {@link Wrapper}
+     * @return boolean
+     */
+    boolean delete(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 删除(根据ID 批量删除)
+     * </p>
+     *
+     * @param idList
+     *            主键ID列表
+     * @return boolean
+     */
+    boolean deleteBatchIds(List<? extends Serializable> idList);
+
+    /**
+     * <p>
+     * 根据 ID 修改
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return boolean
+     */
+    boolean updateById(T entity);
+
+    /**
+     * <p>
+     * 根据 ID 选择修改
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return boolean
+     */
+    boolean updateAllColumnById(T entity);
+
+    /**
+     * <p>
+     * 根据 whereEntity 条件,更新记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @param wrapper
+     *            实体包装类 {@link Wrapper}
+     * @return boolean
+     */
+    boolean update(T entity, Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据ID 批量更新
+     * </p>
+     *
+     * @param entityList
+     *            实体对象列表
+     * @return boolean
+     */
+    boolean updateBatchById(List<T> entityList);
+
+    /**
+     * <p>
+     * 根据ID 批量更新
+     * </p>
+     *
+     * @param entityList
+     *            实体对象列表
+     * @param batchSize
+     *            更新批次数量
+     * @return boolean
+     */
+    boolean updateBatchById(List<T> entityList, int batchSize);
+
+    /**
+     * <p>
+     * TableId 注解存在更新记录,否插入一条记录
+     * </p>
+     *
+     * @param entity
+     *            实体对象
+     * @return boolean
+     */
+    boolean insertOrUpdate(T entity);
+
+    /**
+     * <p>
+     * 根据 ID 查询
+     * </p>
+     *
+     * @param id
+     *            主键ID
+     * @return T
+     */
+    T selectById(Serializable id);
+
+    /**
+     * <p>
+     * 查询(根据ID 批量查询)
+     * </p>
+     *
+     * @param idList
+     *            主键ID列表
+     * @return List<T>
+     */
+    List<T> selectBatchIds(List<? extends Serializable> idList);
+
+    /**
+     * <p>
+     * 查询(根据 columnMap 条件)
+     * </p>
+     *
+     * @param columnMap
+     *            表字段 map 对象
+     * @return List<T>
+     */
+    List<T> selectByMap(Map<String, Object> columnMap);
+
+    /**
+     * <p>
+     * 根据 Wrapper,查询一条记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象
+     * @return T
+     */
+    T selectOne(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper,查询一条记录
+     * </p>
+     *
+     * @param wrapper
+     *            {@link Wrapper}
+     * @return Map<String,Object>
+     */
+    Map<String, Object> selectMap(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper,查询一条记录
+     * </p>
+     *
+     * @param wrapper
+     *            {@link Wrapper}
+     * @return Object
+     */
+    Object selectObj(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper 条件,查询总记录数
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象
+     * @return int
+     */
+    int selectCount(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 查询列表
+     * </p>
+     *
+     * @param wrapper
+     *            实体包装类 {@link Wrapper}
+     * @return
+     */
+    List<T> selectList(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 翻页查询
+     * </p>
+     *
+     * @param page
+     *            翻页对象
+     * @return
+     */
+    Page<T> selectPage(Page<T> page);
+
+    /**
+     * <p>
+     * 查询列表
+     * </p>
+     *
+     * @param wrapper
+     *            {@link Wrapper}
+     * @return
+     */
+    List<Map<String, Object>> selectMaps(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 根据 Wrapper 条件,查询全部记录
+     * </p>
+     *
+     * @param wrapper
+     *            实体对象封装操作类(可以为 null)
+     * @return List<Object>
+     */
+    List<Object> selectObjs(Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 翻页查询
+     * </p>
+     *
+     * @param page
+     *            翻页对象
+     * @param wrapper
+     *            {@link Wrapper}
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    Page<Map<String, Object>> selectMapsPage(Page page, Wrapper<T> wrapper);
+
+    /**
+     * <p>
+     * 翻页查询
+     * </p>
+     *
+     * @param page
+     *            翻页对象
+     * @param wrapper
+     *            实体包装类 {@link Wrapper}
+     * @return
+     */
+    Page<T> selectPage(Page<T> page, Wrapper<T> wrapper);
 
 }

+ 18 - 27
mybatis-plus/src/main/java/com/baomidou/mybatisplus/service/impl/ServiceImpl.java

@@ -54,6 +54,21 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
     @Autowired
     protected M baseMapper;
 
+    /**
+     * <p>
+     * 判断数据库操作是否成功
+     * </p>
+     * <p>
+     * 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
+     * </p>
+     *
+     * @param result 数据库操作返回影响条数
+     * @return boolean
+     */
+    protected static boolean retBool(Integer result) {
+        return SqlHelper.retBool(result);
+    }
+
     @SuppressWarnings("unchecked")
     protected Class<T> currentModleClass() {
         return ReflectionKit.getSuperClassGenricType(getClass(), 1);
@@ -78,21 +93,6 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         return SqlHelper.table(currentModleClass()).getSqlStatement(sqlMethod.getMethod());
     }
 
-    /**
-     * <p>
-     * 判断数据库操作是否成功
-     * </p>
-     * <p>
-     * 注意!! 该方法为 Integer 判断,不可传入 int 基本类型
-     * </p>
-     *
-     * @param result 数据库操作返回影响条数
-     * @return boolean
-     */
-    protected static boolean retBool(Integer result) {
-        return SqlHelper.retBool(result);
-    }
-
     public boolean insert(T entity) {
         return retBool(baseMapper.insert(entity));
     }
@@ -116,8 +116,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         if (CollectionUtils.isEmpty(entityList)) {
             throw new IllegalArgumentException("Error: entityList must not be empty");
         }
-        SqlSession batchSqlSession = sqlSessionBatch();
-        try {
+        try (SqlSession batchSqlSession = sqlSessionBatch()) {
             int size = entityList.size();
             String sqlStatement = sqlStatement(SqlMethod.INSERT_ONE);
             for (int i = 0; i < size; i++) {
@@ -130,8 +129,6 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         } catch (Exception e) {
             logger.error("Error: Cannot execute insertBatch Method. Cause:" + e);
             return false;
-        } finally {
-            batchSqlSession.close();
         }
         return true;
 
@@ -174,8 +171,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         if (CollectionUtils.isEmpty(entityList)) {
             throw new IllegalArgumentException("Error: entityList must not be empty");
         }
-        SqlSession batchSqlSession = sqlSessionBatch();
-        try {
+        try (SqlSession batchSqlSession = sqlSessionBatch()) {
             int size = entityList.size();
             for (int i = 0; i < size; i++) {
                 insertOrUpdate(entityList.get(i));
@@ -187,8 +183,6 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         } catch (Exception e) {
             logger.error("Error: Cannot execute insertOrUpdateBatch Method. Cause:" + e);
             return false;
-        } finally {
-            batchSqlSession.close();
         }
         return true;
     }
@@ -232,8 +226,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         if (CollectionUtils.isEmpty(entityList)) {
             throw new IllegalArgumentException("Error: entityList must not be empty");
         }
-        SqlSession batchSqlSession = sqlSessionBatch();
-        try {
+        try (SqlSession batchSqlSession = sqlSessionBatch()) {
             int size = entityList.size();
             String sqlStatement = sqlStatement(SqlMethod.UPDATE_BY_ID);
             for (int i = 0; i < size; i++) {
@@ -246,8 +239,6 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
         } catch (Exception e) {
             logger.error("Error: Cannot execute insertBatch Method. Cause:" + e);
             return false;
-        } finally {
-            batchSqlSession.close();
         }
         return true;
     }

+ 233 - 236
mybatis-plus/src/main/java/com/baomidou/mybatisplus/spring/MybatisMapperRefresh.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,8 +15,16 @@
  */
 package com.baomidou.mybatisplus.spring;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-import com.baomidou.mybatisplus.toolkit.SystemClock;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
 import org.apache.ibatis.binding.MapperRegistry;
 import org.apache.ibatis.builder.xml.XMLMapperBuilder;
 import org.apache.ibatis.builder.xml.XMLMapperEntityResolver;
@@ -35,15 +43,8 @@ import org.springframework.core.io.Resource;
 import org.springframework.core.io.UrlResource;
 import org.springframework.util.ResourceUtils;
 
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.toolkit.SystemClock;
 
 /**
  * <p>
@@ -56,241 +57,237 @@ import java.util.Set;
  * @Date 2016-08-25
  */
 public class MybatisMapperRefresh implements Runnable {
-	private static final Log logger = LogFactory.getLog(MybatisMapperRefresh.class);
-	private SqlSessionFactory sqlSessionFactory;
-	private Resource[] mapperLocations;
-	private Long beforeTime = 0L;
-	private Configuration configuration;
-
-	/**
-	 * 是否开启刷新mapper
-	 */
-	private boolean enabled;
-
-	/**
-	 * xml文件目录
-	 */
-	private Set<String> fileSet;
-
-	/**
-	 * 延迟加载时间
-	 */
-	private int delaySeconds = 10;
-
-	/**
-	 * 刷新间隔时间
-	 */
-	private int sleepSeconds = 20;
 
-	/**
-	 * 记录jar包存在的mapper
-	 */
-	private static Map<String, List<Resource>> jarMapper = new HashMap<String, List<Resource>>();
+    private static final Log logger = LogFactory.getLog(MybatisMapperRefresh.class);
+    /**
+     * 记录jar包存在的mapper
+     */
+    private static Map<String, List<Resource>> jarMapper = new HashMap<String, List<Resource>>();
+    private SqlSessionFactory sqlSessionFactory;
+    private Resource[] mapperLocations;
+    private Long beforeTime = 0L;
+    private Configuration configuration;
+    /**
+     * 是否开启刷新mapper
+     */
+    private boolean enabled;
+    /**
+     * xml文件目录
+     */
+    private Set<String> fileSet;
+    /**
+     * 延迟加载时间
+     */
+    private int delaySeconds = 10;
+    /**
+     * 刷新间隔时间
+     */
+    private int sleepSeconds = 20;
 
-	public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, int delaySeconds,
-			int sleepSeconds, boolean enabled) {
-		this.mapperLocations = mapperLocations;
-		this.sqlSessionFactory = sqlSessionFactory;
-		this.delaySeconds = delaySeconds;
-		this.enabled = enabled;
-		this.sleepSeconds = sleepSeconds;
-		this.configuration = sqlSessionFactory.getConfiguration();
-		this.run();
-	}
+    public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, int delaySeconds,
+                                int sleepSeconds, boolean enabled) {
+        this.mapperLocations = mapperLocations;
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.delaySeconds = delaySeconds;
+        this.enabled = enabled;
+        this.sleepSeconds = sleepSeconds;
+        this.configuration = sqlSessionFactory.getConfiguration();
+        this.run();
+    }
 
-	public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, boolean enabled) {
-		this.mapperLocations = mapperLocations;
-		this.sqlSessionFactory = sqlSessionFactory;
-		this.enabled = enabled;
-		this.configuration = sqlSessionFactory.getConfiguration();
-		this.run();
-	}
+    public MybatisMapperRefresh(Resource[] mapperLocations, SqlSessionFactory sqlSessionFactory, boolean enabled) {
+        this.mapperLocations = mapperLocations;
+        this.sqlSessionFactory = sqlSessionFactory;
+        this.enabled = enabled;
+        this.configuration = sqlSessionFactory.getConfiguration();
+        this.run();
+    }
 
-	public void run() {
-		final GlobalConfiguration globalConfig = GlobalConfiguration.getGlobalConfig(configuration);
-		/*
+    public void run() {
+        final GlobalConfiguration globalConfig = GlobalConfiguration.getGlobalConfig(configuration);
+        /*
 		 * 启动 XML 热加载
 		 */
-		if (enabled) {
-			beforeTime = SystemClock.now();
-			final MybatisMapperRefresh runnable = this;
-			new Thread(new Runnable() {
+        if (enabled) {
+            beforeTime = SystemClock.now();
+            final MybatisMapperRefresh runnable = this;
+            new Thread(new Runnable() {
 
-				public void run() {
-					if (fileSet == null) {
-						fileSet = new HashSet<String>();
-						for (Resource mapperLocation : mapperLocations) {
-							try {
-								if (ResourceUtils.isJarURL(mapperLocation.getURL())) {
-									String key = new UrlResource(ResourceUtils.extractJarFileURL(mapperLocation.getURL()))
-											.getFile().getPath();
-									fileSet.add(key);
-									if (jarMapper.get(key) != null) {
-										jarMapper.get(key).add(mapperLocation);
-									} else {
-										List<Resource> resourcesList = new ArrayList<Resource>();
-										resourcesList.add(mapperLocation);
-										jarMapper.put(key, resourcesList);
-									}
-								} else {
-									fileSet.add(mapperLocation.getFile().getPath());
-								}
-							} catch (IOException ioException) {
-								ioException.printStackTrace();
-							}
-						}
-					}
-					try {
-						Thread.sleep(delaySeconds * 1000);
-					} catch (InterruptedException interruptedException) {
-						interruptedException.printStackTrace();
-					}
-					do {
-						try {
-							for (String filePath : fileSet) {
-								File file = new File(filePath);
-								if (file.isFile() && file.lastModified() > beforeTime) {
-									globalConfig.setRefresh(true);
-									List<Resource> removeList = jarMapper.get(filePath);
-									if (removeList != null && !removeList.isEmpty()) {// 如果是jar包中的xml,将刷新jar包中存在的所有xml,后期再修改加载jar中修改过后的xml
-										for (Resource resource : removeList) {
-											runnable.refresh(resource);
-										}
-									} else {
-										runnable.refresh(new FileSystemResource(file));
-									}
-								}
-							}
-							if (globalConfig.isRefresh()) {
-								beforeTime = SystemClock.now();
-							}
-							globalConfig.setRefresh(true);
-						} catch (Exception exception) {
-							exception.printStackTrace();
-						}
-						try {
-							Thread.sleep(sleepSeconds * 1000);
-						} catch (InterruptedException interruptedException) {
-							interruptedException.printStackTrace();
-						}
+                public void run() {
+                    if (fileSet == null) {
+                        fileSet = new HashSet<String>();
+                        for (Resource mapperLocation : mapperLocations) {
+                            try {
+                                if (ResourceUtils.isJarURL(mapperLocation.getURL())) {
+                                    String key = new UrlResource(ResourceUtils.extractJarFileURL(mapperLocation.getURL()))
+                                            .getFile().getPath();
+                                    fileSet.add(key);
+                                    if (jarMapper.get(key) != null) {
+                                        jarMapper.get(key).add(mapperLocation);
+                                    } else {
+                                        List<Resource> resourcesList = new ArrayList<Resource>();
+                                        resourcesList.add(mapperLocation);
+                                        jarMapper.put(key, resourcesList);
+                                    }
+                                } else {
+                                    fileSet.add(mapperLocation.getFile().getPath());
+                                }
+                            } catch (IOException ioException) {
+                                ioException.printStackTrace();
+                            }
+                        }
+                    }
+                    try {
+                        Thread.sleep(delaySeconds * 1000);
+                    } catch (InterruptedException interruptedException) {
+                        interruptedException.printStackTrace();
+                    }
+                    do {
+                        try {
+                            for (String filePath : fileSet) {
+                                File file = new File(filePath);
+                                if (file.isFile() && file.lastModified() > beforeTime) {
+                                    globalConfig.setRefresh(true);
+                                    List<Resource> removeList = jarMapper.get(filePath);
+                                    if (removeList != null && !removeList.isEmpty()) {// 如果是jar包中的xml,将刷新jar包中存在的所有xml,后期再修改加载jar中修改过后的xml
+                                        for (Resource resource : removeList) {
+                                            runnable.refresh(resource);
+                                        }
+                                    } else {
+                                        runnable.refresh(new FileSystemResource(file));
+                                    }
+                                }
+                            }
+                            if (globalConfig.isRefresh()) {
+                                beforeTime = SystemClock.now();
+                            }
+                            globalConfig.setRefresh(true);
+                        } catch (Exception exception) {
+                            exception.printStackTrace();
+                        }
+                        try {
+                            Thread.sleep(sleepSeconds * 1000);
+                        } catch (InterruptedException interruptedException) {
+                            interruptedException.printStackTrace();
+                        }
 
-					} while (true);
-				}
-			}, "mybatis-plus MapperRefresh").start();
-		}
-	}
+                    } while (true);
+                }
+            }, "mybatis-plus MapperRefresh").start();
+        }
+    }
 
-	/**
-	 * 刷新mapper
-	 *
-	 * @throws Exception
-	 */
-	@SuppressWarnings("rawtypes")
-	private void refresh(Resource resource) throws Exception {
-		this.configuration = sqlSessionFactory.getConfiguration();
-		boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
-		try {
-			Field loadedResourcesField = isSupper ? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
-					: configuration.getClass().getDeclaredField("loadedResources");
-			loadedResourcesField.setAccessible(true);
-			Set loadedResourcesSet = ((Set) loadedResourcesField.get(configuration));
-			XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, configuration.getVariables(),
-					new XMLMapperEntityResolver());
-			XNode context = xPathParser.evalNode("/mapper");
-			String namespace = context.getStringAttribute("namespace");
-			Field field = MapperRegistry.class.getDeclaredField("knownMappers");
-			field.setAccessible(true);
-			Map mapConfig = (Map) field.get(configuration.getMapperRegistry());
-			mapConfig.remove(Resources.classForName(namespace));
-			loadedResourcesSet.remove(resource.toString());
-			configuration.getCacheNames().remove(namespace);
-			cleanParameterMap(context.evalNodes("/mapper/parameterMap"), namespace);
-			cleanResultMap(context.evalNodes("/mapper/resultMap"), namespace);
-			cleanKeyGenerators(context.evalNodes("insert|update"), namespace);
-			cleanSqlElement(context.evalNodes("/mapper/sql"), namespace);
-			XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),
-					sqlSessionFactory.getConfiguration(), // 注入的sql先不进行处理了
-					resource.toString(), sqlSessionFactory.getConfiguration().getSqlFragments());
-			xmlMapperBuilder.parse();
-			logger.debug("refresh: '" + resource + "', success!");
-		} catch (Exception e) {
-			throw new NestedIOException("Failed to parse mapping resource: '" + resource + "'", e);
-		} finally {
-			ErrorContext.instance().reset();
-		}
-	}
+    /**
+     * 刷新mapper
+     *
+     * @throws Exception
+     */
+    @SuppressWarnings("rawtypes")
+    private void refresh(Resource resource) throws Exception {
+        this.configuration = sqlSessionFactory.getConfiguration();
+        boolean isSupper = configuration.getClass().getSuperclass() == Configuration.class;
+        try {
+            Field loadedResourcesField = isSupper ? configuration.getClass().getSuperclass().getDeclaredField("loadedResources")
+                    : configuration.getClass().getDeclaredField("loadedResources");
+            loadedResourcesField.setAccessible(true);
+            Set loadedResourcesSet = ((Set) loadedResourcesField.get(configuration));
+            XPathParser xPathParser = new XPathParser(resource.getInputStream(), true, configuration.getVariables(),
+                    new XMLMapperEntityResolver());
+            XNode context = xPathParser.evalNode("/mapper");
+            String namespace = context.getStringAttribute("namespace");
+            Field field = MapperRegistry.class.getDeclaredField("knownMappers");
+            field.setAccessible(true);
+            Map mapConfig = (Map) field.get(configuration.getMapperRegistry());
+            mapConfig.remove(Resources.classForName(namespace));
+            loadedResourcesSet.remove(resource.toString());
+            configuration.getCacheNames().remove(namespace);
+            cleanParameterMap(context.evalNodes("/mapper/parameterMap"), namespace);
+            cleanResultMap(context.evalNodes("/mapper/resultMap"), namespace);
+            cleanKeyGenerators(context.evalNodes("insert|update"), namespace);
+            cleanSqlElement(context.evalNodes("/mapper/sql"), namespace);
+            XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(resource.getInputStream(),
+                    sqlSessionFactory.getConfiguration(), // 注入的sql先不进行处理了
+                    resource.toString(), sqlSessionFactory.getConfiguration().getSqlFragments());
+            xmlMapperBuilder.parse();
+            logger.debug("refresh: '" + resource + "', success!");
+        } catch (Exception e) {
+            throw new NestedIOException("Failed to parse mapping resource: '" + resource + "'", e);
+        } finally {
+            ErrorContext.instance().reset();
+        }
+    }
 
-	/**
-	 * 清理parameterMap
-	 *
-	 * @param list
-	 * @param namespace
-	 */
-	private void cleanParameterMap(List<XNode> list, String namespace) {
-		for (XNode parameterMapNode : list) {
-			String id = parameterMapNode.getStringAttribute("id");
-			configuration.getParameterMaps().remove(namespace + "." + id);
-		}
-	}
+    /**
+     * 清理parameterMap
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanParameterMap(List<XNode> list, String namespace) {
+        for (XNode parameterMapNode : list) {
+            String id = parameterMapNode.getStringAttribute("id");
+            configuration.getParameterMaps().remove(namespace + "." + id);
+        }
+    }
 
-	/**
-	 * 清理resultMap
-	 *
-	 * @param list
-	 * @param namespace
-	 */
-	private void cleanResultMap(List<XNode> list, String namespace) {
-		for (XNode resultMapNode : list) {
-			String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
-			configuration.getResultMapNames().remove(id);
-			configuration.getResultMapNames().remove(namespace + "." + id);
-			clearResultMap(resultMapNode, namespace);
-		}
-	}
+    /**
+     * 清理resultMap
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanResultMap(List<XNode> list, String namespace) {
+        for (XNode resultMapNode : list) {
+            String id = resultMapNode.getStringAttribute("id", resultMapNode.getValueBasedIdentifier());
+            configuration.getResultMapNames().remove(id);
+            configuration.getResultMapNames().remove(namespace + "." + id);
+            clearResultMap(resultMapNode, namespace);
+        }
+    }
 
-	private void clearResultMap(XNode xNode, String namespace) {
-		for (XNode resultChild : xNode.getChildren()) {
-			if ("association".equals(resultChild.getName()) || "collection".equals(resultChild.getName())
-					|| "case".equals(resultChild.getName())) {
-				if (resultChild.getStringAttribute("select") == null) {
-					configuration.getResultMapNames().remove(
-							resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
-					configuration.getResultMapNames().remove(
-							namespace + "." + resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
-					if (resultChild.getChildren() != null && !resultChild.getChildren().isEmpty()) {
-						clearResultMap(resultChild, namespace);
-					}
-				}
-			}
-		}
-	}
+    private void clearResultMap(XNode xNode, String namespace) {
+        for (XNode resultChild : xNode.getChildren()) {
+            if ("association".equals(resultChild.getName()) || "collection".equals(resultChild.getName())
+                    || "case".equals(resultChild.getName())) {
+                if (resultChild.getStringAttribute("select") == null) {
+                    configuration.getResultMapNames().remove(
+                            resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
+                    configuration.getResultMapNames().remove(
+                            namespace + "." + resultChild.getStringAttribute("id", resultChild.getValueBasedIdentifier()));
+                    if (resultChild.getChildren() != null && !resultChild.getChildren().isEmpty()) {
+                        clearResultMap(resultChild, namespace);
+                    }
+                }
+            }
+        }
+    }
 
-	/**
-	 * 清理selectKey
-	 *
-	 * @param list
-	 * @param namespace
-	 */
-	private void cleanKeyGenerators(List<XNode> list, String namespace) {
-		for (XNode context : list) {
-			String id = context.getStringAttribute("id");
-			configuration.getKeyGeneratorNames().remove(id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
-			configuration.getKeyGeneratorNames().remove(namespace + "." + id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
-		}
-	}
+    /**
+     * 清理selectKey
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanKeyGenerators(List<XNode> list, String namespace) {
+        for (XNode context : list) {
+            String id = context.getStringAttribute("id");
+            configuration.getKeyGeneratorNames().remove(id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
+            configuration.getKeyGeneratorNames().remove(namespace + "." + id + SelectKeyGenerator.SELECT_KEY_SUFFIX);
+        }
+    }
 
-	/**
-	 * 清理sql节点缓存
-	 *
-	 * @param list
-	 * @param namespace
-	 */
-	private void cleanSqlElement(List<XNode> list, String namespace) {
-		for (XNode context : list) {
-			String id = context.getStringAttribute("id");
-			configuration.getSqlFragments().remove(id);
-			configuration.getSqlFragments().remove(namespace + "." + id);
-		}
-	}
+    /**
+     * 清理sql节点缓存
+     *
+     * @param list
+     * @param namespace
+     */
+    private void cleanSqlElement(List<XNode> list, String namespace) {
+        for (XNode context : list) {
+            String id = context.getStringAttribute("id");
+            configuration.getSqlFragments().remove(id);
+            configuration.getSqlFragments().remove(namespace + "." + id);
+        }
+    }
 
 }

+ 554 - 552
mybatis-plus/src/main/java/com/baomidou/mybatisplus/spring/MybatisSqlSessionFactoryBean.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
@@ -15,13 +15,18 @@
  */
 package com.baomidou.mybatisplus.spring;
 
-import com.baomidou.mybatisplus.MybatisConfiguration;
-import com.baomidou.mybatisplus.MybatisXMLConfigBuilder;
-import com.baomidou.mybatisplus.MybatisXMLMapperBuilder;
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
-import com.baomidou.mybatisplus.mapper.SqlRunner;
-import com.baomidou.mybatisplus.toolkit.PackageHelper;
+import static org.springframework.util.Assert.notNull;
+import static org.springframework.util.Assert.state;
+import static org.springframework.util.ObjectUtils.isEmpty;
+import static org.springframework.util.StringUtils.hasLength;
+import static org.springframework.util.StringUtils.tokenizeToStringArray;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import javax.sql.DataSource;
+
 import org.apache.ibatis.cache.Cache;
 import org.apache.ibatis.executor.ErrorContext;
 import org.apache.ibatis.io.VFS;
@@ -48,16 +53,13 @@ import org.springframework.core.NestedIOException;
 import org.springframework.core.io.Resource;
 import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;
 
-import javax.sql.DataSource;
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.Properties;
-
-import static org.springframework.util.Assert.notNull;
-import static org.springframework.util.Assert.state;
-import static org.springframework.util.ObjectUtils.isEmpty;
-import static org.springframework.util.StringUtils.hasLength;
-import static org.springframework.util.StringUtils.tokenizeToStringArray;
+import com.baomidou.mybatisplus.MybatisConfiguration;
+import com.baomidou.mybatisplus.MybatisXMLConfigBuilder;
+import com.baomidou.mybatisplus.MybatisXMLMapperBuilder;
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.mapper.SqlRunner;
+import com.baomidou.mybatisplus.toolkit.PackageHelper;
 
 /**
  * <p>
@@ -69,557 +71,557 @@ import static org.springframework.util.StringUtils.tokenizeToStringArray;
  * @Date 2017-01-04
  */
 public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean,
-		ApplicationListener<ApplicationEvent> {
+        ApplicationListener<ApplicationEvent> {
 
-	private static final Log LOGGER = LogFactory.getLog(MybatisSqlSessionFactoryBean.class);
+    private static final Log LOGGER = LogFactory.getLog(MybatisSqlSessionFactoryBean.class);
 
-	private Resource configLocation;
+    private Resource configLocation;
 
-	private Configuration configuration;
+    private Configuration configuration;
 
-	private Resource[] mapperLocations;
+    private Resource[] mapperLocations;
 
-	private DataSource dataSource;
+    private DataSource dataSource;
 
-	private TransactionFactory transactionFactory;
+    private TransactionFactory transactionFactory;
 
-	private Properties configurationProperties;
+    private Properties configurationProperties;
 
-	private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
+    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
 
-	private SqlSessionFactory sqlSessionFactory;
+    private SqlSessionFactory sqlSessionFactory;
 
-	// EnvironmentAware requires spring 3.1
-	private String environment = MybatisSqlSessionFactoryBean.class.getSimpleName();
+    // EnvironmentAware requires spring 3.1
+    private String environment = MybatisSqlSessionFactoryBean.class.getSimpleName();
 
-	private boolean failFast;
+    private boolean failFast;
 
-	private Interceptor[] plugins;
+    private Interceptor[] plugins;
 
-	private TypeHandler<?>[] typeHandlers;
+    private TypeHandler<?>[] typeHandlers;
 
-	private String typeHandlersPackage;
+    private String typeHandlersPackage;
 
-	private Class<?>[] typeAliases;
+    private Class<?>[] typeAliases;
 
-	private String typeAliasesPackage;
+    private String typeAliasesPackage;
 
-	private Class<?> typeAliasesSuperType;
+    private Class<?> typeAliasesSuperType;
 
-	// issue #19. No default provider.
-	private DatabaseIdProvider databaseIdProvider;
+    // issue #19. No default provider.
+    private DatabaseIdProvider databaseIdProvider;
 
-	private Class<? extends VFS> vfs;
+    private Class<? extends VFS> vfs;
 
-	private Cache cache;
-
-	private ObjectFactory objectFactory;
-
-	private ObjectWrapperFactory objectWrapperFactory;
-
-	private GlobalConfiguration globalConfig = GlobalConfiguration.defaults();
-
-	// TODO 注入全局配置
-	public void setGlobalConfig(GlobalConfiguration globalConfig) {
-		this.globalConfig = globalConfig;
-	}
-
-	/**
-	 * Sets the ObjectFactory.
-	 *
-	 * @since 1.1.2
-	 * @param objectFactory
-	 */
-	public void setObjectFactory(ObjectFactory objectFactory) {
-		this.objectFactory = objectFactory;
-	}
-
-	/**
-	 * Sets the ObjectWrapperFactory.
-	 *
-	 * @since 1.1.2
-	 * @param objectWrapperFactory
-	 */
-	public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory) {
-		this.objectWrapperFactory = objectWrapperFactory;
-	}
-
-	/**
-	 * Gets the DatabaseIdProvider
-	 *
-	 * @since 1.1.0
-	 * @return
-	 */
-	public DatabaseIdProvider getDatabaseIdProvider() {
-		return databaseIdProvider;
-	}
-
-	/**
-	 * Sets the DatabaseIdProvider. As of version 1.2.2 this variable is not
-	 * initialized by default.
-	 *
-	 * @since 1.1.0
-	 * @param databaseIdProvider
-	 */
-	public void setDatabaseIdProvider(DatabaseIdProvider databaseIdProvider) {
-		this.databaseIdProvider = databaseIdProvider;
-	}
-
-	public Class<? extends VFS> getVfs() {
-		return this.vfs;
-	}
-
-	public void setVfs(Class<? extends VFS> vfs) {
-		this.vfs = vfs;
-	}
-
-	public Cache getCache() {
-		return this.cache;
-	}
-
-	public void setCache(Cache cache) {
-		this.cache = cache;
-	}
-
-	/**
-	 * Mybatis plugin list.
-	 *
-	 * @since 1.0.1
-	 *
-	 * @param plugins
-	 *            list of plugins
-	 *
-	 */
-	public void setPlugins(Interceptor[] plugins) {
-		this.plugins = plugins;
-	}
-
-	/**
-	 * Packages to search for type aliases.
-	 *
-	 * @since 1.0.1
-	 *
-	 * @param typeAliasesPackage
-	 *            package to scan for domain objects
-	 *
-	 */
-	public void setTypeAliasesPackage(String typeAliasesPackage) {
-		this.typeAliasesPackage = typeAliasesPackage;
-	}
-
-	/**
-	 * Super class which domain objects have to extend to have a type alias
-	 * created. No effect if there is no package to scan configured.
-	 *
-	 * @since 1.1.2
-	 *
-	 * @param typeAliasesSuperType
-	 *            super class for domain objects
-	 *
-	 */
-	public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType) {
-		this.typeAliasesSuperType = typeAliasesSuperType;
-	}
-
-	/**
-	 * Packages to search for type handlers.
-	 *
-	 * @since 1.0.1
-	 *
-	 * @param typeHandlersPackage
-	 *            package to scan for type handlers
-	 *
-	 */
-	public void setTypeHandlersPackage(String typeHandlersPackage) {
-		this.typeHandlersPackage = typeHandlersPackage;
-	}
-
-	/**
-	 * Set type handlers. They must be annotated with {@code MappedTypes} and
-	 * optionally with {@code MappedJdbcTypes}
-	 *
-	 * @since 1.0.1
-	 *
-	 * @param typeHandlers
-	 *            Type handler list
-	 */
-	public void setTypeHandlers(TypeHandler<?>[] typeHandlers) {
-		this.typeHandlers = typeHandlers;
-	}
-
-	/**
-	 * List of type aliases to register. They can be annotated with
-	 * {@code Alias}
-	 *
-	 * @since 1.0.1
-	 *
-	 * @param typeAliases
-	 *            Type aliases list
-	 */
-	public void setTypeAliases(Class<?>[] typeAliases) {
-		this.typeAliases = typeAliases;
-	}
-
-	/**
-	 * If true, a final check is done on Configuration to assure that all mapped
-	 * statements are fully loaded and there is no one still pending to resolve
-	 * includes. Defaults to false.
-	 *
-	 * @since 1.0.1
-	 *
-	 * @param failFast
-	 *            enable failFast
-	 */
-	public void setFailFast(boolean failFast) {
-		this.failFast = failFast;
-	}
-
-	/**
-	 * Set the location of the MyBatis {@code SqlSessionFactory} config file. A
-	 * typical value is "WEB-INF/mybatis-configuration.xml".
-	 */
-	public void setConfigLocation(Resource configLocation) {
-		this.configLocation = configLocation;
-	}
-
-	/**
-	 * Set a customized MyBatis configuration.
-	 *
-	 * @param configuration
-	 *            MyBatis configuration
-	 * @since 1.3.0
-	 */
-	public void setConfiguration(Configuration configuration) {
-		this.configuration = configuration;
-	}
-
-	/**
-	 * Set locations of MyBatis mapper files that are going to be merged into
-	 * the {@code SqlSessionFactory} configuration at runtime.
-	 *
-	 * This is an alternative to specifying "&lt;sqlmapper&gt;" entries in an
-	 * MyBatis config file. This property being based on Spring's resource
-	 * abstraction also allows for specifying resource patterns here: e.g.
-	 * "classpath*:sqlmap/*-mapper.xml".
-	 */
-	public void setMapperLocations(Resource[] mapperLocations) {
-		this.mapperLocations = mapperLocations;
-	}
-
-	/**
-	 * Set optional properties to be passed into the SqlSession configuration,
-	 * as alternative to a {@code &lt;properties&gt;} tag in the configuration
-	 * xml file. This will be used to resolve placeholders in the config file.
-	 */
-	public void setConfigurationProperties(Properties sqlSessionFactoryProperties) {
-		this.configurationProperties = sqlSessionFactoryProperties;
-	}
-
-	/**
-	 * Set the JDBC {@code DataSource} that this instance should manage
-	 * transactions for. The {@code DataSource} should match the one used by the
-	 * {@code SqlSessionFactory}: for example, you could specify the same JNDI
-	 * DataSource for both.
-	 *
-	 * A transactional JDBC {@code Connection} for this {@code DataSource} will
-	 * be provided to application code accessing this {@code DataSource}
-	 * directly via {@code DataSourceUtils} or
-	 * {@code DataSourceTransactionManager}.
-	 *
-	 * The {@code DataSource} specified here should be the target
-	 * {@code DataSource} to manage transactions for, not a
-	 * {@code TransactionAwareDataSourceProxy}. Only data access code may work
-	 * with {@code TransactionAwareDataSourceProxy}, while the transaction
-	 * manager needs to work on the underlying target {@code DataSource}. If
-	 * there's nevertheless a {@code TransactionAwareDataSourceProxy} passed in,
-	 * it will be unwrapped to extract its target {@code DataSource}.
-	 *
-	 */
-	public void setDataSource(DataSource dataSource) {
-		if (dataSource instanceof TransactionAwareDataSourceProxy) {
-			// If we got a TransactionAwareDataSourceProxy, we need to perform
-			// transactions for its underlying target DataSource, else data
-			// access code won't see properly exposed transactions (i.e.
-			// transactions for the target DataSource).
-			this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
-		} else {
-			this.dataSource = dataSource;
-		}
-	}
-
-	/**
-	 * Sets the {@code SqlSessionFactoryBuilder} to use when creating the
-	 * {@code SqlSessionFactory}.
-	 *
-	 * This is mainly meant for testing so that mock SqlSessionFactory classes
-	 * can be injected. By default, {@code SqlSessionFactoryBuilder} creates
-	 * {@code DefaultSqlSessionFactory} instances.
-	 *
-	 */
-	public void setSqlSessionFactoryBuilder(SqlSessionFactoryBuilder sqlSessionFactoryBuilder) {
-		this.sqlSessionFactoryBuilder = sqlSessionFactoryBuilder;
-	}
-
-	/**
-	 * Set the MyBatis TransactionFactory to use. Default is
-	 * {@code SpringManagedTransactionFactory}
-	 *
-	 * The default {@code SpringManagedTransactionFactory} should be appropriate
-	 * for all cases: be it Spring transaction management, EJB CMT or plain JTA.
-	 * If there is no active transaction, SqlSession operations will execute SQL
-	 * statements non-transactionally.
-	 *
-	 * <b>It is strongly recommended to use the default
-	 * {@code TransactionFactory}.</b> If not used, any attempt at getting an
-	 * SqlSession through Spring's MyBatis framework will throw an exception if
-	 * a transaction is active.
-	 *
-	 * @see SpringManagedTransactionFactory
-	 * @param transactionFactory
-	 *            the MyBatis TransactionFactory
-	 */
-	public void setTransactionFactory(TransactionFactory transactionFactory) {
-		this.transactionFactory = transactionFactory;
-	}
-
-	/**
-	 * <b>NOTE:</b> This class <em>overrides</em> any {@code Environment} you
-	 * have set in the MyBatis config file. This is used only as a placeholder
-	 * name. The default value is
-	 * {@code SqlSessionFactoryBean.class.getSimpleName()}.
-	 *
-	 * @param environment
-	 *            the environment name
-	 */
-	public void setEnvironment(String environment) {
-		this.environment = environment;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public void afterPropertiesSet() throws Exception {
-		notNull(dataSource, "Property 'dataSource' is required");
-		notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
-		state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
-				"Property 'configuration' and 'configLocation' can not specified with together");
-		this.sqlSessionFactory = buildSqlSessionFactory();
-	}
-
-	/**
-	 * Build a {@code SqlSessionFactory} instance.
-	 *
-	 * The default implementation uses the standard MyBatis
-	 * {@code XMLConfigBuilder} API to build a {@code SqlSessionFactory}
-	 * instance based on an Reader. Since 1.3.0, it can be specified a
-	 * {@link Configuration} instance directly(without config file).
-	 *
-	 * @return SqlSessionFactory
-	 * @throws IOException
-	 *             if loading the config file failed
-	 */
-	protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
-
-		Configuration configuration;
-
-		// TODO 加载自定义 MybatisXmlConfigBuilder
-		MybatisXMLConfigBuilder xmlConfigBuilder = null;
-		if (this.configuration != null) {
-			configuration = this.configuration;
-			if (configuration.getVariables() == null) {
-				configuration.setVariables(this.configurationProperties);
-			} else if (this.configurationProperties != null) {
-				configuration.getVariables().putAll(this.configurationProperties);
-			}
-		} else if (this.configLocation != null) {
-			xmlConfigBuilder = new MybatisXMLConfigBuilder(this.configLocation.getInputStream(), null,
-					this.configurationProperties);
-			configuration = xmlConfigBuilder.getConfiguration();
-		} else {
-			if (LOGGER.isDebugEnabled()) {
-				LOGGER.debug("Property 'configuration' or 'configLocation' not specified, using default MyBatisPlus Configuration");
-			}
-			// TODO 使用自定义配置
-			configuration = new MybatisConfiguration();
-			if (this.configurationProperties != null) {
-				configuration.setVariables(this.configurationProperties);
-			}
-		}
-
-		if (this.objectFactory != null) {
-			configuration.setObjectFactory(this.objectFactory);
-		}
-
-		if (this.objectWrapperFactory != null) {
-			configuration.setObjectWrapperFactory(this.objectWrapperFactory);
-		}
-
-		if (this.vfs != null) {
-			configuration.setVfsImpl(this.vfs);
-		}
-
-		if (hasLength(this.typeAliasesPackage)) {
-			// TODO
-			String[] typeAliasPackageArray;
-			if (typeAliasesPackage.contains("*")) {
-				typeAliasPackageArray = PackageHelper.convertTypeAliasesPackage(typeAliasesPackage);
-			} else {
-				typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
-						ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
-			}
-			if (typeAliasPackageArray == null) {
-				throw new MybatisPlusException("not find typeAliasesPackage:" + typeAliasesPackage);
-			}
-			for (String packageToScan : typeAliasPackageArray) {
-				configuration.getTypeAliasRegistry().registerAliases(packageToScan,
-						typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
-				}
-			}
-		}
-
-		if (!isEmpty(this.typeAliases)) {
-			for (Class<?> typeAlias : this.typeAliases) {
-				configuration.getTypeAliasRegistry().registerAlias(typeAlias);
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Registered type alias: '" + typeAlias + "'");
-				}
-			}
-		}
-
-		if (!isEmpty(this.plugins)) {
-			for (Interceptor plugin : this.plugins) {
-				configuration.addInterceptor(plugin);
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Registered plugin: '" + plugin + "'");
-				}
-			}
-		}
-
-		if (hasLength(this.typeHandlersPackage)) {
-			String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,
-					ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
-			for (String packageToScan : typeHandlersPackageArray) {
-				configuration.getTypeHandlerRegistry().register(packageToScan);
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Scanned package: '" + packageToScan + "' for type handlers");
-				}
-			}
-		}
-
-		if (!isEmpty(this.typeHandlers)) {
-			for (TypeHandler<?> typeHandler : this.typeHandlers) {
-				configuration.getTypeHandlerRegistry().register(typeHandler);
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Registered type handler: '" + typeHandler + "'");
-				}
-			}
-		}
-
-		if (this.databaseIdProvider != null) {// fix #64 set databaseId before
-			// parse mapper xmls
-			try {
-				configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
-			} catch (SQLException e) {
-				throw new NestedIOException("Failed getting a databaseId", e);
-			}
-		}
-
-		if (this.cache != null) {
-			configuration.addCache(this.cache);
-		}
-
-		if (xmlConfigBuilder != null) {
-			try {
-				xmlConfigBuilder.parse();
-
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'");
-				}
-			} catch (Exception ex) {
-				throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
-			} finally {
-				ErrorContext.instance().reset();
-			}
-		}
-
-		if (this.transactionFactory == null) {
-			this.transactionFactory = new SpringManagedTransactionFactory();
-		}
-
-		configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource));
-		// 设置元数据相关
-		GlobalConfiguration.setMetaData(dataSource, globalConfig);
-		SqlSessionFactory sqlSessionFactory = this.sqlSessionFactoryBuilder.build(configuration);
-		// TODO SqlRunner
-		SqlRunner.FACTORY = sqlSessionFactory;
-		// TODO 缓存 sqlSessionFactory
-		globalConfig.setSqlSessionFactory(sqlSessionFactory);
-		// TODO 设置全局参数属性
-		globalConfig.signGlobalConfig(sqlSessionFactory);
-
-		if (!isEmpty(this.mapperLocations)) {
-			for (Resource mapperLocation : this.mapperLocations) {
-				if (mapperLocation == null) {
-					continue;
-				}
-
-				try {
-					// TODO
-					MybatisXMLMapperBuilder xmlMapperBuilder = new MybatisXMLMapperBuilder(mapperLocation.getInputStream(),
-							configuration, mapperLocation.toString(), configuration.getSqlFragments());
-					xmlMapperBuilder.parse();
-				} catch (Exception e) {
-					throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
-				} finally {
-					ErrorContext.instance().reset();
-				}
-
-				if (LOGGER.isDebugEnabled()) {
-					LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'");
-				}
-			}
-		} else {
-			if (LOGGER.isDebugEnabled()) {
-				LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");
-			}
-		}
-		return sqlSessionFactory;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public SqlSessionFactory getObject() throws Exception {
-		if (this.sqlSessionFactory == null) {
-			afterPropertiesSet();
-		}
-		return this.sqlSessionFactory;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public Class<? extends SqlSessionFactory> getObjectType() {
-		return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public boolean isSingleton() {
-		return true;
-	}
-
-	/**
-	 * {@inheritDoc}
-	 */
-	public void onApplicationEvent(ApplicationEvent event) {
-		if (failFast && event instanceof ContextRefreshedEvent) {
-			// fail-fast -> check all statements are completed
-			this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
-		}
-	}
+    private Cache cache;
+
+    private ObjectFactory objectFactory;
+
+    private ObjectWrapperFactory objectWrapperFactory;
+
+    private GlobalConfiguration globalConfig = GlobalConfiguration.defaults();
+
+    // TODO 注入全局配置
+    public void setGlobalConfig(GlobalConfiguration globalConfig) {
+        this.globalConfig = globalConfig;
+    }
+
+    /**
+     * Sets the ObjectFactory.
+     *
+     * @since 1.1.2
+     * @param objectFactory
+     */
+    public void setObjectFactory(ObjectFactory objectFactory) {
+        this.objectFactory = objectFactory;
+    }
+
+    /**
+     * Sets the ObjectWrapperFactory.
+     *
+     * @since 1.1.2
+     * @param objectWrapperFactory
+     */
+    public void setObjectWrapperFactory(ObjectWrapperFactory objectWrapperFactory) {
+        this.objectWrapperFactory = objectWrapperFactory;
+    }
+
+    /**
+     * Gets the DatabaseIdProvider
+     *
+     * @since 1.1.0
+     * @return
+     */
+    public DatabaseIdProvider getDatabaseIdProvider() {
+        return databaseIdProvider;
+    }
+
+    /**
+     * Sets the DatabaseIdProvider. As of version 1.2.2 this variable is not
+     * initialized by default.
+     *
+     * @since 1.1.0
+     * @param databaseIdProvider
+     */
+    public void setDatabaseIdProvider(DatabaseIdProvider databaseIdProvider) {
+        this.databaseIdProvider = databaseIdProvider;
+    }
+
+    public Class<? extends VFS> getVfs() {
+        return this.vfs;
+    }
+
+    public void setVfs(Class<? extends VFS> vfs) {
+        this.vfs = vfs;
+    }
+
+    public Cache getCache() {
+        return this.cache;
+    }
+
+    public void setCache(Cache cache) {
+        this.cache = cache;
+    }
+
+    /**
+     * Mybatis plugin list.
+     *
+     * @since 1.0.1
+     *
+     * @param plugins
+     *            list of plugins
+     *
+     */
+    public void setPlugins(Interceptor[] plugins) {
+        this.plugins = plugins;
+    }
+
+    /**
+     * Packages to search for type aliases.
+     *
+     * @since 1.0.1
+     *
+     * @param typeAliasesPackage
+     *            package to scan for domain objects
+     *
+     */
+    public void setTypeAliasesPackage(String typeAliasesPackage) {
+        this.typeAliasesPackage = typeAliasesPackage;
+    }
+
+    /**
+     * Super class which domain objects have to extend to have a type alias
+     * created. No effect if there is no package to scan configured.
+     *
+     * @since 1.1.2
+     *
+     * @param typeAliasesSuperType
+     *            super class for domain objects
+     *
+     */
+    public void setTypeAliasesSuperType(Class<?> typeAliasesSuperType) {
+        this.typeAliasesSuperType = typeAliasesSuperType;
+    }
+
+    /**
+     * Packages to search for type handlers.
+     *
+     * @since 1.0.1
+     *
+     * @param typeHandlersPackage
+     *            package to scan for type handlers
+     *
+     */
+    public void setTypeHandlersPackage(String typeHandlersPackage) {
+        this.typeHandlersPackage = typeHandlersPackage;
+    }
+
+    /**
+     * Set type handlers. They must be annotated with {@code MappedTypes} and
+     * optionally with {@code MappedJdbcTypes}
+     *
+     * @since 1.0.1
+     *
+     * @param typeHandlers
+     *            Type handler list
+     */
+    public void setTypeHandlers(TypeHandler<?>[] typeHandlers) {
+        this.typeHandlers = typeHandlers;
+    }
+
+    /**
+     * List of type aliases to register. They can be annotated with
+     * {@code Alias}
+     *
+     * @since 1.0.1
+     *
+     * @param typeAliases
+     *            Type aliases list
+     */
+    public void setTypeAliases(Class<?>[] typeAliases) {
+        this.typeAliases = typeAliases;
+    }
+
+    /**
+     * If true, a final check is done on Configuration to assure that all mapped
+     * statements are fully loaded and there is no one still pending to resolve
+     * includes. Defaults to false.
+     *
+     * @since 1.0.1
+     *
+     * @param failFast
+     *            enable failFast
+     */
+    public void setFailFast(boolean failFast) {
+        this.failFast = failFast;
+    }
+
+    /**
+     * Set the location of the MyBatis {@code SqlSessionFactory} config file. A
+     * typical value is "WEB-INF/mybatis-configuration.xml".
+     */
+    public void setConfigLocation(Resource configLocation) {
+        this.configLocation = configLocation;
+    }
+
+    /**
+     * Set a customized MyBatis configuration.
+     *
+     * @param configuration
+     *            MyBatis configuration
+     * @since 1.3.0
+     */
+    public void setConfiguration(Configuration configuration) {
+        this.configuration = configuration;
+    }
+
+    /**
+     * Set locations of MyBatis mapper files that are going to be merged into
+     * the {@code SqlSessionFactory} configuration at runtime.
+     *
+     * This is an alternative to specifying "&lt;sqlmapper&gt;" entries in an
+     * MyBatis config file. This property being based on Spring's resource
+     * abstraction also allows for specifying resource patterns here: e.g.
+     * "classpath*:sqlmap/*-mapper.xml".
+     */
+    public void setMapperLocations(Resource[] mapperLocations) {
+        this.mapperLocations = mapperLocations;
+    }
+
+    /**
+     * Set optional properties to be passed into the SqlSession configuration,
+     * as alternative to a {@code &lt;properties&gt;} tag in the configuration
+     * xml file. This will be used to resolve placeholders in the config file.
+     */
+    public void setConfigurationProperties(Properties sqlSessionFactoryProperties) {
+        this.configurationProperties = sqlSessionFactoryProperties;
+    }
+
+    /**
+     * Set the JDBC {@code DataSource} that this instance should manage
+     * transactions for. The {@code DataSource} should match the one used by the
+     * {@code SqlSessionFactory}: for example, you could specify the same JNDI
+     * DataSource for both.
+     *
+     * A transactional JDBC {@code Connection} for this {@code DataSource} will
+     * be provided to application code accessing this {@code DataSource}
+     * directly via {@code DataSourceUtils} or
+     * {@code DataSourceTransactionManager}.
+     *
+     * The {@code DataSource} specified here should be the target
+     * {@code DataSource} to manage transactions for, not a
+     * {@code TransactionAwareDataSourceProxy}. Only data access code may work
+     * with {@code TransactionAwareDataSourceProxy}, while the transaction
+     * manager needs to work on the underlying target {@code DataSource}. If
+     * there's nevertheless a {@code TransactionAwareDataSourceProxy} passed in,
+     * it will be unwrapped to extract its target {@code DataSource}.
+     *
+     */
+    public void setDataSource(DataSource dataSource) {
+        if (dataSource instanceof TransactionAwareDataSourceProxy) {
+            // If we got a TransactionAwareDataSourceProxy, we need to perform
+            // transactions for its underlying target DataSource, else data
+            // access code won't see properly exposed transactions (i.e.
+            // transactions for the target DataSource).
+            this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
+        } else {
+            this.dataSource = dataSource;
+        }
+    }
+
+    /**
+     * Sets the {@code SqlSessionFactoryBuilder} to use when creating the
+     * {@code SqlSessionFactory}.
+     *
+     * This is mainly meant for testing so that mock SqlSessionFactory classes
+     * can be injected. By default, {@code SqlSessionFactoryBuilder} creates
+     * {@code DefaultSqlSessionFactory} instances.
+     *
+     */
+    public void setSqlSessionFactoryBuilder(SqlSessionFactoryBuilder sqlSessionFactoryBuilder) {
+        this.sqlSessionFactoryBuilder = sqlSessionFactoryBuilder;
+    }
+
+    /**
+     * Set the MyBatis TransactionFactory to use. Default is
+     * {@code SpringManagedTransactionFactory}
+     *
+     * The default {@code SpringManagedTransactionFactory} should be appropriate
+     * for all cases: be it Spring transaction management, EJB CMT or plain JTA.
+     * If there is no active transaction, SqlSession operations will execute SQL
+     * statements non-transactionally.
+     *
+     * <b>It is strongly recommended to use the default
+     * {@code TransactionFactory}.</b> If not used, any attempt at getting an
+     * SqlSession through Spring's MyBatis framework will throw an exception if
+     * a transaction is active.
+     *
+     * @see SpringManagedTransactionFactory
+     * @param transactionFactory
+     *            the MyBatis TransactionFactory
+     */
+    public void setTransactionFactory(TransactionFactory transactionFactory) {
+        this.transactionFactory = transactionFactory;
+    }
+
+    /**
+     * <b>NOTE:</b> This class <em>overrides</em> any {@code Environment} you
+     * have set in the MyBatis config file. This is used only as a placeholder
+     * name. The default value is
+     * {@code SqlSessionFactoryBean.class.getSimpleName()}.
+     *
+     * @param environment
+     *            the environment name
+     */
+    public void setEnvironment(String environment) {
+        this.environment = environment;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void afterPropertiesSet() throws Exception {
+        notNull(dataSource, "Property 'dataSource' is required");
+        notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
+        state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
+                "Property 'configuration' and 'configLocation' can not specified with together");
+        this.sqlSessionFactory = buildSqlSessionFactory();
+    }
+
+    /**
+     * Build a {@code SqlSessionFactory} instance.
+     *
+     * The default implementation uses the standard MyBatis
+     * {@code XMLConfigBuilder} API to build a {@code SqlSessionFactory}
+     * instance based on an Reader. Since 1.3.0, it can be specified a
+     * {@link Configuration} instance directly(without config file).
+     *
+     * @return SqlSessionFactory
+     * @throws IOException
+     *             if loading the config file failed
+     */
+    protected SqlSessionFactory buildSqlSessionFactory() throws IOException {
+
+        Configuration configuration;
+
+        // TODO 加载自定义 MybatisXmlConfigBuilder
+        MybatisXMLConfigBuilder xmlConfigBuilder = null;
+        if (this.configuration != null) {
+            configuration = this.configuration;
+            if (configuration.getVariables() == null) {
+                configuration.setVariables(this.configurationProperties);
+            } else if (this.configurationProperties != null) {
+                configuration.getVariables().putAll(this.configurationProperties);
+            }
+        } else if (this.configLocation != null) {
+            xmlConfigBuilder = new MybatisXMLConfigBuilder(this.configLocation.getInputStream(), null,
+                    this.configurationProperties);
+            configuration = xmlConfigBuilder.getConfiguration();
+        } else {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Property 'configuration' or 'configLocation' not specified, using default MyBatisPlus Configuration");
+            }
+            // TODO 使用自定义配置
+            configuration = new MybatisConfiguration();
+            if (this.configurationProperties != null) {
+                configuration.setVariables(this.configurationProperties);
+            }
+        }
+
+        if (this.objectFactory != null) {
+            configuration.setObjectFactory(this.objectFactory);
+        }
+
+        if (this.objectWrapperFactory != null) {
+            configuration.setObjectWrapperFactory(this.objectWrapperFactory);
+        }
+
+        if (this.vfs != null) {
+            configuration.setVfsImpl(this.vfs);
+        }
+
+        if (hasLength(this.typeAliasesPackage)) {
+            // TODO
+            String[] typeAliasPackageArray;
+            if (typeAliasesPackage.contains("*")) {
+                typeAliasPackageArray = PackageHelper.convertTypeAliasesPackage(typeAliasesPackage);
+            } else {
+                typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,
+                        ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
+            }
+            if (typeAliasPackageArray == null) {
+                throw new MybatisPlusException("not find typeAliasesPackage:" + typeAliasesPackage);
+            }
+            for (String packageToScan : typeAliasPackageArray) {
+                configuration.getTypeAliasRegistry().registerAliases(packageToScan,
+                        typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
+                }
+            }
+        }
+
+        if (!isEmpty(this.typeAliases)) {
+            for (Class<?> typeAlias : this.typeAliases) {
+                configuration.getTypeAliasRegistry().registerAlias(typeAlias);
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Registered type alias: '" + typeAlias + "'");
+                }
+            }
+        }
+
+        if (!isEmpty(this.plugins)) {
+            for (Interceptor plugin : this.plugins) {
+                configuration.addInterceptor(plugin);
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Registered plugin: '" + plugin + "'");
+                }
+            }
+        }
+
+        if (hasLength(this.typeHandlersPackage)) {
+            String[] typeHandlersPackageArray = tokenizeToStringArray(this.typeHandlersPackage,
+                    ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
+            for (String packageToScan : typeHandlersPackageArray) {
+                configuration.getTypeHandlerRegistry().register(packageToScan);
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Scanned package: '" + packageToScan + "' for type handlers");
+                }
+            }
+        }
+
+        if (!isEmpty(this.typeHandlers)) {
+            for (TypeHandler<?> typeHandler : this.typeHandlers) {
+                configuration.getTypeHandlerRegistry().register(typeHandler);
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Registered type handler: '" + typeHandler + "'");
+                }
+            }
+        }
+
+        if (this.databaseIdProvider != null) {// fix #64 set databaseId before
+            // parse mapper xmls
+            try {
+                configuration.setDatabaseId(this.databaseIdProvider.getDatabaseId(this.dataSource));
+            } catch (SQLException e) {
+                throw new NestedIOException("Failed getting a databaseId", e);
+            }
+        }
+
+        if (this.cache != null) {
+            configuration.addCache(this.cache);
+        }
+
+        if (xmlConfigBuilder != null) {
+            try {
+                xmlConfigBuilder.parse();
+
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'");
+                }
+            } catch (Exception ex) {
+                throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);
+            } finally {
+                ErrorContext.instance().reset();
+            }
+        }
+
+        if (this.transactionFactory == null) {
+            this.transactionFactory = new SpringManagedTransactionFactory();
+        }
+
+        configuration.setEnvironment(new Environment(this.environment, this.transactionFactory, this.dataSource));
+        // 设置元数据相关
+        GlobalConfiguration.setMetaData(dataSource, globalConfig);
+        SqlSessionFactory sqlSessionFactory = this.sqlSessionFactoryBuilder.build(configuration);
+        // TODO SqlRunner
+        SqlRunner.FACTORY = sqlSessionFactory;
+        // TODO 缓存 sqlSessionFactory
+        globalConfig.setSqlSessionFactory(sqlSessionFactory);
+        // TODO 设置全局参数属性
+        globalConfig.signGlobalConfig(sqlSessionFactory);
+
+        if (!isEmpty(this.mapperLocations)) {
+            for (Resource mapperLocation : this.mapperLocations) {
+                if (mapperLocation == null) {
+                    continue;
+                }
+
+                try {
+                    // TODO
+                    MybatisXMLMapperBuilder xmlMapperBuilder = new MybatisXMLMapperBuilder(mapperLocation.getInputStream(),
+                            configuration, mapperLocation.toString(), configuration.getSqlFragments());
+                    xmlMapperBuilder.parse();
+                } catch (Exception e) {
+                    throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
+                } finally {
+                    ErrorContext.instance().reset();
+                }
+
+                if (LOGGER.isDebugEnabled()) {
+                    LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'");
+                }
+            }
+        } else {
+            if (LOGGER.isDebugEnabled()) {
+                LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");
+            }
+        }
+        return sqlSessionFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public SqlSessionFactory getObject() throws Exception {
+        if (this.sqlSessionFactory == null) {
+            afterPropertiesSet();
+        }
+        return this.sqlSessionFactory;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Class<? extends SqlSessionFactory> getObjectType() {
+        return this.sqlSessionFactory == null ? SqlSessionFactory.class : this.sqlSessionFactory.getClass();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isSingleton() {
+        return true;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void onApplicationEvent(ApplicationEvent event) {
+        if (failFast && event instanceof ContextRefreshedEvent) {
+            // fail-fast -> check all statements are completed
+            this.sqlSessionFactory.getConfiguration().getMappedStatementNames();
+        }
+    }
 
 }

+ 6 - 6
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/ArrayUtils.java

@@ -10,12 +10,12 @@ package com.baomidou.mybatisplus.toolkit;
  */
 public class ArrayUtils {
 
-	public static boolean isEmpty(final Object[] array) {
-		return array == null || array.length == 0;
-	}
+    public static boolean isEmpty(final Object[] array) {
+        return array == null || array.length == 0;
+    }
 
-	public static boolean isNotEmpty(final Object[] array) {
-		return !isEmpty(array);
-	}
+    public static boolean isNotEmpty(final Object[] array) {
+        return !isEmpty(array);
+    }
 
 }

+ 25 - 25
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/CollectionUtils.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -27,28 +27,28 @@ import java.util.Collection;
  */
 public class CollectionUtils {
 
-	/**
-	 * <p>
-	 * 校验集合是否为空
-	 * </p>
-	 *
-	 * @param coll
-	 * @return boolean
-	 */
-	public static boolean isEmpty(Collection<?> coll) {
-		return (coll == null || coll.isEmpty());
-	}
+    /**
+     * <p>
+     * 校验集合是否为空
+     * </p>
+     *
+     * @param coll
+     * @return boolean
+     */
+    public static boolean isEmpty(Collection<?> coll) {
+        return (coll == null || coll.isEmpty());
+    }
 
-	/**
-	 * <p>
-	 * 校验集合是否不为空
-	 * </p>
-	 *
-	 * @param coll
-	 * @return boolean
-	 */
-	public static boolean isNotEmpty(Collection<?> coll) {
-		return !isEmpty(coll);
-	}
+    /**
+     * <p>
+     * 校验集合是否不为空
+     * </p>
+     *
+     * @param coll
+     * @return boolean
+     */
+    public static boolean isNotEmpty(Collection<?> coll) {
+        return !isEmpty(coll);
+    }
 
 }

+ 13 - 13
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/DruidUtils.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -27,15 +27,15 @@ import com.alibaba.druid.sql.PagerUtils;
  */
 public class DruidUtils {
 
-	/**
-	 * 通过Druid方式获取count语句
-	 * 
-	 * @param originalSql
-	 * @param dialectType
-	 * @return
-	 */
-	public static String count(String originalSql, String dialectType) {
-		return PagerUtils.count(originalSql, dialectType);
-	}
+    /**
+     * 通过Druid方式获取count语句
+     *
+     * @param originalSql
+     * @param dialectType
+     * @return
+     */
+    public static String count(String originalSql, String dialectType) {
+        return PagerUtils.count(originalSql, dialectType);
+    }
 
 }

+ 458 - 458
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/IOUtils.java

@@ -44,478 +44,478 @@ import org.apache.ibatis.logging.LogFactory;
  */
 public class IOUtils {
 
-	private static final Log logger = LogFactory.getLog(IOUtils.class);
+    private static final Log logger = LogFactory.getLog(IOUtils.class);
 
-	private IOUtils() {
-	}
+    private IOUtils() {
+    }
 
-	/**
-	 * Closes a URLConnection.
-	 *
-	 * @param conn the connection to close.
-	 * @since 2.4
-	 */
-	public static void close(final URLConnection conn) {
-		if (conn instanceof HttpURLConnection) {
-			((HttpURLConnection) conn).disconnect();
-		}
-	}
+    /**
+     * Closes a URLConnection.
+     *
+     * @param conn the connection to close.
+     * @since 2.4
+     */
+    public static void close(final URLConnection conn) {
+        if (conn instanceof HttpURLConnection) {
+            ((HttpURLConnection) conn).disconnect();
+        }
+    }
 
-	/**
-	 * Closes an <code>Reader</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Reader#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * char[] data = new char[1024];
-	 * Reader in = null;
-	 * try {
-	 * 	in = new FileReader(&quot;foo.txt&quot;);
-	 * 	in.read(data);
-	 * 	in.close(); // close errors are handled
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(in);
-	 * }
-	 * </pre>
-	 *
-	 * @param input the Reader to close, may be null or already closed
-	 */
-	public static void closeQuietly(final Reader input) {
-		closeQuietly((Closeable) input);
-	}
+    /**
+     * Closes an <code>Reader</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Reader#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * char[] data = new char[1024];
+     * Reader in = null;
+     * try {
+     * 	in = new FileReader(&quot;foo.txt&quot;);
+     * 	in.read(data);
+     * 	in.close(); // close errors are handled
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(in);
+     * }
+     * </pre>
+     *
+     * @param input the Reader to close, may be null or already closed
+     */
+    public static void closeQuietly(final Reader input) {
+        closeQuietly((Closeable) input);
+    }
 
-	/**
-	 * Closes an <code>Writer</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Writer#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * Writer out = null;
-	 * try {
-	 * 	out = new StringWriter();
-	 * 	out.write(&quot;Hello World&quot;);
-	 * 	out.close(); // close errors are handled
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(out);
-	 * }
-	 * </pre>
-	 *
-	 * @param output the Writer to close, may be null or already closed
-	 */
-	public static void closeQuietly(final Writer output) {
-		closeQuietly((Closeable) output);
-	}
+    /**
+     * Closes an <code>Writer</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Writer#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * Writer out = null;
+     * try {
+     * 	out = new StringWriter();
+     * 	out.write(&quot;Hello World&quot;);
+     * 	out.close(); // close errors are handled
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(out);
+     * }
+     * </pre>
+     *
+     * @param output the Writer to close, may be null or already closed
+     */
+    public static void closeQuietly(final Writer output) {
+        closeQuietly((Closeable) output);
+    }
 
-	/**
-	 * Closes an <code>InputStream</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. This is typically used in
-	 * finally blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * byte[] data = new byte[1024];
-	 * InputStream in = null;
-	 * try {
-	 * 	in = new FileInputStream(&quot;foo.txt&quot;);
-	 * 	in.read(data);
-	 * 	in.close(); // close errors are handled
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(in);
-	 * }
-	 * </pre>
-	 *
-	 * @param input the InputStream to close, may be null or already closed
-	 */
-	public static void closeQuietly(final InputStream input) {
-		closeQuietly((Closeable) input);
-	}
+    /**
+     * Closes an <code>InputStream</code> unconditionally.
+     * <p>
+     * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored. This is typically used in
+     * finally blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * byte[] data = new byte[1024];
+     * InputStream in = null;
+     * try {
+     * 	in = new FileInputStream(&quot;foo.txt&quot;);
+     * 	in.read(data);
+     * 	in.close(); // close errors are handled
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(in);
+     * }
+     * </pre>
+     *
+     * @param input the InputStream to close, may be null or already closed
+     */
+    public static void closeQuietly(final InputStream input) {
+        closeQuietly((Closeable) input);
+    }
 
-	/**
-	 * Closes an <code>OutputStream</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. This is typically used in
-	 * finally blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * byte[] data = &quot;Hello, World&quot;.getBytes();
-	 * 
-	 * OutputStream out = null;
-	 * try {
-	 * 	out = new FileOutputStream(&quot;foo.txt&quot;);
-	 * 	out.write(data);
-	 * 	out.close(); // close errors are handled
-	 * } catch (IOException e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(out);
-	 * }
-	 * </pre>
-	 *
-	 * @param output the OutputStream to close, may be null or already closed
-	 */
-	public static void closeQuietly(final OutputStream output) {
-		closeQuietly((Closeable) output);
-	}
+    /**
+     * Closes an <code>OutputStream</code> unconditionally.
+     * <p>
+     * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored. This is typically used in
+     * finally blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * byte[] data = &quot;Hello, World&quot;.getBytes();
+     *
+     * OutputStream out = null;
+     * try {
+     * 	out = new FileOutputStream(&quot;foo.txt&quot;);
+     * 	out.write(data);
+     * 	out.close(); // close errors are handled
+     * } catch (IOException e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(out);
+     * }
+     * </pre>
+     *
+     * @param output the OutputStream to close, may be null or already closed
+     */
+    public static void closeQuietly(final OutputStream output) {
+        closeQuietly((Closeable) output);
+    }
 
-	/**
-	 * Closes a <code>Closeable</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 * </p>
-	 * 
-	 * <pre>
-	 * Closeable closeable = null;
-	 * try {
-	 * 	closeable = new FileReader(&quot;foo.txt&quot;);
-	 * 	// process closeable
-	 * 	closeable.close();
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(closeable);
-	 * }
-	 * </pre>
-	 * <p>
-	 * Closing all streams:
-	 * </p>
-	 * 
-	 * <pre>
-	 * try {
-	 * 	return IOUtils.copy(inputStream, outputStream);
-	 * } finally {
-	 * 	IOUtils.closeQuietly(inputStream);
-	 * 	IOUtils.closeQuietly(outputStream);
-	 * }
-	 * </pre>
-	 *
-	 * @param closeable the objects to close, may be null or already closed
-	 * @since 2.0
-	 */
-	public static void closeQuietly(final Closeable closeable) {
-		try {
-			if (closeable != null) {
-				closeable.close();
-			}
-		} catch (final IOException ioe) {
-			logger.error("error close io", ioe);
-		}
-	}
+    /**
+     * Closes a <code>Closeable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * </p>
+     * <p>
+     * <pre>
+     * Closeable closeable = null;
+     * try {
+     * 	closeable = new FileReader(&quot;foo.txt&quot;);
+     * 	// process closeable
+     * 	closeable.close();
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(closeable);
+     * }
+     * </pre>
+     * <p>
+     * Closing all streams:
+     * </p>
+     * <p>
+     * <pre>
+     * try {
+     * 	return IOUtils.copy(inputStream, outputStream);
+     * } finally {
+     * 	IOUtils.closeQuietly(inputStream);
+     * 	IOUtils.closeQuietly(outputStream);
+     * }
+     * </pre>
+     *
+     * @param closeable the objects to close, may be null or already closed
+     * @since 2.0
+     */
+    public static void closeQuietly(final Closeable closeable) {
+        try {
+            if (closeable != null) {
+                closeable.close();
+            }
+        } catch (final IOException ioe) {
+            logger.error("error close io", ioe);
+        }
+    }
 
-	/**
-	 * Closes a <code>Closeable</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
-	 * <p>
-	 * This is typically used in finally blocks to ensure that the closeable is closed even if an Exception was thrown
-	 * before the normal close statement was reached. <br>
-	 * <b>It should not be used to replace the close statement(s) which should be present for the non-exceptional
-	 * case.</b> <br>
-	 * It is only intended to simplify tidying up where normal processing has already failed and reporting close failure
-	 * as well is not necessary or useful.
-	 * <p>
-	 * Example code:
-	 * </p>
-	 * 
-	 * <pre>
-	 * Closeable closeable = null;
-	 * try {
-	 *     closeable = new FileReader(&quot;foo.txt&quot;);
-	 *     // processing using the closeable; may throw an Exception
-	 *     closeable.close(); // Normal close - exceptions not ignored
-	 * } catch (Exception e) {
-	 *     // error handling
-	 * } finally {
-	 *     <b>IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception</b>
-	 * }
-	 * </pre>
-	 * <p>
-	 * Closing all streams: <br>
-	 * 
-	 * <pre>
-	 * try {
-	 * 	return IOUtils.copy(inputStream, outputStream);
-	 * } finally {
-	 * 	IOUtils.closeQuietly(inputStream, outputStream);
-	 * }
-	 * </pre>
-	 *
-	 * @param closeables the objects to close, may be null or already closed
-	 * @see #closeQuietly(Closeable)
-	 * @since 2.5
-	 */
-	public static void closeQuietly(final Closeable... closeables) {
-		if (closeables == null) {
-			return;
-		}
-		for (final Closeable closeable : closeables) {
-			closeQuietly(closeable);
-		}
-	}
+    /**
+     * Closes a <code>Closeable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
+     * <p>
+     * This is typically used in finally blocks to ensure that the closeable is closed even if an Exception was thrown
+     * before the normal close statement was reached. <br>
+     * <b>It should not be used to replace the close statement(s) which should be present for the non-exceptional
+     * case.</b> <br>
+     * It is only intended to simplify tidying up where normal processing has already failed and reporting close failure
+     * as well is not necessary or useful.
+     * <p>
+     * Example code:
+     * </p>
+     * <p>
+     * <pre>
+     * Closeable closeable = null;
+     * try {
+     *     closeable = new FileReader(&quot;foo.txt&quot;);
+     *     // processing using the closeable; may throw an Exception
+     *     closeable.close(); // Normal close - exceptions not ignored
+     * } catch (Exception e) {
+     *     // error handling
+     * } finally {
+     *     <b>IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception</b>
+     * }
+     * </pre>
+     * <p>
+     * Closing all streams: <br>
+     * <p>
+     * <pre>
+     * try {
+     * 	return IOUtils.copy(inputStream, outputStream);
+     * } finally {
+     * 	IOUtils.closeQuietly(inputStream, outputStream);
+     * }
+     * </pre>
+     *
+     * @param closeables the objects to close, may be null or already closed
+     * @see #closeQuietly(Closeable)
+     * @since 2.5
+     */
+    public static void closeQuietly(final Closeable... closeables) {
+        if (closeables == null) {
+            return;
+        }
+        for (final Closeable closeable : closeables) {
+            closeQuietly(closeable);
+        }
+    }
 
-	/**
-	 * Closes a <code>Socket</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Socket#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * Socket socket = null;
-	 * try {
-	 * 	socket = new Socket(&quot;http://www.foo.com/&quot;, 80);
-	 * 	// process socket
-	 * 	socket.close();
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(socket);
-	 * }
-	 * </pre>
-	 *
-	 * @param sock the Socket to close, may be null or already closed
-	 * @since 2.0
-	 */
-	public static void closeQuietly(final Socket sock) {
-		if (sock != null) {
-			try {
-				sock.close();
-			} catch (final IOException ioe) {
-				logger.error("error close io", ioe);
-			}
-		}
-	}
+    /**
+     * Closes a <code>Socket</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Socket#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * Socket socket = null;
+     * try {
+     * 	socket = new Socket(&quot;http://www.foo.com/&quot;, 80);
+     * 	// process socket
+     * 	socket.close();
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(socket);
+     * }
+     * </pre>
+     *
+     * @param sock the Socket to close, may be null or already closed
+     * @since 2.0
+     */
+    public static void closeQuietly(final Socket sock) {
+        if (sock != null) {
+            try {
+                sock.close();
+            } catch (final IOException ioe) {
+                logger.error("error close io", ioe);
+            }
+        }
+    }
 
-	/**
-	 * Closes a <code>Selector</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Selector#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * Selector selector = null;
-	 * try {
-	 * 	selector = Selector.open();
-	 * 	// process socket
-	 * 
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(selector);
-	 * }
-	 * </pre>
-	 *
-	 * @param selector the Selector to close, may be null or already closed
-	 * @since 2.2
-	 */
-	public static void closeQuietly(final Selector selector) {
-		if (selector != null) {
-			try {
-				selector.close();
-			} catch (final IOException ioe) {
-				logger.error("error close io", ioe);
-			}
-		}
-	}
+    /**
+     * Closes a <code>Selector</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Selector#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * Selector selector = null;
+     * try {
+     * 	selector = Selector.open();
+     * 	// process socket
+     *
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(selector);
+     * }
+     * </pre>
+     *
+     * @param selector the Selector to close, may be null or already closed
+     * @since 2.2
+     */
+    public static void closeQuietly(final Selector selector) {
+        if (selector != null) {
+            try {
+                selector.close();
+            } catch (final IOException ioe) {
+                logger.error("error close io", ioe);
+            }
+        }
+    }
 
-	/**
-	 * Closes a <code>ServerSocket</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored. This is typically used in
-	 * finally blocks.
-	 * <p>
-	 * Example code:
-	 * 
-	 * <pre>
-	 * ServerSocket socket = null;
-	 * try {
-	 * 	socket = new ServerSocket();
-	 * 	// process socket
-	 * 	socket.close();
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(socket);
-	 * }
-	 * </pre>
-	 *
-	 * @param sock the ServerSocket to close, may be null or already closed
-	 * @since 2.2
-	 */
-	public static void closeQuietly(final ServerSocket sock) {
-		if (sock != null) {
-			try {
-				sock.close();
-			} catch (final IOException ioe) {
-				logger.error("error close io", ioe);
-			}
-		}
-	}
+    /**
+     * Closes a <code>ServerSocket</code> unconditionally.
+     * <p>
+     * Equivalent to {@link ServerSocket#close()}, except any exceptions will be ignored. This is typically used in
+     * finally blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * ServerSocket socket = null;
+     * try {
+     * 	socket = new ServerSocket();
+     * 	// process socket
+     * 	socket.close();
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(socket);
+     * }
+     * </pre>
+     *
+     * @param sock the ServerSocket to close, may be null or already closed
+     * @since 2.2
+     */
+    public static void closeQuietly(final ServerSocket sock) {
+        if (sock != null) {
+            try {
+                sock.close();
+            } catch (final IOException ioe) {
+                logger.error("error close io", ioe);
+            }
+        }
+    }
 
-	/**
-	 * Closes a <code>Connection</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Connection#close()}, except any exceptions will be ignored. This is typically used in
-	 * finally blocks.
-	 * <p>
-	 * Example code:
-	 *
-	 * <pre>
-	 * Connection conn = null;
-	 * try {
-	 * 	conn = new Connection();
-	 * 	// process close
-	 * 	conn.close();
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(conn);
-	 * }
-	 * </pre>
-	 *
-	 * @param conn the Connection to close, may be null or already closed
-	 * @since 2.2
-	 */
-	public static void closeQuietly(final Connection conn) {
-		if (conn != null) {
-			try {
-				conn.close();
-			} catch (Exception e) {
-				logger.error("error close conn", e);
-			}
-		}
-	}
+    /**
+     * Closes a <code>Connection</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Connection#close()}, except any exceptions will be ignored. This is typically used in
+     * finally blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * Connection conn = null;
+     * try {
+     * 	conn = new Connection();
+     * 	// process close
+     * 	conn.close();
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(conn);
+     * }
+     * </pre>
+     *
+     * @param conn the Connection to close, may be null or already closed
+     * @since 2.2
+     */
+    public static void closeQuietly(final Connection conn) {
+        if (conn != null) {
+            try {
+                conn.close();
+            } catch (Exception e) {
+                logger.error("error close conn", e);
+            }
+        }
+    }
 
-	/**
-	 * Closes a <code>AutoCloseable</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link ResultSet#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 *
-	 * <pre>
-	 * AutoCloseable statement = null;
-	 * try {
-	 * 	statement = new Connection();
-	 * 	// process close
-	 * 	statement.close();
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(conn);
-	 * }
-	 * </pre>
-	 *
-	 * @param resultSet the Connection to close, may be null or already closed
-	 * @since 2.2
-	 */
-	public static void closeQuietly(final ResultSet resultSet) {
-		if (resultSet != null) {
-			try {
-				resultSet.close();
-			} catch (Exception e) {
-				logger.error("error close resultSet", e);
-			}
-		}
-	}
+    /**
+     * Closes a <code>AutoCloseable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link ResultSet#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * AutoCloseable statement = null;
+     * try {
+     * 	statement = new Connection();
+     * 	// process close
+     * 	statement.close();
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(conn);
+     * }
+     * </pre>
+     *
+     * @param resultSet the Connection to close, may be null or already closed
+     * @since 2.2
+     */
+    public static void closeQuietly(final ResultSet resultSet) {
+        if (resultSet != null) {
+            try {
+                resultSet.close();
+            } catch (Exception e) {
+                logger.error("error close resultSet", e);
+            }
+        }
+    }
 
-	/**
-	 * Closes a <code>AutoCloseable</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link Statement#close()}, except any exceptions will be ignored. This is typically used in finally
-	 * blocks.
-	 * <p>
-	 * Example code:
-	 *
-	 * <pre>
-	 * AutoCloseable statement = null;
-	 * try {
-	 * 	statement = new Connection();
-	 * 	// process close
-	 * 	statement.close();
-	 * } catch (Exception e) {
-	 * 	// error handling
-	 * } finally {
-	 * 	IOUtils.closeQuietly(conn);
-	 * }
-	 * </pre>
-	 *
-	 * @param statement the Connection to close, may be null or already closed
-	 * @since 2.2
-	 */
-	public static void closeQuietly(final Statement statement) {
-		if (statement != null) {
-			try {
-				statement.close();
-			} catch (Exception e) {
-				logger.error("error close statement", e);
-			}
-		}
-	}
+    /**
+     * Closes a <code>AutoCloseable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link Statement#close()}, except any exceptions will be ignored. This is typically used in finally
+     * blocks.
+     * <p>
+     * Example code:
+     * <p>
+     * <pre>
+     * AutoCloseable statement = null;
+     * try {
+     * 	statement = new Connection();
+     * 	// process close
+     * 	statement.close();
+     * } catch (Exception e) {
+     * 	// error handling
+     * } finally {
+     * 	IOUtils.closeQuietly(conn);
+     * }
+     * </pre>
+     *
+     * @param statement the Connection to close, may be null or already closed
+     * @since 2.2
+     */
+    public static void closeQuietly(final Statement statement) {
+        if (statement != null) {
+            try {
+                statement.close();
+            } catch (Exception e) {
+                logger.error("error close statement", e);
+            }
+        }
+    }
 
-	/**
-	 * Closes a <code>AutoCloseable</code> unconditionally.
-	 * <p>
-	 * Equivalent to {@link AutoCloseable#close()}, except any exceptions will be ignored.
-	 * <p>
-	 * This is typically used in finally blocks to ensure that the closeable is closed even if an Exception was thrown
-	 * before the normal close statement was reached. <br>
-	 * <b>It should not be used to replace the close statement(s) which should be present for the non-exceptional
-	 * case.</b> <br>
-	 * It is only intended to simplify tidying up where normal processing has already failed and reporting close failure
-	 * as well is not necessary or useful.
-	 * <p>
-	 * Example code:
-	 * </p>
-	 *
-	 * <pre>
-	 * AutoCloseable closeable = null;
-	 * try {
-	 *     closeable = new AutoCloseable();
-	 *     // processing using the closeable; may throw an Exception
-	 *     closeable.close(); // Normal close - exceptions not ignored
-	 * } catch (Exception e) {
-	 *     // error handling
-	 * } finally {
-	 *     <b>IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception</b>
-	 * }
-	 * </pre>
-	 * <p>
-	 * Closing all streams: <br>
-	 *
-	 * @param statements the objects to close, may be null or already closed
-	 * @see #closeQuietly(Statement)
-	 * @since 2.5
-	 */
-	public static void closeQuietly(final Statement... statements) {
-		if (statements == null) {
-			return;
-		}
-		for (final Statement statement : statements) {
-			closeQuietly(statement);
-		}
-	}
+    /**
+     * Closes a <code>AutoCloseable</code> unconditionally.
+     * <p>
+     * Equivalent to {@link AutoCloseable#close()}, except any exceptions will be ignored.
+     * <p>
+     * This is typically used in finally blocks to ensure that the closeable is closed even if an Exception was thrown
+     * before the normal close statement was reached. <br>
+     * <b>It should not be used to replace the close statement(s) which should be present for the non-exceptional
+     * case.</b> <br>
+     * It is only intended to simplify tidying up where normal processing has already failed and reporting close failure
+     * as well is not necessary or useful.
+     * <p>
+     * Example code:
+     * </p>
+     * <p>
+     * <pre>
+     * AutoCloseable closeable = null;
+     * try {
+     *     closeable = new AutoCloseable();
+     *     // processing using the closeable; may throw an Exception
+     *     closeable.close(); // Normal close - exceptions not ignored
+     * } catch (Exception e) {
+     *     // error handling
+     * } finally {
+     *     <b>IOUtils.closeQuietly(closeable); // In case normal close was skipped due to Exception</b>
+     * }
+     * </pre>
+     * <p>
+     * Closing all streams: <br>
+     *
+     * @param statements the objects to close, may be null or already closed
+     * @see #closeQuietly(Statement)
+     * @since 2.5
+     */
+    public static void closeQuietly(final Statement... statements) {
+        if (statements == null) {
+            return;
+        }
+        for (final Statement statement : statements) {
+            closeQuietly(statement);
+        }
+    }
 
 }

+ 18 - 18
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/IdWorker.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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,22 +28,22 @@ import java.util.UUID;
  */
 public class IdWorker {
 
-	/**
-	 * 主机和进程的机器码
-	 */
-	private static Sequence worker = new Sequence();
+    /**
+     * 主机和进程的机器码
+     */
+    private static final Sequence worker = new Sequence();
 
-	public static long getId() {
-		return worker.nextId();
-	}
+    public static long getId() {
+        return worker.nextId();
+    }
 
-	/**
-	 * <p>
-	 * 获取去掉"-" UUID
-	 * </p>
-	 */
-	public static synchronized String get32UUID() {
-		return UUID.randomUUID().toString().replace("-", "");
-	}
+    /**
+     * <p>
+     * 获取去掉"-" UUID
+     * </p>
+     */
+    public static synchronized String get32UUID() {
+        return UUID.randomUUID().toString().replace("-", "");
+    }
 
 }

+ 40 - 40
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/JdbcUtils.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
@@ -21,47 +21,47 @@ import com.baomidou.mybatisplus.enums.DBType;
  * <p>
  * JDBC 工具类
  * </p>
- * 
+ *
  * @author nieqiurong
  * @Date 2016-12-05
  */
 public class JdbcUtils {
 
-	/**
-	 * <p>
-	 * 根据连接地址判断数据库类型
-	 * </p>
-	 * 
-	 * @param jdbcUrl
-	 *            连接地址
-	 * @return
-	 */
-	public static DBType getDbType(String jdbcUrl) {
-		if (StringUtils.isEmpty(jdbcUrl)) {
-			return DBType.MYSQL;
-		}
-		if (jdbcUrl.startsWith("jdbc:mysql:") || jdbcUrl.startsWith("jdbc:cobar:")
-				|| jdbcUrl.startsWith("jdbc:log4jdbc:mysql:")) {
-			return DBType.MYSQL;
-		} else if (jdbcUrl.startsWith("jdbc:oracle:") || jdbcUrl.startsWith("jdbc:log4jdbc:oracle:")) {
-			return DBType.ORACLE;
-		} else if (jdbcUrl.startsWith("jdbc:microsoft:") || jdbcUrl.startsWith("jdbc:log4jdbc:microsoft:")) {
-			return DBType.SQLSERVER;
-		} else if (jdbcUrl.startsWith("jdbc:sqlserver:") || jdbcUrl.startsWith("jdbc:log4jdbc:sqlserver:")) {
-			return DBType.SQLSERVER;
-		} else if (jdbcUrl.startsWith("jdbc:postgresql:") || jdbcUrl.startsWith("jdbc:log4jdbc:postgresql:")) {
-			return DBType.POSTGRE;
-		} else if (jdbcUrl.startsWith("jdbc:hsqldb:") || jdbcUrl.startsWith("jdbc:log4jdbc:hsqldb:")) {
-			return DBType.HSQL;
-		} else if (jdbcUrl.startsWith("jdbc:db2:")) {
-			return DBType.DB2;
-		} else if (jdbcUrl.startsWith("jdbc:sqlite:")) {
-			return DBType.SQLITE;
-		} else if (jdbcUrl.startsWith("jdbc:h2:") || jdbcUrl.startsWith("jdbc:log4jdbc:h2:")) {
-			return DBType.H2;
-		} else {
-			return DBType.OTHER;
-		}
-	}
+    /**
+     * <p>
+     * 根据连接地址判断数据库类型
+     * </p>
+     *
+     * @param jdbcUrl
+     *            连接地址
+     * @return
+     */
+    public static DBType getDbType(String jdbcUrl) {
+        if (StringUtils.isEmpty(jdbcUrl)) {
+            return DBType.MYSQL;
+        }
+        if (jdbcUrl.startsWith("jdbc:mysql:") || jdbcUrl.startsWith("jdbc:cobar:")
+                || jdbcUrl.startsWith("jdbc:log4jdbc:mysql:")) {
+            return DBType.MYSQL;
+        } else if (jdbcUrl.startsWith("jdbc:oracle:") || jdbcUrl.startsWith("jdbc:log4jdbc:oracle:")) {
+            return DBType.ORACLE;
+        } else if (jdbcUrl.startsWith("jdbc:microsoft:") || jdbcUrl.startsWith("jdbc:log4jdbc:microsoft:")) {
+            return DBType.SQLSERVER;
+        } else if (jdbcUrl.startsWith("jdbc:sqlserver:") || jdbcUrl.startsWith("jdbc:log4jdbc:sqlserver:")) {
+            return DBType.SQLSERVER;
+        } else if (jdbcUrl.startsWith("jdbc:postgresql:") || jdbcUrl.startsWith("jdbc:log4jdbc:postgresql:")) {
+            return DBType.POSTGRE;
+        } else if (jdbcUrl.startsWith("jdbc:hsqldb:") || jdbcUrl.startsWith("jdbc:log4jdbc:hsqldb:")) {
+            return DBType.HSQL;
+        } else if (jdbcUrl.startsWith("jdbc:db2:")) {
+            return DBType.DB2;
+        } else if (jdbcUrl.startsWith("jdbc:sqlite:")) {
+            return DBType.SQLITE;
+        } else if (jdbcUrl.startsWith("jdbc:h2:") || jdbcUrl.startsWith("jdbc:log4jdbc:h2:")) {
+            return DBType.H2;
+        } else {
+            return DBType.OTHER;
+        }
+    }
 
 }

+ 65 - 64
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/JsqlParserUtils.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -18,6 +18,8 @@ package com.baomidou.mybatisplus.toolkit;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.baomidou.mybatisplus.entity.CountOptimize;
+
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.Function;
 import net.sf.jsqlparser.expression.LongValue;
@@ -30,8 +32,6 @@ import net.sf.jsqlparser.statement.select.Select;
 import net.sf.jsqlparser.statement.select.SelectExpressionItem;
 import net.sf.jsqlparser.statement.select.SelectItem;
 
-import com.baomidou.mybatisplus.entity.CountOptimize;
-
 /**
  * <p>
  * JsqlParserUtils工具类
@@ -41,65 +41,66 @@ import com.baomidou.mybatisplus.entity.CountOptimize;
  * @Date 2016-11-30
  */
 public class JsqlParserUtils {
-	private static List<SelectItem> countSelectItem = null;
 
-	/**
-	 * jsqlparser方式获取select的count语句
-	 *
-	 * @param originalSql
-	 *            selectSQL
-	 * @return
-	 */
-	public static CountOptimize jsqlparserCount(CountOptimize countOptimize, String originalSql) {
-		String sqlCount;
-		try {
-			Select selectStatement = (Select) CCJSqlParserUtil.parse(originalSql);
-			PlainSelect plainSelect = (PlainSelect) selectStatement.getSelectBody();
-			Distinct distinct = plainSelect.getDistinct();
-			List<Expression> groupBy = plainSelect.getGroupByColumnReferences();
-			// 优化Order by
-			List<OrderByElement> orderBy = plainSelect.getOrderByElements();
-			// 添加包含groupby 不去除orderby
-			if (CollectionUtils.isEmpty(groupBy) && CollectionUtils.isNotEmpty(orderBy)) {
-				plainSelect.setOrderByElements(null);
-				countOptimize.setOrderBy(false);
-			}
-			// 包含 distinct、groupBy不优化
-			if (distinct != null || CollectionUtils.isNotEmpty(groupBy)) {
-				sqlCount = String.format(SqlUtils.SQL_BASE_COUNT, selectStatement.toString());
-				countOptimize.setCountSQL(sqlCount);
-				return countOptimize;
-			}
-			List<SelectItem> selectCount = countSelectItem();
-			plainSelect.setSelectItems(selectCount);
-			sqlCount = selectStatement.toString();
-		} catch (Exception e) {
-			sqlCount = String.format(SqlUtils.SQL_BASE_COUNT, originalSql);
-		}
-		countOptimize.setCountSQL(sqlCount);
-		return countOptimize;
-	}
+    private static List<SelectItem> countSelectItem = null;
+
+    /**
+     * jsqlparser方式获取select的count语句
+     *
+     * @param originalSql
+     *            selectSQL
+     * @return
+     */
+    public static CountOptimize jsqlparserCount(CountOptimize countOptimize, String originalSql) {
+        String sqlCount;
+        try {
+            Select selectStatement = (Select) CCJSqlParserUtil.parse(originalSql);
+            PlainSelect plainSelect = (PlainSelect) selectStatement.getSelectBody();
+            Distinct distinct = plainSelect.getDistinct();
+            List<Expression> groupBy = plainSelect.getGroupByColumnReferences();
+            // 优化Order by
+            List<OrderByElement> orderBy = plainSelect.getOrderByElements();
+            // 添加包含groupby 不去除orderby
+            if (CollectionUtils.isEmpty(groupBy) && CollectionUtils.isNotEmpty(orderBy)) {
+                plainSelect.setOrderByElements(null);
+                countOptimize.setOrderBy(false);
+            }
+            // 包含 distinct、groupBy不优化
+            if (distinct != null || CollectionUtils.isNotEmpty(groupBy)) {
+                sqlCount = String.format(SqlUtils.SQL_BASE_COUNT, selectStatement.toString());
+                countOptimize.setCountSQL(sqlCount);
+                return countOptimize;
+            }
+            List<SelectItem> selectCount = countSelectItem();
+            plainSelect.setSelectItems(selectCount);
+            sqlCount = selectStatement.toString();
+        } catch (Exception e) {
+            sqlCount = String.format(SqlUtils.SQL_BASE_COUNT, originalSql);
+        }
+        countOptimize.setCountSQL(sqlCount);
+        return countOptimize;
+    }
 
-	/**
-	 * 获取jsqlparser中count的SelectItem
-	 *
-	 * @return
-	 */
-	private static List<SelectItem> countSelectItem() {
-		if (CollectionUtils.isNotEmpty(countSelectItem)) {
-			return countSelectItem;
-		}
-		Function function = new Function();
-		function.setName("COUNT");
-		List<Expression> expressions = new ArrayList<Expression>();
-		LongValue longValue = new LongValue(1);
-		ExpressionList expressionList = new ExpressionList();
-		expressions.add(longValue);
-		expressionList.setExpressions(expressions);
-		function.setParameters(expressionList);
-		countSelectItem = new ArrayList<SelectItem>();
-		SelectExpressionItem selectExpressionItem = new SelectExpressionItem(function);
-		countSelectItem.add(selectExpressionItem);
-		return countSelectItem;
-	}
+    /**
+     * 获取jsqlparser中count的SelectItem
+     *
+     * @return
+     */
+    private static List<SelectItem> countSelectItem() {
+        if (CollectionUtils.isNotEmpty(countSelectItem)) {
+            return countSelectItem;
+        }
+        Function function = new Function();
+        function.setName("COUNT");
+        List<Expression> expressions = new ArrayList<Expression>();
+        LongValue longValue = new LongValue(1);
+        ExpressionList expressionList = new ExpressionList();
+        expressions.add(longValue);
+        expressionList.setExpressions(expressions);
+        function.setParameters(expressionList);
+        countSelectItem = new ArrayList<SelectItem>();
+        SelectExpressionItem selectExpressionItem = new SelectExpressionItem(function);
+        countSelectItem.add(selectExpressionItem);
+        return countSelectItem;
+    }
 }

+ 18 - 18
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/MapUtils.java

@@ -10,24 +10,24 @@ import java.util.Map;
  */
 public class MapUtils {
 
-	/**
-	 * 判断Map是否为空
-	 *
-	 * @param map
-	 * @return
-	 */
-	public static boolean isEmpty(Map<?, ?> map) {
-		return (map == null || map.isEmpty());
-	}
+    /**
+     * 判断Map是否为空
+     *
+     * @param map
+     * @return
+     */
+    public static boolean isEmpty(Map<?, ?> map) {
+        return (map == null || map.isEmpty());
+    }
 
-	/**
-	 * 判断Map是否不为空
-	 *
-	 * @param map
-	 * @return
-	 */
-	public static boolean isNotEmpty(Map<?, ?> map) {
-		return !isEmpty(map);
-	}
+    /**
+     * 判断Map是否不为空
+     *
+     * @param map
+     * @return
+     */
+    public static boolean isNotEmpty(Map<?, ?> map) {
+        return !isEmpty(map);
+    }
 
 }

+ 47 - 46
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/PackageHelper.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
@@ -15,7 +15,9 @@
  */
 package com.baomidou.mybatisplus.toolkit;
 
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import java.util.HashSet;
+import java.util.Set;
+
 import org.springframework.core.io.Resource;
 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
 import org.springframework.core.io.support.ResourcePatternResolver;
@@ -24,61 +26,60 @@ import org.springframework.core.type.classreading.MetadataReader;
 import org.springframework.core.type.classreading.MetadataReaderFactory;
 import org.springframework.util.ClassUtils;
 
-import java.util.HashSet;
-import java.util.Set;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
 
 /**
  * <p>
  * 包扫描辅助类
  * </p>
- * 
+ *
  * @author hubin
  * @Date 2016-06-16
  */
 public class PackageHelper {
 
-	/**
-	 * <p>
-	 * 别名通配符设置
-	 * </p>
-	 * <p>
-	 * <property name="typeAliasesPackage" value="com.baomidou.*.entity"/>
-	 * </p>
-	 * 
-	 * @param typeAliasesPackage
-	 *            类别名包路径
-	 * @return
-	 */
-	public static String[] convertTypeAliasesPackage(String typeAliasesPackage) {
-		ResourcePatternResolver resolver = (ResourcePatternResolver) new PathMatchingResourcePatternResolver();
-		MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
-		String pkg = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
-				+ ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/*.class";
+    /**
+     * <p>
+     * 别名通配符设置
+     * </p>
+     * <p>
+     * <property name="typeAliasesPackage" value="com.baomidou.*.entity"/>
+     * </p>
+     *
+     * @param typeAliasesPackage
+     *            类别名包路径
+     * @return
+     */
+    public static String[] convertTypeAliasesPackage(String typeAliasesPackage) {
+        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+        MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory(resolver);
+        String pkg = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+                + ClassUtils.convertClassNameToResourcePath(typeAliasesPackage) + "/*.class";
 
 		/*
-		 * 将加载多个绝对匹配的所有Resource
+         * 将加载多个绝对匹配的所有Resource
 		 * 将首先通过ClassLoader.getResource("META-INF")加载非模式路径部分,然后进行遍历模式匹配,排除重复包路径
 		 */
-		try {
-			Set<String> set = new HashSet<String>();
-			Resource[] resources = resolver.getResources(pkg);
-			if (resources != null && resources.length > 0) {
-				MetadataReader metadataReader;
-				for (Resource resource : resources) {
-					if (resource.isReadable()) {
-						metadataReader = metadataReaderFactory.getMetadataReader(resource);
-						set.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
-					}
-				}
-			}
-			if (!set.isEmpty()) {
-				return set.toArray(new String[] {});
-			} else {
-				throw new MybatisPlusException("not find typeAliasesPackage:" + pkg);
-			}
-		} catch (Exception e) {
-			throw new MybatisPlusException("not find typeAliasesPackage:" + pkg, e);
-		}
-	}
+        try {
+            Set<String> set = new HashSet<String>();
+            Resource[] resources = resolver.getResources(pkg);
+            if (resources != null && resources.length > 0) {
+                MetadataReader metadataReader;
+                for (Resource resource : resources) {
+                    if (resource.isReadable()) {
+                        metadataReader = metadataReaderFactory.getMetadataReader(resource);
+                        set.add(Class.forName(metadataReader.getClassMetadata().getClassName()).getPackage().getName());
+                    }
+                }
+            }
+            if (!set.isEmpty()) {
+                return set.toArray(new String[]{});
+            } else {
+                throw new MybatisPlusException("not find typeAliasesPackage:" + pkg);
+            }
+        } catch (Exception e) {
+            throw new MybatisPlusException("not find typeAliasesPackage:" + pkg, e);
+        }
+    }
 
 }

+ 13 - 13
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/PluginUtils.java

@@ -7,23 +7,23 @@ import org.apache.ibatis.reflection.SystemMetaObject;
 
 /**
  * 插件工具类
- * 
+ *
  * @author TaoYu
  */
 public final class PluginUtils {
 
-	private PluginUtils() {
-	}
+    private PluginUtils() {
+    }
 
-	/**
-	 * 获得真正的处理对象,可能多层代理.
-	 */
-	public static Object realTarget(Object target) {
-		if (Proxy.isProxyClass(target.getClass())) {
-			MetaObject mo = SystemMetaObject.forObject(target);
-			return realTarget(mo.getValue("h.target"));
-		}
-		return target;
-	}
+    /**
+     * 获得真正的处理对象,可能多层代理.
+     */
+    public static Object realTarget(Object target) {
+        if (Proxy.isProxyClass(target.getClass())) {
+            MetaObject mo = SystemMetaObject.forObject(target);
+            return realTarget(mo.getValue("h.target"));
+        }
+        return target;
+    }
 
 }

+ 182 - 191
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/ReflectionKit.java

@@ -15,13 +15,6 @@
  */
 package com.baomidou.mybatisplus.toolkit;
 
-import com.baomidou.mybatisplus.entity.TableFieldInfo;
-import com.baomidou.mybatisplus.entity.TableInfo;
-import com.baomidou.mybatisplus.enums.FieldStrategy;
-import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
-import org.apache.ibatis.logging.Log;
-import org.apache.ibatis.logging.LogFactory;
-
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -34,6 +27,14 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
+
+import com.baomidou.mybatisplus.entity.TableFieldInfo;
+import com.baomidou.mybatisplus.entity.TableInfo;
+import com.baomidou.mybatisplus.enums.FieldStrategy;
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+
 /**
  * <p>
  * 反射工具类
@@ -44,190 +45,180 @@ import java.util.Map;
  */
 public class ReflectionKit {
 
-	private static final Log logger = LogFactory.getLog(ReflectionKit.class);
-
-	/**
-	 * <p>
-	 * 反射 method 方法名,例如 getId
-	 * </p>
-	 *
-	 * @param field
-	 * @param str
-	 *            属性字符串内容
-	 * @return
-	 */
-	public static String getMethodCapitalize(Field field, final String str) {
-		Class<?> fieldType = field.getType();
-		// fix #176
-		return StringUtils.concatCapitalize(boolean.class.equals(fieldType) ? "is" : "get", str);
-	}
-
-	/**
-	 * 获取 public get方法的值
-	 *
-	 * @param cls
-	 * @param entity
-	 *            实体
-	 * @param str
-	 *            属性字符串内容
-	 * @return Object
-	 */
-	public static Object getMethodValue(Class<?> cls, Object entity, String str) {
-		Map<String, Field> fieldMaps = getFieldMap(cls);
-		try {
-			if (MapUtils.isEmpty(fieldMaps)) {
-				throw new MybatisPlusException(
-						String.format("Error: NoSuchField in %s for %s.  Cause:", cls.getSimpleName(), str));
-			}
-			Method method = cls.getMethod(getMethodCapitalize(fieldMaps.get(str), str));
-			return method.invoke(entity);
-		} catch (NoSuchMethodException e) {
-			throw new MybatisPlusException(String.format("Error: NoSuchMethod in %s.  Cause:", cls.getSimpleName()) + e);
-		} catch (IllegalAccessException e) {
-			throw new MybatisPlusException(String.format("Error: Cannot execute a private method. in %s.  Cause:",
-					cls.getSimpleName())
-					+ e);
-		} catch (InvocationTargetException e) {
-			throw new MybatisPlusException("Error: InvocationTargetException on getMethodValue.  Cause:" + e);
-		}
-	}
-
-	/**
-	 * 获取 public get方法的值
-	 *
-	 * @param entity
-	 *            实体
-	 * @param str
-	 *            属性字符串内容
-	 * @return Object
-	 */
-	public static Object getMethodValue(Object entity, String str) {
-		if (null == entity) {
-			return null;
-		}
-		return getMethodValue(entity.getClass(), entity, str);
-	}
-
-	/**
-	 * 调用对象的get方法检查对象所有属性是否为null
-	 *
-	 * @param bean
-	 *            检查对象
-	 * @return boolean true对象所有属性不为null,false对象所有属性为null
-	 */
-	public static boolean checkFieldValueNotNull(Object bean) {
-		if (null == bean) {
-			return false;
-		}
-		Class<?> cls = bean.getClass();
-		TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
-		if (null == tableInfo) {
-			throw new MybatisPlusException(String.format("Error: Could Not find %s in TableInfo Cache. ", cls.getSimpleName()));
-		}
-		boolean result = false;
-		List<TableFieldInfo> fieldList = tableInfo.getFieldList();
-		for (TableFieldInfo tableFieldInfo : fieldList) {
-			FieldStrategy fieldStrategy = tableFieldInfo.getFieldStrategy();
-			Object val = getMethodValue(cls, bean, tableFieldInfo.getProperty());
-			if (FieldStrategy.NOT_EMPTY.equals(fieldStrategy)) {
-				if (StringUtils.checkValNotNull(val)) {
-					result = true;
-					break;
-				}
-			} else {
-				if (null != val) {
-					result = true;
-					break;
-				}
-			}
-
-		}
-		return result;
-	}
-
-	/**
-	 * 反射对象获取泛型
-	 *
-	 * @param clazz
-	 *            对象
-	 * @param index
-	 *            泛型所在位置
-	 * @return Class
-	 */
-	@SuppressWarnings("rawtypes")
-	public static Class getSuperClassGenricType(final Class clazz, final int index) {
-
-		Type genType = clazz.getGenericSuperclass();
-
-		if (!(genType instanceof ParameterizedType)) {
-			logger.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
-			return Object.class;
-		}
-
-		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
-
-		if (index >= params.length || index < 0) {
-			logger.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index, clazz.getSimpleName(),
-					params.length));
-			return Object.class;
-		}
-		if (!(params[index] instanceof Class)) {
-			logger.warn(String.format("Warn: %s not set the actual class on superclass generic parameter", clazz.getSimpleName()));
-			return Object.class;
-		}
-
-		return (Class) params[index];
-	}
-
-	/**
-	 * 获取该类的所有属性列表
-	 *
-	 * @param clazz
-	 *            反射类
-	 * @return
-	 */
-	public static Map<String, Field> getFieldMap(Class<?> clazz) {
-		List<Field> fieldList = getFieldList(clazz);
-		Map<String, Field> fieldMap = Collections.emptyMap();
-		if (CollectionUtils.isNotEmpty(fieldList)) {
-			fieldMap = new LinkedHashMap<String, Field>();
-			for (Field field : fieldList) {
-				fieldMap.put(field.getName(), field);
-			}
-		}
-		return fieldMap;
-	}
-
-	/**
-	 * 获取该类的所有属性列表
-	 *
-	 * @param clazz
-	 *            反射类
-	 * @return
-	 */
-	public static List<Field> getFieldList(Class<?> clazz) {
-		if (null == clazz) {
-			return null;
-		}
-		List<Field> fieldList = new LinkedList<Field>();
-		Field[] fields = clazz.getDeclaredFields();
-		for (Field field : fields) {
-			/* 过滤静态属性 */
-			if (Modifier.isStatic(field.getModifiers())) {
-				continue;
-			}
+    private static final Log logger = LogFactory.getLog(ReflectionKit.class);
+
+    /**
+     * <p>
+     * 反射 method 方法名,例如 getId
+     * </p>
+     *
+     * @param field
+     * @param str   属性字符串内容
+     * @return
+     */
+    public static String getMethodCapitalize(Field field, final String str) {
+        Class<?> fieldType = field.getType();
+        // fix #176
+        return StringUtils.concatCapitalize(boolean.class.equals(fieldType) ? "is" : "get", str);
+    }
+
+    /**
+     * 获取 public get方法的值
+     *
+     * @param cls
+     * @param entity 实体
+     * @param str    属性字符串内容
+     * @return Object
+     */
+    public static Object getMethodValue(Class<?> cls, Object entity, String str) {
+        Map<String, Field> fieldMaps = getFieldMap(cls);
+        try {
+            if (MapUtils.isEmpty(fieldMaps)) {
+                throw new MybatisPlusException(
+                        String.format("Error: NoSuchField in %s for %s.  Cause:", cls.getSimpleName(), str));
+            }
+            Method method = cls.getMethod(getMethodCapitalize(fieldMaps.get(str), str));
+            return method.invoke(entity);
+        } catch (NoSuchMethodException e) {
+            throw new MybatisPlusException(String.format("Error: NoSuchMethod in %s.  Cause:", cls.getSimpleName()) + e);
+        } catch (IllegalAccessException e) {
+            throw new MybatisPlusException(String.format("Error: Cannot execute a private method. in %s.  Cause:",
+                    cls.getSimpleName())
+                    + e);
+        } catch (InvocationTargetException e) {
+            throw new MybatisPlusException("Error: InvocationTargetException on getMethodValue.  Cause:" + e);
+        }
+    }
+
+    /**
+     * 获取 public get方法的值
+     *
+     * @param entity 实体
+     * @param str    属性字符串内容
+     * @return Object
+     */
+    public static Object getMethodValue(Object entity, String str) {
+        if (null == entity) {
+            return null;
+        }
+        return getMethodValue(entity.getClass(), entity, str);
+    }
+
+    /**
+     * 调用对象的get方法检查对象所有属性是否为null
+     *
+     * @param bean 检查对象
+     * @return boolean true对象所有属性不为null,false对象所有属性为null
+     */
+    public static boolean checkFieldValueNotNull(Object bean) {
+        if (null == bean) {
+            return false;
+        }
+        Class<?> cls = bean.getClass();
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(cls);
+        if (null == tableInfo) {
+            throw new MybatisPlusException(String.format("Error: Could Not find %s in TableInfo Cache. ", cls.getSimpleName()));
+        }
+        boolean result = false;
+        List<TableFieldInfo> fieldList = tableInfo.getFieldList();
+        for (TableFieldInfo tableFieldInfo : fieldList) {
+            FieldStrategy fieldStrategy = tableFieldInfo.getFieldStrategy();
+            Object val = getMethodValue(cls, bean, tableFieldInfo.getProperty());
+            if (FieldStrategy.NOT_EMPTY.equals(fieldStrategy)) {
+                if (StringUtils.checkValNotNull(val)) {
+                    result = true;
+                    break;
+                }
+            } else {
+                if (null != val) {
+                    result = true;
+                    break;
+                }
+            }
+
+        }
+        return result;
+    }
+
+    /**
+     * 反射对象获取泛型
+     *
+     * @param clazz 对象
+     * @param index 泛型所在位置
+     * @return Class
+     */
+    @SuppressWarnings("rawtypes")
+    public static Class getSuperClassGenricType(final Class clazz, final int index) {
+
+        Type genType = clazz.getGenericSuperclass();
+
+        if (!(genType instanceof ParameterizedType)) {
+            logger.warn(String.format("Warn: %s's superclass not ParameterizedType", clazz.getSimpleName()));
+            return Object.class;
+        }
+
+        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+        if (index >= params.length || index < 0) {
+            logger.warn(String.format("Warn: Index: %s, Size of %s's Parameterized Type: %s .", index, clazz.getSimpleName(),
+                    params.length));
+            return Object.class;
+        }
+        if (!(params[index] instanceof Class)) {
+            logger.warn(String.format("Warn: %s not set the actual class on superclass generic parameter", clazz.getSimpleName()));
+            return Object.class;
+        }
+
+        return (Class) params[index];
+    }
+
+    /**
+     * 获取该类的所有属性列表
+     *
+     * @param clazz 反射类
+     * @return
+     */
+    public static Map<String, Field> getFieldMap(Class<?> clazz) {
+        List<Field> fieldList = getFieldList(clazz);
+        Map<String, Field> fieldMap = Collections.emptyMap();
+        if (CollectionUtils.isNotEmpty(fieldList)) {
+            fieldMap = new LinkedHashMap<String, Field>();
+            for (Field field : fieldList) {
+                fieldMap.put(field.getName(), field);
+            }
+        }
+        return fieldMap;
+    }
+
+    /**
+     * 获取该类的所有属性列表
+     *
+     * @param clazz 反射类
+     * @return
+     */
+    public static List<Field> getFieldList(Class<?> clazz) {
+        if (null == clazz) {
+            return null;
+        }
+        List<Field> fieldList = new LinkedList<Field>();
+        Field[] fields = clazz.getDeclaredFields();
+        for (Field field : fields) {
+            /* 过滤静态属性 */
+            if (Modifier.isStatic(field.getModifiers())) {
+                continue;
+            }
 			/* 过滤 transient关键字修饰的属性 */
-			if (Modifier.isTransient(field.getModifiers())) {
-				continue;
-			}
-			fieldList.add(field);
-		}
+            if (Modifier.isTransient(field.getModifiers())) {
+                continue;
+            }
+            fieldList.add(field);
+        }
 		/* 处理父类字段 */
-		Class<?> superClass = clazz.getSuperclass();
-		if (superClass.equals(Object.class)) {
-			return fieldList;
-		}
-		fieldList.addAll(getFieldList(superClass));
-		return fieldList;
-	}
+        Class<?> superClass = clazz.getSuperclass();
+        if (superClass.equals(Object.class)) {
+            return fieldList;
+        }
+        fieldList.addAll(getFieldList(superClass));
+        return fieldList;
+    }
 }

+ 125 - 124
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/Sequence.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -35,131 +35,132 @@ import com.baomidou.mybatisplus.plugins.SqlExplainInterceptor;
  * @date 2016-08-18
  */
 public class Sequence {
-	private static final Log logger = LogFactory.getLog(SqlExplainInterceptor.class);
-
-	/* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) */
-	private final long twepoch = 1288834974657L;
-	private final long workerIdBits = 5L;/* 机器标识位数 */
-	private final long datacenterIdBits = 5L;
-	private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
-	private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
-	private final long sequenceBits = 12L;/* 毫秒内自增位 */
-	private final long workerIdShift = sequenceBits;
-	private final long datacenterIdShift = sequenceBits + workerIdBits;
-	/* 时间戳左移动位 */
-	private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
-	private final long sequenceMask = -1L ^ (-1L << sequenceBits);
-
-	private long workerId;
-
-	/* 数据标识id部分 */
-	private long datacenterId;
-	private long sequence = 0L;/* 0,并发控制 */
-	private long lastTimestamp = -1L;/* 上次生产id时间戳 */
-
-	public Sequence() {
-		this.datacenterId = getDatacenterId(maxDatacenterId);
-		this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
-	}
-
-	/**
-	 * @param workerId
-	 *            工作机器ID
-	 * @param datacenterId
-	 *            序列号
-	 */
-	public Sequence(long workerId, long datacenterId) {
-		if (workerId > maxWorkerId || workerId < 0) {
-			throw new MybatisPlusException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
-		}
-		if (datacenterId > maxDatacenterId || datacenterId < 0) {
-			throw new MybatisPlusException(
-					String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
-		}
-		this.workerId = workerId;
-		this.datacenterId = datacenterId;
-	}
-
-	/**
-	 * 获取下一个ID
-	 *
-	 * @return
-	 */
-	public synchronized long nextId() {
-		long timestamp = timeGen();
-		if (timestamp < lastTimestamp) {
-			throw new MybatisPlusException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
-					lastTimestamp - timestamp));
-		}
-		if (lastTimestamp == timestamp) {
-			sequence = (sequence + 1) & sequenceMask;
-			if (sequence == 0) {
-				timestamp = tilNextMillis(lastTimestamp);
-			}
-		} else {
-			sequence = 0L;
-		}
-
-		lastTimestamp = timestamp;
-
-		return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift)
-				| sequence;
-	}
-
-	protected long tilNextMillis(long lastTimestamp) {
-		long timestamp = timeGen();
-		while (timestamp <= lastTimestamp) {
-			timestamp = timeGen();
-		}
-		return timestamp;
-	}
-
-	protected long timeGen() {
-		return SystemClock.now();
-	}
-
-	/**
-	 * <p>
-	 * 获取 maxWorkerId
-	 * </p>
-	 */
-	protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
-		StringBuffer mpid = new StringBuffer();
-		mpid.append(datacenterId);
-		String name = ManagementFactory.getRuntimeMXBean().getName();
-		if (StringUtils.isNotEmpty(name)) {
-			/*
+
+    private static final Log logger = LogFactory.getLog(SqlExplainInterceptor.class);
+
+    /* 时间起始标记点,作为基准,一般取系统的最近时间(一旦确定不能变动) */
+    private final long twepoch = 1288834974657L;
+    private final long workerIdBits = 5L;/* 机器标识位数 */
+    private final long datacenterIdBits = 5L;
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+    private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
+    private final long sequenceBits = 12L;/* 毫秒内自增位 */
+    private final long workerIdShift = sequenceBits;
+    private final long datacenterIdShift = sequenceBits + workerIdBits;
+    /* 时间戳左移动位 */
+    private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    private long workerId;
+
+    /* 数据标识id部分 */
+    private long datacenterId;
+    private long sequence = 0L;/* 0,并发控制 */
+    private long lastTimestamp = -1L;/* 上次生产id时间戳 */
+
+    public Sequence() {
+        this.datacenterId = getDatacenterId(maxDatacenterId);
+        this.workerId = getMaxWorkerId(datacenterId, maxWorkerId);
+    }
+
+    /**
+     * @param workerId
+     *            工作机器ID
+     * @param datacenterId
+     *            序列号
+     */
+    public Sequence(long workerId, long datacenterId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new MybatisPlusException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
+        }
+        if (datacenterId > maxDatacenterId || datacenterId < 0) {
+            throw new MybatisPlusException(
+                    String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
+        }
+        this.workerId = workerId;
+        this.datacenterId = datacenterId;
+    }
+
+    /**
+     * <p>
+     * 获取 maxWorkerId
+     * </p>
+     */
+    protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) {
+        StringBuffer mpid = new StringBuffer();
+        mpid.append(datacenterId);
+        String name = ManagementFactory.getRuntimeMXBean().getName();
+        if (StringUtils.isNotEmpty(name)) {
+            /*
 			 * GET jvmPid
 			 */
-			mpid.append(name.split("@")[0]);
-		}
+            mpid.append(name.split("@")[0]);
+        }
 		/*
 		 * MAC + PID 的 hashcode 获取16个低位
 		 */
-		return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
-	}
-
-	/**
-	 * <p>
-	 * 数据标识id部分
-	 * </p>
-	 */
-	protected static long getDatacenterId(long maxDatacenterId) {
-		long id = 0L;
-		try {
-			InetAddress ip = InetAddress.getLocalHost();
-			NetworkInterface network = NetworkInterface.getByInetAddress(ip);
-			if (network == null) {
-				id = 1L;
-			} else {
-				byte[] mac = network.getHardwareAddress();
-				id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
-				id = id % (maxDatacenterId + 1);
-			}
-		} catch (Exception e) {
-			logger.warn(" getDatacenterId: " + e.getMessage());
-		}
-		return id;
-	}
+        return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
+    }
+
+    /**
+     * <p>
+     * 数据标识id部分
+     * </p>
+     */
+    protected static long getDatacenterId(long maxDatacenterId) {
+        long id = 0L;
+        try {
+            InetAddress ip = InetAddress.getLocalHost();
+            NetworkInterface network = NetworkInterface.getByInetAddress(ip);
+            if (network == null) {
+                id = 1L;
+            } else {
+                byte[] mac = network.getHardwareAddress();
+                id = ((0x000000FF & (long) mac[mac.length - 1]) | (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
+                id = id % (maxDatacenterId + 1);
+            }
+        } catch (Exception e) {
+            logger.warn(" getDatacenterId: " + e.getMessage());
+        }
+        return id;
+    }
+
+    /**
+     * 获取下一个ID
+     *
+     * @return
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        if (timestamp < lastTimestamp) {
+            throw new MybatisPlusException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds",
+                    lastTimestamp - timestamp));
+        }
+        if (lastTimestamp == timestamp) {
+            sequence = (sequence + 1) & sequenceMask;
+            if (sequence == 0) {
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        } else {
+            sequence = 0L;
+        }
+
+        lastTimestamp = timestamp;
+
+        return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift)
+                | sequence;
+    }
+
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    protected long timeGen() {
+        return SystemClock.now();
+    }
 
 }

+ 315 - 339
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlFormatter.java

@@ -14,351 +14,327 @@ import java.util.StringTokenizer;
 
 /**
  * Performs formatting of basic SQL statements (DML + query).
- * <P>
+ * <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 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();
-		}
-
-		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 final String WHITESPACE = " \n\r\f\t";
+    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>();
+    private static final String INDENT_STRING = "    ";
+    private static final String INITIAL = "\n    ";
+
+    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");
+    }
+
+    public String format(String source) {
+        return new FormatProcess(source).perform();
+    }
+
+    private static class FormatProcess {
+
+        boolean beginLine = true;
+        boolean afterBeginBeforeEnd;
+        boolean afterByOrSetOrFromOrSelect;
+        boolean afterOn;
+        boolean afterBetween;
+        boolean afterInsert;
+        int inFunction;
+        int parensSinceSelect;
+        int indent = 1;
+        StringBuilder result = new StringBuilder();
+        StringTokenizer tokens;
+        String lastToken;
+        String token;
+        String lcToken;
+        private LinkedList<Integer> parenCounts = new LinkedList<Integer>();
+        private LinkedList<Boolean> afterByOrFromOrSelects = new LinkedList<Boolean>();
+
+        public FormatProcess(String sql) {
+            tokens = new StringTokenizer(sql, "()+*/-=<>'`\"[]," + WHITESPACE, true);
+        }
+
+        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);
+        }
+
+        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();
+        }
+
+        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 void newline() {
+            result.append("\n");
+            for (int i = 0; i < indent; i++) {
+                result.append(INDENT_STRING);
+            }
+            beginLine = true;
+        }
+    }
 
 }

+ 150 - 150
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlReservedWords.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -15,12 +15,12 @@
  */
 package com.baomidou.mybatisplus.toolkit;
 
-import com.baomidou.mybatisplus.entity.GlobalConfiguration;
-
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
+import com.baomidou.mybatisplus.entity.GlobalConfiguration;
+
 /**
  * <p>
  * 数据库保留字转义处理类
@@ -31,156 +31,156 @@ import java.util.Set;
  */
 public class SqlReservedWords {
 
-	public static final Set<String> RESERVED_WORDS;
+    public static final Set<String> RESERVED_WORDS;
 
-	static {
-		String[] words = { "AUDIT", "VOLUMES", "MINVALUE", "STATIC", "FLOOR", "CATALOG", "YEAR", "TRIGGER_CATALOG", "WLM",
-				"DISCONNECT", "PARTITION", "LEFT", " MODE", "SEARCH", "CURRENT_PATH", "DAYOFYEAR", "SIZE", "RESTRICT", "RELEASE",
-				"WHERE", "POSTFIX", "SQLWARNING", "UID", "AS", "AT", "SYSID", "DATABASE", "SPECIFIC_NAME", "TIMEZONE_MINUTE",
-				"LC_CTYPE", "ATTRIBUTES", "LOCATION", "A", "DOMAIN", "C", "SET", " INCREMENT", "MERGE", "G", "DAYS", "HEADER",
-				"K", "CONSTRAINT", "M", "PRECISION", "ROLE", "COLLATION_NAME", "BY", "STRAIGHT_JOIN", "CHARACTER", "INSTEAD",
-				"DUAL", "DSNHATTR", "BERNOULLI", " ADD", "CLUSTERED", "CONTINUE", "DIV", "OPERATOR", "SETS", "SECURITY",
-				"CURRENT_LC_CTYPE", "TRUNCATE", "CURSOR", "SQL_LOW_PRIORITY_UPDATES", "CONSTRAINT_SCHEMA", "STATEMENT",
-				"TABLE_NAME", "NODENUMBER", "DO", "RECOVERY", "LOW_PRIORITY", "ADMIN", "ESCAPED", "CAPTURE", "ALLOW", "VARYING",
-				"DISABLE", "STRICT", "SQL_BIG_RESULT", "ABORT", "FOR", "IMPLICIT", "USING", "EXEC", "DEFERRABLE", "RAISERROR",
-				"USER_DEFINED_TYPE_NAME", "VALIDATOR", "UNDO", "STATE", "WITHIN", "NCHAR", "ABSOLUTE", "PREORDER", "SCHEMA",
-				"SEQUENCE", "ASSIGNMENT", "COLUMNS", "END-EXEC1", "GO", "ROW_NUMBER", "BIT", "INTERSECT", "SYSDATE", "WITH",
-				"CLASS_ORIGIN", "ACTION", "ISNULL", "VALIDATE", " COMPRESS", "START", "CHARACTER_LENGTH", "BULK", "EVERY",
-				"NULLIF", "CEIL", "FLUSH", "MIN_ROWS", "GRANTED", "IF", "BIT_LENGTH", "PARAMETER", "CHARACTER_SET_SCHEMA",
-				"DEFINITION", "NCLOB", "FIELDS", "IN", "DISTINCT", "STYLE", "IS", "MASTER_BIND", "REGR_INTERCEPT", "TERMINATE",
-				"FORCE", "FENCED", " IMMEDIATE", "MAP", "READTEXT", "SYSFUN", "EXIT", "DBCC", "OPENROWSET", "COLLATION", "GOTO",
-				"RAID0", "MAX", "CASCADE", "DELIMITERS", "TRANSACTION", "SECQTY", "IGNORE", "COMMENT", "OFF", "CHARACTERS",
-				"IDENTITYCOL", "USAGE", "UPDATE", "SAVE", "REQUIRE", "DISTINCTROW", "USE", "RETURNS", "LOCATORS",
-				"CHARACTERISTICS", "FIRST", "LINENO", "ONLINE", "SELECT", "EXCLUDING", "TABLES", "OUTFILE", "ERASE", "GREATEST",
-				"UTC_DATE", "VARCHARACTER", "INVOKER", "STOGROUP", "DEPTH", "CURRENT_USER", "LN", "ARRAY", "ATOMIC", " ALTER",
-				"COLUMN_NAME", "COLUMN", "MODE", " COMMENT", "DECIMAL", "RESET", "NEW_TABLE", "ROUTINE_NAME", "COMPRESS",
-				"OVERLAY", "READ_WRITE", "COALESCE", "STATUS", " EXCLUSIVE", "UNBOUNDED", "REGR_SLOPE", "CORRESPONDING",
-				"TIMESTAMP", "MESSAGE_OCTET_LENGTH", "SQL_LOG_OFF", "RETURNED_LENGTH", "DISALLOW", "PRIVILEGES", "SQL", "READ",
-				" IDENTIFIED", "REAL", "LESS", "DIAGNOSTICS", "QUERYNO", "NO", "FLOAT", "COMMAND_FUNCTION_CODE",
-				"CURRENT_TIMESTAMP", "TIES", "ROUTINE", "SUBLIST", "FOLLOWING", "ROLLBACK", "MEMBER", "DSSIZE", "DUMP",
-				"EXTERNAL", "GROUPING", "OF", "CHANGE", "RECHECK", " NUMBER", "ON", "DBINFO", "OR", "EQUALS", "CREATEROLE",
-				"PRIMARY", "SSL", "MATCHED", "DAYOFWEEK", "DYNAMIC_FUNCTION_CODE", "ENCODING", "OPTIMIZATION", "SECOND",
-				"UNKNOWN", "HOUR_SECOND", "REFERENCES", "ROWS", "JAVA", "SPATIAL", "INHERIT", "CREATE",
-				"PARAMETER_SPECIFIC_SCHEMA", "LEAST", "OLD", "TRIGGER", "BETWEEN", "OBID", "CONVERT", "POSITION", "PROCESS",
-				"SQL_SELECT_LIMIT", "NOTHING", "DEALLOCATE", "SUBPAGES", "INNER", "SQL_BIG_SELECTS", "EACH", "OPTIONALLY",
-				"SETUSER", "BIGINT", "NOAUDIT", "SUM", "OPTIONS", "MIN", "BITVAR", "VARCHAR", "SQLCA", "KEY", "PROGRAM", "CALL",
-				"WAITFOR", "RELOAD", "DELAY_KEY_WRITE", "USER_DEFINED_TYPE_SCHEMA", "RLIKE", "EDITPROC", "GROUP",
-				"DATETIME_INTERVAL_PRECISION", "ASSOCIATE", "RESTORE", "OFFSET", "TEMPORARY", "STANDARD", "OPENDATASOURCE",
-				"STATISTICS", "COBOL", "SECOND_MICROSECOND", "NULLABLE", "COMMITTED", "DELAYED", "PERCENT", " ONLINE", "DB2SQL",
-				"TO", "CONSTRUCTOR", "DB2GNRL", "UNION", "FREEZE", "SCOPE", "CLASS", "VIEW", "LINES", "ASSERTION", "PACKAGE",
-				"TRIGGER_NAME", "CONSTRAINTS", "LABEL", "CURRENT_TIME", "DEFERRED", "REPLACE", "KEY_MEMBER", "INTEGER",
-				"OVERRIDING", "UNIQUE", " MAXEXTENTS", "TRAILING", "COVAR_SAMP", "FINAL", " NOAUDIT", "FULL", "NAME", "YEARS",
-				"ROW_COUNT", "NOCREATEROLE", "CEILING", "LAST", "MAXVALUE", "QUOTE", "TOAST", "LOCALTIME", "CONTAINS", "GENERAL",
-				"DELIMITER", "STDIN", "REGEXP", "REGR_COUNT", "NOTIFY", "NEXT", "GLOBAL", "LEAVE", "SHOW", "SHUTDOWN", "VERBOSE",
-				"NORMALIZE", "CURRENT_TIMEZONE", "MOD", "EXISTS", "TIME", "MYISAM", "INHERITS", "DATETIME", "HOURS",
-				"NOMINVALUE", "BOOL", "ERRLVL", "NESTING", "FALSE", "MINUTES", "SECTION", "NOCHECK", "NOTNULL",
-				"PERCENTILE_CONT", "SYMMETRIC", "VALID", "PLAN", "SHARE", "TRAN", "STDDEV_SAMP", "WHEN",
-				"TRANSACTIONS_COMMITTED", "BREAK", "LOCAL", "CONSTRAINT_CATALOG", "DICTIONARY", "LOGIN", "CLUSTER", "GRANTS",
-				"DAY_MINUTE", "LONGBLOB", "CYCLE", "CAST", "INSTANCE", "VARCHAR2", "FUNCTION", "LEADING", "MODIFIES", "NOWAIT",
-				"CASE", "OUT", "OPTIMIZE", "REGR_SXX", "REGR_SXY", "OVERLAPS", "GET", "DENSE_RANK", "PUBLIC", "COUNT", "TREAT",
-				"NAMES", " NOCOMPRESS", "IDENTITY_INSERT", "NONCLUSTERED", "LENGTH", "UNSIGNED", "CHAR", "BEGIN", "MAX_ROWS",
-				"WRITE", "ORDER", "ISOLATION", "REPLICATION", "SQL_CALC_FOUND_ROWS", "REGR_SYY", "LANCOMPILER", " CLUSTER",
-				"CHARACTER_SET_NAME", "SIGNAL", "SUBMULTISET", "COLLATE", "MODIFY", "INSTANTIABLE", "UNCOMMITTED", "RESIGNAL",
-				"MORE", "PROC", "REPEATABLE", "COMPLETION", "KEY_TYPE", "KILL", "TRANSFORMS", "VOLATILE", "INPUT", "SUBSTRING",
-				"ZONE", "VCAT", "DEREF", "AUXILIARY", "REGR_AVGY", "REGR_AVGX", "TEMPLATE", "INCLUDING", "INSENSITIVE", "BOTH",
-				"CHARACTER_SET_CATALOG", "ENABLE", "EXCEPT", "HOSTS", "SCHEMA_NAME", "PREFIX", "SCROLL", "METHOD", "DAY_SECOND",
-				"DESTRUCTOR", "OIDS", "INT", "PASCAL", "COLLID", "PART", "ALSO", "CARDINALITY", "ACCESS", "OPENQUERY", "CLOB",
-				"COMMIT", "DISPATCH", "STRUCTURE", "DETERMINISTIC", "SAVEPOINT", "UNTIL", "USER", "TEMP", "MEDIUMBLOB", "MOVE",
-				"CROSS", "SMALLINT", "UESCAPE", "USER_DEFINED_TYPE_CATALOG", "RESULT", "SQLID", "PATH", "RESULT_SET_LOCATOR",
-				"PURGE", "TRIM", "ROWGUIDCOL", "RAW", "RANK", "VAR_POP", "MUMPS", "TRANSLATION", "MINUS", "EXPLAIN",
-				"PARAMETER_SPECIFIC_CATALOG", " INITIAL", "MESSAGE_LENGTH", "HOUR_MINUTE", "LISTEN", "WIDTH_BUCKET", "STORAGE",
-				"CURRENT_DEFAULT_TRANSFORM_GROUP", "STDOUT", "CUBE", "IMMUTABLE", "REGR_R2", "SQL_LOG_UPDATE", "XOR",
-				"FREETEXTTABLE", "ALTER", "MONTHNAME", "FUSION", "DESTROY", "PARAMETER_SPECIFIC_NAME", "TEXTSIZE", "SPACE",
-				"UPPER", "ABS", "CREATEUSER", "INTEGRITY", "OCTET_LENGTH", "TINYINT", "INTERVAL", "COLLATION_SCHEMA",
-				"CATALOG_NAME", "UNLISTEN", "MASTER_SSL_VERIFY_SERVER_CERT", "POWER", "CONNECTION", "PAD", "REF", "LOCALE",
-				"OPERATION", "SIMPLE", "VARBINARY", "VARIABLES", "ADA", "VIRTUAL", " FILE", "SYSTEM", "ADD", "SCOPE_CATALOG",
-				"SQLERROR", "CHECKED", "VARIANT", "OLD_TABLE", "INFIX", "TRUSTED", "INDEX", "FOUND", "HOLD", "EXTRACT",
-				"OFFSETS", "ATTRIBUTE", "PERCENTILE_DISC", "ITERATE", "CURRENT_SERVER", "CACHE", " LOCK", "CURRENT", " NOWAIT",
-				"RETURNED_SQLSTATE", "SYSPROC", "CONNECTION_NAME", "END", "PRESERVE", "LOAD", "TERMINATED", "BINARY", "FORWARD",
-				"SOME", "LAST_INSERT_ID", "OUTER", "INFILE", "RENAME", "EXCLUSIVE", "FILTER", "IDENTIFIED", "NORMALIZED",
-				" COLUMN", "INITIALLY", "OVER", "CURRENT_ROLE", "GRANT", "OTHERS", "SONAME", "CHAR_LENGTH", "NOMAXVALUE",
-				"ROWID", "DEFAULT", "SQRT", "JOIN", "LOCK", "TEXT", "UNNEST", "AVG_ROW_LENGTH", "SESSION_USER", "AGGREGATE",
-				"MULTISET", "ELSE", "TRANSACTION_ACTIVE", "LANGUAGE", "PERCENT_RANK", "ENUM", "NATIONAL", "SETOF",
-				"RETURNED_CARDINALITY", "SYNONYM", "CURRENT_TRANSFORM_GROUP_FOR_TYPE", "SPECIFICTYPE", "TOP", "FORTRAN",
-				"DEGREE", "ASYMMETRIC", "GRAPHIC", "ALWAYS", "MEDIUMTEXT", "SYSTEM_USER", "ROUTINE_CATALOG", "CURSOR_NAME",
-				"RIGHT", "STABLE", "FILE", "CREATEDB", "DISTRIBUTED", "FILLFACTOR", "FETCH", "NUMERIC", "STARTING", "REVOKE",
-				"SQLEXCEPTION", "DYNAMIC", "CHAIN", "CALLED", "INCREMENT", "ELEMENT", "MAXEXTENTS", "ROUTINE_SCHEMA",
-				"IO_AFTER_GTIDS", "TRIGGER_SCHEMA", "ALL", "NEW", "THAN", "ALIAS", "HOST", "VALUE", "LOGS", "SERIALIZABLE",
-				"X509", "AUTO_INCREMENT", "BACKUP", "MINUTE_MICROSECOND", "ALLOCATE", "HOLDLOCK", "MINUTE", "SCALE", "TINYTEXT",
-				"DESCRIBE", "NOCREATEDB", " INTERSECT", " PCTFREE", " PRIOR", "NULL", "TRUE", "PCTFREE", "EXISTING",
-				"PARAMETERS", "OBJECT", "TABLESPACE", "UTC_TIME", " LEVEL", "MODULE", "PASSWORD", "EXCLUDE", "SQL_WARNINGS",
-				"AND", "SQLCODE", "ROW", "CURRENT_DATE", "MESSAGE_TEXT", "DISK", "RANGE", "VACUUM", "MLSLABEL", "STORED", "HOUR",
-				"CONCAT", "APPLICATION", "INITIAL", "ANY", "PLI", "HEAP", " AUDIT", "NATURAL", "NOINHERIT", "STORES", "UNNAMED",
-				"KEYS", "RESTART", "READS", "NUMPARTS", "CSV", "IMPLEMENTATION", "ORDERING", "TRANSLATE", "REINDEX", "JAR",
-				"EXP", "MATCH", "PRINT", "NOCREATEUSER", "CHECKSUM", "ELSEIF", "MONTH", "ROWCOUNT", "AFTER", "CLOSE", "RRN",
-				"MONTHS", "OWNER", "DENY", "END-EXEC", "INCLUDE", "OCTETS", "UPDATETEXT", "PRIOR", "SYSIBM", " DATE",
-				"SCRATCHPAD", "NODENAME", "IDENTITY", "ARE", "FULLTEXT", "SOURCE", "CONDITION", "THEN", "PROCEDURAL", "UNLOCK",
-				"HIERARCHY", "ORDINALITY", "INTO", "MICROSECONDS", "REPEAT", "MICROSECOND", "EXCEPTION", "INDICATOR", "FREE",
-				"RETURNED_OCTET_LENGTH", "NOCOMPRESS", "ASC", "DELETE", "COVAR_POP", "VARIABLE", " INDEX", "PREPARED",
-				"GENERATED", "SIMILAR", "LONG", "RESOURCE", "INT1", "INT2", "PROCEDURE", "INT3", "STDDEV_POP", "INT4", "SECONDS",
-				"COLLECT", "ANALYZE", "RUN", "UNDER", "INT8", "OPEN", "DERIVED", "NO_WRITE_TO_BINLOG", "REFERENCING", "STRING",
-				"PSID", "BREADTH", "STAY", "LOCATOR", "NOCACHE", "LOOP", "HIGH_PRIORITY", "IMMEDIATE", "DESC", "FREETEXT",
-				"NUMBER", "AUX", "OUTPUT", "LONGTEXT", "DATABASES", "BOOLEAN", "AVG", "NOT", "PLACING", "INTERSECTION", "LOWER",
-				"SPECIFIC", "MINUTE_SECOND", "FLOAT8", "HAVING", "FIELDPROC", "FLOAT4", "SQLSTATE", "RECONFIGURE", "LOCKMAX",
-				"BACKWARD", "BUFFERPOOL", "VALIDPROC", " MINUS", "COMMAND_FUNCTION", "DROP", "RETURN", "FOREIGN",
-				"PARAMETER_NAME", "TSEQUAL", "SQL_SMALL_RESULT", "RULE", "SERVER_NAME", "DAYOFMONTH", "IO_BEFORE_GTIDS",
-				"PARTIAL", "MEDIUMINT", "TRANSACTIONS_ROLLED_BACK", "OPENXML", " DROP", "ESCAPE", "SCOPE_NAME", "ISAM", "LINEAR",
-				"PARAMETER_ORDINAL_POSITION", " OFFLINE", "ROWNUM", "DATETIME_INTERVAL_CODE", "DEFINED", "LOCALTIMESTAMP",
-				" CONNECT", "ISOBID", "TABLE", "ANALYSE", "DEFINER", "SCOPE_SCHEMA", "COLLATION_CATALOG", "NONE", "PROCESSLIST",
-				"TYPE", "USER_DEFINED_TYPE_CODE", "DESCRIPTOR", "PIECESIZE", "OPTION", "WHENEVER", "ENCLOSED", "LEVEL",
-				"COUNT_BIG", "ASENSITIVE", "LOCKSIZE", "TINYBLOB", "PREPARE", "CHECK", "WITHOUT", "WORK", "HANDLER", "CUME_DIST",
-				"WRITETEXT", "INITIALIZE", "DAY_HOUR", "ILIKE", "CONNECT", "TABLESAMPLE", "INSERT_ID", "MIDDLEINT", "RELATIVE",
-				"LARGE", "ACCESSIBLE", "VALUES", "DOUBLE", "ASUTIME", "DEFAULTS", "NOLOGIN", "TIMEZONE_HOUR", "COMPUTE", "COPY",
-				"SELF", "SESSION", "NOCYCLE", "DUMMY", "WINDOW", "EXECUTE", "PRECEDING", "PACK_KEYS", "NOORDER", "CHECKPOINT",
-				" LONG", "DAY", "AUTHORIZATION", "CCSID", "COLLECTION", "BLOB", "PRIQTY", "RECURSIVE", "ONLY", "FROM",
-				"SQL_BIG_TABLES", "LATERAL", "TRANSFORM", "HOUR_MICROSECOND", "SENSITIVE", "SUBCLASS_ORIGIN", "CONVERSION",
-				"DAY_MICROSECOND", "SEPARATOR", "OPTIMIZER_COSTS", "NOSUPERUSER", "DATE", "ROLLUP", "TOP_LEVEL_COUNT", "CORR",
-				"UNENCRYPTED", "UTC_TIMESTAMP", "LIKE", "ZEROFILL", "DATA", "SUCCESSFUL", "INSERT", "YEAR_MONTH", "OFFLINE",
-				"INOUT", "VAR_SAMP", "BROWSE", "SCHEMAS", "CONSTRAINT_NAME", "PARAMETER_MODE", "LIMIT", "LINKTYPE", "NULLS",
-				"DEC", "CASCADED", "ENCRYPTED", "CONTAINSTABLE", "DYNAMIC_FUNCTION", "CONDITION_NUMBER", "BEFORE", "DB2GENERAL",
-				"DECLARE", "SUPERUSER", "WHILE" };
+    static {
+        String[] words = {"AUDIT", "VOLUMES", "MINVALUE", "STATIC", "FLOOR", "CATALOG", "YEAR", "TRIGGER_CATALOG", "WLM",
+                "DISCONNECT", "PARTITION", "LEFT", " MODE", "SEARCH", "CURRENT_PATH", "DAYOFYEAR", "SIZE", "RESTRICT", "RELEASE",
+                "WHERE", "POSTFIX", "SQLWARNING", "UID", "AS", "AT", "SYSID", "DATABASE", "SPECIFIC_NAME", "TIMEZONE_MINUTE",
+                "LC_CTYPE", "ATTRIBUTES", "LOCATION", "A", "DOMAIN", "C", "SET", " INCREMENT", "MERGE", "G", "DAYS", "HEADER",
+                "K", "CONSTRAINT", "M", "PRECISION", "ROLE", "COLLATION_NAME", "BY", "STRAIGHT_JOIN", "CHARACTER", "INSTEAD",
+                "DUAL", "DSNHATTR", "BERNOULLI", " ADD", "CLUSTERED", "CONTINUE", "DIV", "OPERATOR", "SETS", "SECURITY",
+                "CURRENT_LC_CTYPE", "TRUNCATE", "CURSOR", "SQL_LOW_PRIORITY_UPDATES", "CONSTRAINT_SCHEMA", "STATEMENT",
+                "TABLE_NAME", "NODENUMBER", "DO", "RECOVERY", "LOW_PRIORITY", "ADMIN", "ESCAPED", "CAPTURE", "ALLOW", "VARYING",
+                "DISABLE", "STRICT", "SQL_BIG_RESULT", "ABORT", "FOR", "IMPLICIT", "USING", "EXEC", "DEFERRABLE", "RAISERROR",
+                "USER_DEFINED_TYPE_NAME", "VALIDATOR", "UNDO", "STATE", "WITHIN", "NCHAR", "ABSOLUTE", "PREORDER", "SCHEMA",
+                "SEQUENCE", "ASSIGNMENT", "COLUMNS", "END-EXEC1", "GO", "ROW_NUMBER", "BIT", "INTERSECT", "SYSDATE", "WITH",
+                "CLASS_ORIGIN", "ACTION", "ISNULL", "VALIDATE", " COMPRESS", "START", "CHARACTER_LENGTH", "BULK", "EVERY",
+                "NULLIF", "CEIL", "FLUSH", "MIN_ROWS", "GRANTED", "IF", "BIT_LENGTH", "PARAMETER", "CHARACTER_SET_SCHEMA",
+                "DEFINITION", "NCLOB", "FIELDS", "IN", "DISTINCT", "STYLE", "IS", "MASTER_BIND", "REGR_INTERCEPT", "TERMINATE",
+                "FORCE", "FENCED", " IMMEDIATE", "MAP", "READTEXT", "SYSFUN", "EXIT", "DBCC", "OPENROWSET", "COLLATION", "GOTO",
+                "RAID0", "MAX", "CASCADE", "DELIMITERS", "TRANSACTION", "SECQTY", "IGNORE", "COMMENT", "OFF", "CHARACTERS",
+                "IDENTITYCOL", "USAGE", "UPDATE", "SAVE", "REQUIRE", "DISTINCTROW", "USE", "RETURNS", "LOCATORS",
+                "CHARACTERISTICS", "FIRST", "LINENO", "ONLINE", "SELECT", "EXCLUDING", "TABLES", "OUTFILE", "ERASE", "GREATEST",
+                "UTC_DATE", "VARCHARACTER", "INVOKER", "STOGROUP", "DEPTH", "CURRENT_USER", "LN", "ARRAY", "ATOMIC", " ALTER",
+                "COLUMN_NAME", "COLUMN", "MODE", " COMMENT", "DECIMAL", "RESET", "NEW_TABLE", "ROUTINE_NAME", "COMPRESS",
+                "OVERLAY", "READ_WRITE", "COALESCE", "STATUS", " EXCLUSIVE", "UNBOUNDED", "REGR_SLOPE", "CORRESPONDING",
+                "TIMESTAMP", "MESSAGE_OCTET_LENGTH", "SQL_LOG_OFF", "RETURNED_LENGTH", "DISALLOW", "PRIVILEGES", "SQL", "READ",
+                " IDENTIFIED", "REAL", "LESS", "DIAGNOSTICS", "QUERYNO", "NO", "FLOAT", "COMMAND_FUNCTION_CODE",
+                "CURRENT_TIMESTAMP", "TIES", "ROUTINE", "SUBLIST", "FOLLOWING", "ROLLBACK", "MEMBER", "DSSIZE", "DUMP",
+                "EXTERNAL", "GROUPING", "OF", "CHANGE", "RECHECK", " NUMBER", "ON", "DBINFO", "OR", "EQUALS", "CREATEROLE",
+                "PRIMARY", "SSL", "MATCHED", "DAYOFWEEK", "DYNAMIC_FUNCTION_CODE", "ENCODING", "OPTIMIZATION", "SECOND",
+                "UNKNOWN", "HOUR_SECOND", "REFERENCES", "ROWS", "JAVA", "SPATIAL", "INHERIT", "CREATE",
+                "PARAMETER_SPECIFIC_SCHEMA", "LEAST", "OLD", "TRIGGER", "BETWEEN", "OBID", "CONVERT", "POSITION", "PROCESS",
+                "SQL_SELECT_LIMIT", "NOTHING", "DEALLOCATE", "SUBPAGES", "INNER", "SQL_BIG_SELECTS", "EACH", "OPTIONALLY",
+                "SETUSER", "BIGINT", "NOAUDIT", "SUM", "OPTIONS", "MIN", "BITVAR", "VARCHAR", "SQLCA", "KEY", "PROGRAM", "CALL",
+                "WAITFOR", "RELOAD", "DELAY_KEY_WRITE", "USER_DEFINED_TYPE_SCHEMA", "RLIKE", "EDITPROC", "GROUP",
+                "DATETIME_INTERVAL_PRECISION", "ASSOCIATE", "RESTORE", "OFFSET", "TEMPORARY", "STANDARD", "OPENDATASOURCE",
+                "STATISTICS", "COBOL", "SECOND_MICROSECOND", "NULLABLE", "COMMITTED", "DELAYED", "PERCENT", " ONLINE", "DB2SQL",
+                "TO", "CONSTRUCTOR", "DB2GNRL", "UNION", "FREEZE", "SCOPE", "CLASS", "VIEW", "LINES", "ASSERTION", "PACKAGE",
+                "TRIGGER_NAME", "CONSTRAINTS", "LABEL", "CURRENT_TIME", "DEFERRED", "REPLACE", "KEY_MEMBER", "INTEGER",
+                "OVERRIDING", "UNIQUE", " MAXEXTENTS", "TRAILING", "COVAR_SAMP", "FINAL", " NOAUDIT", "FULL", "NAME", "YEARS",
+                "ROW_COUNT", "NOCREATEROLE", "CEILING", "LAST", "MAXVALUE", "QUOTE", "TOAST", "LOCALTIME", "CONTAINS", "GENERAL",
+                "DELIMITER", "STDIN", "REGEXP", "REGR_COUNT", "NOTIFY", "NEXT", "GLOBAL", "LEAVE", "SHOW", "SHUTDOWN", "VERBOSE",
+                "NORMALIZE", "CURRENT_TIMEZONE", "MOD", "EXISTS", "TIME", "MYISAM", "INHERITS", "DATETIME", "HOURS",
+                "NOMINVALUE", "BOOL", "ERRLVL", "NESTING", "FALSE", "MINUTES", "SECTION", "NOCHECK", "NOTNULL",
+                "PERCENTILE_CONT", "SYMMETRIC", "VALID", "PLAN", "SHARE", "TRAN", "STDDEV_SAMP", "WHEN",
+                "TRANSACTIONS_COMMITTED", "BREAK", "LOCAL", "CONSTRAINT_CATALOG", "DICTIONARY", "LOGIN", "CLUSTER", "GRANTS",
+                "DAY_MINUTE", "LONGBLOB", "CYCLE", "CAST", "INSTANCE", "VARCHAR2", "FUNCTION", "LEADING", "MODIFIES", "NOWAIT",
+                "CASE", "OUT", "OPTIMIZE", "REGR_SXX", "REGR_SXY", "OVERLAPS", "GET", "DENSE_RANK", "PUBLIC", "COUNT", "TREAT",
+                "NAMES", " NOCOMPRESS", "IDENTITY_INSERT", "NONCLUSTERED", "LENGTH", "UNSIGNED", "CHAR", "BEGIN", "MAX_ROWS",
+                "WRITE", "ORDER", "ISOLATION", "REPLICATION", "SQL_CALC_FOUND_ROWS", "REGR_SYY", "LANCOMPILER", " CLUSTER",
+                "CHARACTER_SET_NAME", "SIGNAL", "SUBMULTISET", "COLLATE", "MODIFY", "INSTANTIABLE", "UNCOMMITTED", "RESIGNAL",
+                "MORE", "PROC", "REPEATABLE", "COMPLETION", "KEY_TYPE", "KILL", "TRANSFORMS", "VOLATILE", "INPUT", "SUBSTRING",
+                "ZONE", "VCAT", "DEREF", "AUXILIARY", "REGR_AVGY", "REGR_AVGX", "TEMPLATE", "INCLUDING", "INSENSITIVE", "BOTH",
+                "CHARACTER_SET_CATALOG", "ENABLE", "EXCEPT", "HOSTS", "SCHEMA_NAME", "PREFIX", "SCROLL", "METHOD", "DAY_SECOND",
+                "DESTRUCTOR", "OIDS", "INT", "PASCAL", "COLLID", "PART", "ALSO", "CARDINALITY", "ACCESS", "OPENQUERY", "CLOB",
+                "COMMIT", "DISPATCH", "STRUCTURE", "DETERMINISTIC", "SAVEPOINT", "UNTIL", "USER", "TEMP", "MEDIUMBLOB", "MOVE",
+                "CROSS", "SMALLINT", "UESCAPE", "USER_DEFINED_TYPE_CATALOG", "RESULT", "SQLID", "PATH", "RESULT_SET_LOCATOR",
+                "PURGE", "TRIM", "ROWGUIDCOL", "RAW", "RANK", "VAR_POP", "MUMPS", "TRANSLATION", "MINUS", "EXPLAIN",
+                "PARAMETER_SPECIFIC_CATALOG", " INITIAL", "MESSAGE_LENGTH", "HOUR_MINUTE", "LISTEN", "WIDTH_BUCKET", "STORAGE",
+                "CURRENT_DEFAULT_TRANSFORM_GROUP", "STDOUT", "CUBE", "IMMUTABLE", "REGR_R2", "SQL_LOG_UPDATE", "XOR",
+                "FREETEXTTABLE", "ALTER", "MONTHNAME", "FUSION", "DESTROY", "PARAMETER_SPECIFIC_NAME", "TEXTSIZE", "SPACE",
+                "UPPER", "ABS", "CREATEUSER", "INTEGRITY", "OCTET_LENGTH", "TINYINT", "INTERVAL", "COLLATION_SCHEMA",
+                "CATALOG_NAME", "UNLISTEN", "MASTER_SSL_VERIFY_SERVER_CERT", "POWER", "CONNECTION", "PAD", "REF", "LOCALE",
+                "OPERATION", "SIMPLE", "VARBINARY", "VARIABLES", "ADA", "VIRTUAL", " FILE", "SYSTEM", "ADD", "SCOPE_CATALOG",
+                "SQLERROR", "CHECKED", "VARIANT", "OLD_TABLE", "INFIX", "TRUSTED", "INDEX", "FOUND", "HOLD", "EXTRACT",
+                "OFFSETS", "ATTRIBUTE", "PERCENTILE_DISC", "ITERATE", "CURRENT_SERVER", "CACHE", " LOCK", "CURRENT", " NOWAIT",
+                "RETURNED_SQLSTATE", "SYSPROC", "CONNECTION_NAME", "END", "PRESERVE", "LOAD", "TERMINATED", "BINARY", "FORWARD",
+                "SOME", "LAST_INSERT_ID", "OUTER", "INFILE", "RENAME", "EXCLUSIVE", "FILTER", "IDENTIFIED", "NORMALIZED",
+                " COLUMN", "INITIALLY", "OVER", "CURRENT_ROLE", "GRANT", "OTHERS", "SONAME", "CHAR_LENGTH", "NOMAXVALUE",
+                "ROWID", "DEFAULT", "SQRT", "JOIN", "LOCK", "TEXT", "UNNEST", "AVG_ROW_LENGTH", "SESSION_USER", "AGGREGATE",
+                "MULTISET", "ELSE", "TRANSACTION_ACTIVE", "LANGUAGE", "PERCENT_RANK", "ENUM", "NATIONAL", "SETOF",
+                "RETURNED_CARDINALITY", "SYNONYM", "CURRENT_TRANSFORM_GROUP_FOR_TYPE", "SPECIFICTYPE", "TOP", "FORTRAN",
+                "DEGREE", "ASYMMETRIC", "GRAPHIC", "ALWAYS", "MEDIUMTEXT", "SYSTEM_USER", "ROUTINE_CATALOG", "CURSOR_NAME",
+                "RIGHT", "STABLE", "FILE", "CREATEDB", "DISTRIBUTED", "FILLFACTOR", "FETCH", "NUMERIC", "STARTING", "REVOKE",
+                "SQLEXCEPTION", "DYNAMIC", "CHAIN", "CALLED", "INCREMENT", "ELEMENT", "MAXEXTENTS", "ROUTINE_SCHEMA",
+                "IO_AFTER_GTIDS", "TRIGGER_SCHEMA", "ALL", "NEW", "THAN", "ALIAS", "HOST", "VALUE", "LOGS", "SERIALIZABLE",
+                "X509", "AUTO_INCREMENT", "BACKUP", "MINUTE_MICROSECOND", "ALLOCATE", "HOLDLOCK", "MINUTE", "SCALE", "TINYTEXT",
+                "DESCRIBE", "NOCREATEDB", " INTERSECT", " PCTFREE", " PRIOR", "NULL", "TRUE", "PCTFREE", "EXISTING",
+                "PARAMETERS", "OBJECT", "TABLESPACE", "UTC_TIME", " LEVEL", "MODULE", "PASSWORD", "EXCLUDE", "SQL_WARNINGS",
+                "AND", "SQLCODE", "ROW", "CURRENT_DATE", "MESSAGE_TEXT", "DISK", "RANGE", "VACUUM", "MLSLABEL", "STORED", "HOUR",
+                "CONCAT", "APPLICATION", "INITIAL", "ANY", "PLI", "HEAP", " AUDIT", "NATURAL", "NOINHERIT", "STORES", "UNNAMED",
+                "KEYS", "RESTART", "READS", "NUMPARTS", "CSV", "IMPLEMENTATION", "ORDERING", "TRANSLATE", "REINDEX", "JAR",
+                "EXP", "MATCH", "PRINT", "NOCREATEUSER", "CHECKSUM", "ELSEIF", "MONTH", "ROWCOUNT", "AFTER", "CLOSE", "RRN",
+                "MONTHS", "OWNER", "DENY", "END-EXEC", "INCLUDE", "OCTETS", "UPDATETEXT", "PRIOR", "SYSIBM", " DATE",
+                "SCRATCHPAD", "NODENAME", "IDENTITY", "ARE", "FULLTEXT", "SOURCE", "CONDITION", "THEN", "PROCEDURAL", "UNLOCK",
+                "HIERARCHY", "ORDINALITY", "INTO", "MICROSECONDS", "REPEAT", "MICROSECOND", "EXCEPTION", "INDICATOR", "FREE",
+                "RETURNED_OCTET_LENGTH", "NOCOMPRESS", "ASC", "DELETE", "COVAR_POP", "VARIABLE", " INDEX", "PREPARED",
+                "GENERATED", "SIMILAR", "LONG", "RESOURCE", "INT1", "INT2", "PROCEDURE", "INT3", "STDDEV_POP", "INT4", "SECONDS",
+                "COLLECT", "ANALYZE", "RUN", "UNDER", "INT8", "OPEN", "DERIVED", "NO_WRITE_TO_BINLOG", "REFERENCING", "STRING",
+                "PSID", "BREADTH", "STAY", "LOCATOR", "NOCACHE", "LOOP", "HIGH_PRIORITY", "IMMEDIATE", "DESC", "FREETEXT",
+                "NUMBER", "AUX", "OUTPUT", "LONGTEXT", "DATABASES", "BOOLEAN", "AVG", "NOT", "PLACING", "INTERSECTION", "LOWER",
+                "SPECIFIC", "MINUTE_SECOND", "FLOAT8", "HAVING", "FIELDPROC", "FLOAT4", "SQLSTATE", "RECONFIGURE", "LOCKMAX",
+                "BACKWARD", "BUFFERPOOL", "VALIDPROC", " MINUS", "COMMAND_FUNCTION", "DROP", "RETURN", "FOREIGN",
+                "PARAMETER_NAME", "TSEQUAL", "SQL_SMALL_RESULT", "RULE", "SERVER_NAME", "DAYOFMONTH", "IO_BEFORE_GTIDS",
+                "PARTIAL", "MEDIUMINT", "TRANSACTIONS_ROLLED_BACK", "OPENXML", " DROP", "ESCAPE", "SCOPE_NAME", "ISAM", "LINEAR",
+                "PARAMETER_ORDINAL_POSITION", " OFFLINE", "ROWNUM", "DATETIME_INTERVAL_CODE", "DEFINED", "LOCALTIMESTAMP",
+                " CONNECT", "ISOBID", "TABLE", "ANALYSE", "DEFINER", "SCOPE_SCHEMA", "COLLATION_CATALOG", "NONE", "PROCESSLIST",
+                "TYPE", "USER_DEFINED_TYPE_CODE", "DESCRIPTOR", "PIECESIZE", "OPTION", "WHENEVER", "ENCLOSED", "LEVEL",
+                "COUNT_BIG", "ASENSITIVE", "LOCKSIZE", "TINYBLOB", "PREPARE", "CHECK", "WITHOUT", "WORK", "HANDLER", "CUME_DIST",
+                "WRITETEXT", "INITIALIZE", "DAY_HOUR", "ILIKE", "CONNECT", "TABLESAMPLE", "INSERT_ID", "MIDDLEINT", "RELATIVE",
+                "LARGE", "ACCESSIBLE", "VALUES", "DOUBLE", "ASUTIME", "DEFAULTS", "NOLOGIN", "TIMEZONE_HOUR", "COMPUTE", "COPY",
+                "SELF", "SESSION", "NOCYCLE", "DUMMY", "WINDOW", "EXECUTE", "PRECEDING", "PACK_KEYS", "NOORDER", "CHECKPOINT",
+                " LONG", "DAY", "AUTHORIZATION", "CCSID", "COLLECTION", "BLOB", "PRIQTY", "RECURSIVE", "ONLY", "FROM",
+                "SQL_BIG_TABLES", "LATERAL", "TRANSFORM", "HOUR_MICROSECOND", "SENSITIVE", "SUBCLASS_ORIGIN", "CONVERSION",
+                "DAY_MICROSECOND", "SEPARATOR", "OPTIMIZER_COSTS", "NOSUPERUSER", "DATE", "ROLLUP", "TOP_LEVEL_COUNT", "CORR",
+                "UNENCRYPTED", "UTC_TIMESTAMP", "LIKE", "ZEROFILL", "DATA", "SUCCESSFUL", "INSERT", "YEAR_MONTH", "OFFLINE",
+                "INOUT", "VAR_SAMP", "BROWSE", "SCHEMAS", "CONSTRAINT_NAME", "PARAMETER_MODE", "LIMIT", "LINKTYPE", "NULLS",
+                "DEC", "CASCADED", "ENCRYPTED", "CONTAINSTABLE", "DYNAMIC_FUNCTION", "CONDITION_NUMBER", "BEFORE", "DB2GENERAL",
+                "DECLARE", "SUPERUSER", "WHILE"};
 
-		RESERVED_WORDS = new HashSet<String>(words.length);
-		Collections.addAll(RESERVED_WORDS, words);
-	}
+        RESERVED_WORDS = new HashSet<String>(words.length);
+        Collections.addAll(RESERVED_WORDS, words);
+    }
 
-	/**
-	 * <p>
-	 * 数据库字段转义
-	 * </p>
-	 *
-	 * @param globalConfig
-	 *            全局配置
-	 * @param column
-	 *            数据库字段
-	 * @return
-	 */
-	public static String convert(GlobalConfiguration globalConfig, String column) {
-		if (containsWord(column)) {
-			String identifierQuote = StringUtils.isEmpty(globalConfig.getIdentifierQuote()) ? globalConfig.getDbType().getQuote()
-					: globalConfig.getIdentifierQuote();
-			if (StringUtils.isNotEmpty(identifierQuote)) {
-				return String.format(identifierQuote, column);
-			}
-		}
-		return column;
-	}
+    /**
+     * Utility class - no instances allowed
+     */
+    private SqlReservedWords() {
 
-	/**
-	 * 判断关键字中是否包含该字段
-	 *
-	 * @param word
-	 * @return
-	 */
-	public static boolean containsWord(String word) {
-		return null != word && RESERVED_WORDS.contains(word.toUpperCase());
-	}
+    }
 
-	/**
-	 * Utility class - no instances allowed
-	 */
-	private SqlReservedWords() {
+    /**
+     * <p>
+     * 数据库字段转义
+     * </p>
+     *
+     * @param globalConfig
+     *            全局配置
+     * @param column
+     *            数据库字段
+     * @return
+     */
+    public static String convert(GlobalConfiguration globalConfig, String column) {
+        if (containsWord(column)) {
+            String identifierQuote = StringUtils.isEmpty(globalConfig.getIdentifierQuote()) ? globalConfig.getDbType().getQuote()
+                    : globalConfig.getIdentifierQuote();
+            if (StringUtils.isNotEmpty(identifierQuote)) {
+                return String.format(identifierQuote, column);
+            }
+        }
+        return column;
+    }
 
-	}
+    /**
+     * 判断关键字中是否包含该字段
+     *
+     * @param word
+     * @return
+     */
+    public static boolean containsWord(String word) {
+        return null != word && RESERVED_WORDS.contains(word.toUpperCase());
+    }
 
 }

+ 136 - 135
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlUtils.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -29,143 +29,144 @@ import com.baomidou.mybatisplus.plugins.pagination.Pagination;
  * @Date 2016-11-13
  */
 public class SqlUtils {
-	private final static SqlFormatter sqlFormatter = new SqlFormatter();
-	public static final String SQL_BASE_COUNT = "SELECT COUNT(1) FROM ( %s ) TOTAL";
 
-	/**
-	 * 获取CountOptimize
-	 * 
-	 * @param originalSql
-	 *            需要计算Count SQL
-	 * @param optimizeType
-	 *            count优化方式
-	 * @param isOptimizeCount
-	 *            是否需要优化Count
-	 * @return CountOptimize
-	 */
-	public static CountOptimize getCountOptimize(String originalSql, String optimizeType, String dialectType,
-			boolean isOptimizeCount) {
-		CountOptimize countOptimize = CountOptimize.newInstance();
-		// 获取优化类型
-		Optimize opType = Optimize.getOptimizeType(optimizeType);
-		// 调整SQL便于解析
-		String tempSql = originalSql.replaceAll("(?i)ORDER[\\s]+BY", "ORDER BY").replaceAll("(?i)GROUP[\\s]+BY", "GROUP BY");
-		String indexOfSql = tempSql.toUpperCase();
-		// 有排序情况
-		int orderByIndex = indexOfSql.lastIndexOf("ORDER BY");
-		// 只针对 ALI_DRUID DEFAULT 这2种情况
-		if (orderByIndex > -1) {
-			countOptimize.setOrderBy(false);
-		}
-		if (!isOptimizeCount && opType.equals(Optimize.DEFAULT)) {
-			countOptimize.setCountSQL(String.format(SQL_BASE_COUNT, originalSql));
-			return countOptimize;
-		}
+    public static final String SQL_BASE_COUNT = "SELECT COUNT(1) FROM ( %s ) TOTAL";
+    private final static SqlFormatter sqlFormatter = new SqlFormatter();
+
+    /**
+     * 获取CountOptimize
+     *
+     * @param originalSql
+     *            需要计算Count SQL
+     * @param optimizeType
+     *            count优化方式
+     * @param isOptimizeCount
+     *            是否需要优化Count
+     * @return CountOptimize
+     */
+    public static CountOptimize getCountOptimize(String originalSql, String optimizeType, String dialectType,
+                                                 boolean isOptimizeCount) {
+        CountOptimize countOptimize = CountOptimize.newInstance();
+        // 获取优化类型
+        Optimize opType = Optimize.getOptimizeType(optimizeType);
+        // 调整SQL便于解析
+        String tempSql = originalSql.replaceAll("(?i)ORDER[\\s]+BY", "ORDER BY").replaceAll("(?i)GROUP[\\s]+BY", "GROUP BY");
+        String indexOfSql = tempSql.toUpperCase();
+        // 有排序情况
+        int orderByIndex = indexOfSql.lastIndexOf("ORDER BY");
+        // 只针对 ALI_DRUID DEFAULT 这2种情况
+        if (orderByIndex > -1) {
+            countOptimize.setOrderBy(false);
+        }
+        if (!isOptimizeCount && opType.equals(Optimize.DEFAULT)) {
+            countOptimize.setCountSQL(String.format(SQL_BASE_COUNT, originalSql));
+            return countOptimize;
+        }
 
-		switch (opType) {
-		case ALI_DRUID:
-			/**
-			 * 调用ali druid方式 插件dbType一定要设置为小写与JdbcConstants保持一致
-			 * 
-			 * @see com.alibaba.druid.util.JdbcConstants
-			 */
-			String aliCountSql = DruidUtils.count(originalSql, dialectType);
-			countOptimize.setCountSQL(aliCountSql);
-			break;
-		case JSQLPARSER:
-			/**
-			 * 调用JsqlParser方式
-			 */
-			JsqlParserUtils.jsqlparserCount(countOptimize, originalSql);
-			break;
-		default:
-			StringBuilder countSql = new StringBuilder("SELECT COUNT(1) ");
-			boolean optimize = false;
-			if (!indexOfSql.contains("DISTINCT") && !indexOfSql.contains("GROUP BY")) {
-				int formIndex = indexOfSql.indexOf("FROM");
-				if (formIndex > -1) {
-					if (orderByIndex > -1) {
-						tempSql = tempSql.substring(0, orderByIndex);
-						countSql.append(tempSql.substring(formIndex));
-						// 无排序情况
-					} else {
-						countSql.append(tempSql.substring(formIndex));
-					}
-					// 执行优化
-					optimize = true;
-				}
-			}
-			if (!optimize) {
-				// 无优化SQL
-				countSql.append("FROM ( ").append(originalSql).append(" ) TOTAL");
-			}
-			countOptimize.setCountSQL(countSql.toString());
-		}
+        switch (opType) {
+            case ALI_DRUID:
+                /**
+                 * 调用ali druid方式 插件dbType一定要设置为小写与JdbcConstants保持一致
+                 *
+                 * @see com.alibaba.druid.util.JdbcConstants
+                 */
+                String aliCountSql = DruidUtils.count(originalSql, dialectType);
+                countOptimize.setCountSQL(aliCountSql);
+                break;
+            case JSQLPARSER:
+                /**
+                 * 调用JsqlParser方式
+                 */
+                JsqlParserUtils.jsqlparserCount(countOptimize, originalSql);
+                break;
+            default:
+                StringBuilder countSql = new StringBuilder("SELECT COUNT(1) ");
+                boolean optimize = false;
+                if (!indexOfSql.contains("DISTINCT") && !indexOfSql.contains("GROUP BY")) {
+                    int formIndex = indexOfSql.indexOf("FROM");
+                    if (formIndex > -1) {
+                        if (orderByIndex > -1) {
+                            tempSql = tempSql.substring(0, orderByIndex);
+                            countSql.append(tempSql.substring(formIndex));
+                            // 无排序情况
+                        } else {
+                            countSql.append(tempSql.substring(formIndex));
+                        }
+                        // 执行优化
+                        optimize = true;
+                    }
+                }
+                if (!optimize) {
+                    // 无优化SQL
+                    countSql.append("FROM ( ").append(originalSql).append(" ) TOTAL");
+                }
+                countOptimize.setCountSQL(countSql.toString());
+        }
 
-		return countOptimize;
-	}
+        return countOptimize;
+    }
 
-	/**
-	 * 查询SQL拼接Order By
-	 * 
-	 * @param originalSql
-	 *            需要拼接的SQL
-	 * @param page
-	 *            page对象
-	 * @param orderBy
-	 *            是否需要拼接Order By
-	 * @return
-	 */
-	public static String concatOrderBy(String originalSql, Pagination page, boolean orderBy) {
-		if (orderBy && StringUtils.isNotEmpty(page.getOrderByField()) && page.isOpenSort()) {
-			StringBuilder buildSql = new StringBuilder(originalSql);
-			buildSql.append(" ORDER BY ").append(page.getOrderByField());
-			buildSql.append(page.isAsc() ? " ASC " : " DESC ");
-			return buildSql.toString();
-		}
-		return originalSql;
-	}
+    /**
+     * 查询SQL拼接Order By
+     *
+     * @param originalSql
+     *            需要拼接的SQL
+     * @param page
+     *            page对象
+     * @param orderBy
+     *            是否需要拼接Order By
+     * @return
+     */
+    public static String concatOrderBy(String originalSql, Pagination page, boolean orderBy) {
+        if (orderBy && StringUtils.isNotEmpty(page.getOrderByField()) && page.isOpenSort()) {
+            StringBuilder buildSql = new StringBuilder(originalSql);
+            buildSql.append(" ORDER BY ").append(page.getOrderByField());
+            buildSql.append(page.isAsc() ? " ASC " : " DESC ");
+            return buildSql.toString();
+        }
+        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]+", " ");
-		}
-	}
+    /**
+     * 格式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]+", " ");
+        }
+    }
 
-	/**
-	 * <p>
-	 * 用%连接like
-	 * </p>
-	 *
-	 * @param str
-	 *            原字符串
-	 * @return
-	 */
-	public static String concatLike(String str, SqlLike type) {
-		StringBuilder builder = new StringBuilder(str.length() + 3);
-		switch (type) {
-		case LEFT:
-			builder.append("%").append(str);
-			break;
-		case RIGHT:
-			builder.append(str).append("%");
-			break;
-		case CUSTOM:
-			builder.append(str);
-			break;
-		default:
-			builder.append("%").append(str).append("%");
-		}
-		return builder.toString();
-	}
+    /**
+     * <p>
+     * 用%连接like
+     * </p>
+     *
+     * @param str
+     *            原字符串
+     * @return
+     */
+    public static String concatLike(String str, SqlLike type) {
+        StringBuilder builder = new StringBuilder(str.length() + 3);
+        switch (type) {
+            case LEFT:
+                builder.append("%").append(str);
+                break;
+            case RIGHT:
+                builder.append(str).append("%");
+                break;
+            case CUSTOM:
+                builder.append(str);
+                break;
+            default:
+                builder.append("%").append(str).append("%");
+        }
+        return builder.toString();
+    }
 
 }

+ 98 - 98
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/StringEscape.java

@@ -10,140 +10,140 @@ package com.baomidou.mybatisplus.toolkit;
  */
 public class StringEscape {
 
-	/**
-	 * 字符串是否需要转义
-	 *
-	 * @param str
-	 * @param len
-	 * @return
-	 */
-	private static boolean isEscapeNeededForString(String str, int len) {
+    /**
+     * 字符串是否需要转义
+     *
+     * @param str
+     * @param len
+     * @return
+     */
+    private static boolean isEscapeNeededForString(String str, int len) {
 
-		boolean needsHexEscape = false;
+        boolean needsHexEscape = false;
 
-		for (int i = 0; i < len; ++i) {
-			char c = str.charAt(i);
+        for (int i = 0; i < len; ++i) {
+            char c = str.charAt(i);
 
-			switch (c) {
-				case 0: /* Must be escaped for 'mysql' */
+            switch (c) {
+                case 0: /* Must be escaped for 'mysql' */
 
-					needsHexEscape = true;
-					break;
+                    needsHexEscape = true;
+                    break;
 
-				case '\n': /* Must be escaped for logs */
-					needsHexEscape = true;
+                case '\n': /* Must be escaped for logs */
+                    needsHexEscape = true;
 
-					break;
+                    break;
 
-				case '\r':
-					needsHexEscape = true;
-					break;
+                case '\r':
+                    needsHexEscape = true;
+                    break;
 
-				case '\\':
-					needsHexEscape = true;
+                case '\\':
+                    needsHexEscape = true;
 
-					break;
+                    break;
 
-				case '\'':
-					needsHexEscape = true;
+                case '\'':
+                    needsHexEscape = true;
 
-					break;
+                    break;
 
-				case '"': /* Better safe than sorry */
-					needsHexEscape = true;
+                case '"': /* Better safe than sorry */
+                    needsHexEscape = true;
 
-					break;
+                    break;
 
-				case '\032': /* This gives problems on Win32 */
-					needsHexEscape = true;
-					break;
-			}
+                case '\032': /* This gives problems on Win32 */
+                    needsHexEscape = true;
+                    break;
+            }
 
-			if (needsHexEscape) {
-				break; // no need to scan more
-			}
-		}
-		return needsHexEscape;
-	}
+            if (needsHexEscape) {
+                break; // no need to scan more
+            }
+        }
+        return needsHexEscape;
+    }
 
-	/**
-	 * 转义字符串
-	 *
-	 * @param escapeStr
-	 * @return
-	 */
-	public static String escapeString(String escapeStr) {
+    /**
+     * 转义字符串
+     *
+     * @param escapeStr
+     * @return
+     */
+    public static String escapeString(String escapeStr) {
 
-		if (escapeStr.matches("\'(.+)\'")) {
-			escapeStr = escapeStr.substring(1, escapeStr.length() - 1);
-		}
+        if (escapeStr.matches("\'(.+)\'")) {
+            escapeStr = escapeStr.substring(1, escapeStr.length() - 1);
+        }
 
-		String parameterAsString = escapeStr;
-		int stringLength = escapeStr.length();
-		if (isEscapeNeededForString(escapeStr, stringLength)) {
+        String parameterAsString = escapeStr;
+        int stringLength = escapeStr.length();
+        if (isEscapeNeededForString(escapeStr, stringLength)) {
 
-			StringBuilder buf = new StringBuilder((int) (escapeStr.length() * 1.1));
+            StringBuilder buf = new StringBuilder((int) (escapeStr.length() * 1.1));
 
-			//
-			// Note: buf.append(char) is _faster_ than appending in blocks,
-			// because the block append requires a System.arraycopy().... go
-			// figure...
-			//
+            //
+            // Note: buf.append(char) is _faster_ than appending in blocks,
+            // because the block append requires a System.arraycopy().... go
+            // figure...
+            //
 
-			for (int i = 0; i < stringLength; ++i) {
-				char c = escapeStr.charAt(i);
+            for (int i = 0; i < stringLength; ++i) {
+                char c = escapeStr.charAt(i);
 
-				switch (c) {
-					case 0: /* Must be escaped for 'mysql' */
-						buf.append('\\');
-						buf.append('0');
+                switch (c) {
+                    case 0: /* Must be escaped for 'mysql' */
+                        buf.append('\\');
+                        buf.append('0');
 
-						break;
+                        break;
 
-					case '\n': /* Must be escaped for logs */
-						buf.append('\\');
-						buf.append('n');
+                    case '\n': /* Must be escaped for logs */
+                        buf.append('\\');
+                        buf.append('n');
 
-						break;
+                        break;
 
-					case '\r':
-						buf.append('\\');
-						buf.append('r');
+                    case '\r':
+                        buf.append('\\');
+                        buf.append('r');
 
-						break;
+                        break;
 
-					case '\\':
-						buf.append('\\');
-						buf.append('\\');
+                    case '\\':
+                        buf.append('\\');
+                        buf.append('\\');
 
-						break;
+                        break;
 
-					case '\'':
-						buf.append('\\');
-						buf.append('\'');
+                    case '\'':
+                        buf.append('\\');
+                        buf.append('\'');
 
-						break;
+                        break;
 
-					case '"': /* Better safe than sorry */
-						buf.append('\\');
-						buf.append('"');
+                    case '"': /* Better safe than sorry */
+                        buf.append('\\');
+                        buf.append('"');
 
-						break;
+                        break;
 
-					case '\032': /* This gives problems on Win32 */
-						buf.append('\\');
-						buf.append('Z');
+                    case '\032': /* This gives problems on Win32 */
+                        buf.append('\\');
+                        buf.append('Z');
 
-						break;
+                        break;
 
-					default:
-						buf.append(c);
-				}
-			}
+                    default:
+                        buf.append(c);
+                }
+            }
 
-			parameterAsString = buf.toString();
-		}
-		return "\'" + parameterAsString + "\'";
-	}
+            parameterAsString = buf.toString();
+        }
+        return "\'" + parameterAsString + "\'";
+    }
 
 }

+ 576 - 603
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/StringUtils.java

@@ -33,607 +33,580 @@ import java.util.regex.Pattern;
  */
 public class StringUtils {
 
-	/**
-	 * 空字符
-	 */
-	public static final String EMPTY = "";
-
-	/**
-	 * 下划线字符
-	 */
-	public static final char UNDERLINE = '_';
-
-	/**
-	 * 占位符
-	 */
-	public static final String PLACE_HOLDER = "{%s}";
-
-	private StringUtils() {
-	}
-
-	/**
-	 * <p>
-	 * 判断字符串是否为空
-	 * </p>
-	 *
-	 * @param cs
-	 *            需要判断字符串
-	 * @return 判断结果
-	 */
-	public static boolean isEmpty(final CharSequence cs) {
-		int strLen;
-		if (cs == null || (strLen = cs.length()) == 0) {
-			return true;
-		}
-		for (int i = 0; i < strLen; i++) {
-			if (!Character.isWhitespace(cs.charAt(i))) {
-				return false;
-			}
-		}
-		return true;
-	}
-
-	/**
-	 * <p>
-	 * 判断字符串是否不为空
-	 * </p>
-	 *
-	 * @param cs
-	 *            需要判断字符串
-	 * @return 判断结果
-	 */
-	public static boolean isNotEmpty(final CharSequence cs) {
-		return !isEmpty(cs);
-	}
-
-	/**
-	 * <p>
-	 * 字符串驼峰转下划线格式
-	 * </p>
-	 *
-	 * @param param
-	 *            需要转换的字符串
-	 * @return 转换好的字符串
-	 */
-	public static String camelToUnderline(String param) {
-		if (isEmpty(param)) {
-			return EMPTY;
-		}
-		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 temp = param.toLowerCase();
-		int len = temp.length();
-		StringBuilder sb = new StringBuilder(len);
-		for (int i = 0; i < len; i++) {
-			char c = temp.charAt(i);
-			if (c == UNDERLINE) {
-				if (++i < len) {
-					sb.append(Character.toUpperCase(temp.charAt(i)));
-				}
-			} else {
-				sb.append(c);
-			}
-		}
-		return sb.toString();
-	}
-
-	/**
-	 * <p>
-	 * 首字母转换小写
-	 * </p>
-	 *
-	 * @param param
-	 *            需要转换的字符串
-	 * @return 转换好的字符串
-	 */
-	public static String firstToLowerCase(String param) {
-		if (isEmpty(param)) {
-			return EMPTY;
-		}
-		StringBuilder sb = new StringBuilder(param.length());
-		sb.append(param.substring(0, 1).toLowerCase());
-		sb.append(param.substring(1));
-		return sb.toString();
-	}
-
-	/**
-	 * <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>
-	 * SQL 参数填充
-	 * </p>
-	 *
-	 * @param content
-	 *            填充内容
-	 * @param args
-	 *            填充参数
-	 * @return
-	 */
-	public static String sqlArgsFill(String content, Object... args) {
-		if (StringUtils.isEmpty(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;
-	}
-
-	/**
-	 * 获取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 obj
-	 *            原字符串
-	 * @return 单引号包含的原字符串
-	 */
-	public static String quotaMark(Object obj) {
-		String srcStr = String.valueOf(obj);
-		if (obj instanceof CharSequence) {
-			// fix #79
-			return StringEscape.escapeString(srcStr);
-		}
-		return srcStr;
-	}
-
-	/**
-	 * <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());
-			sqlBuild.append(tempVal);
-			if (i + 1 < _size) {
-				sqlBuild.append(",");
-			}
-			i++;
-		}
-		sqlBuild.append(")");
-		return sqlBuild.toString();
-	}
-
-	/**
-	 * <p>
-	 * 拼接字符串第二个字符串第一个字母大写
-	 * </p>
-	 *
-	 * @param concatStr
-	 * @param str
-	 * @return
-	 */
-	public static String concatCapitalize(String concatStr, final String str) {
-		if (isEmpty(concatStr)) {
-			concatStr = EMPTY;
-		}
-		int strLen;
-		if (str == null || (strLen = str.length()) == 0) {
-			return str;
-		}
-
-		final char firstChar = str.charAt(0);
-		if (Character.isTitleCase(firstChar)) {
-			// already capitalized
-			return str;
-		}
-
-		StringBuilder sb = new StringBuilder(strLen);
-		sb.append(concatStr);
-		sb.append(Character.toTitleCase(firstChar));
-		sb.append(str.substring(1));
-		return sb.toString();
-	}
-
-	/**
-	 * <p>
-	 * 字符串第一个字母大写
-	 * </p>
-	 *
-	 * @param str
-	 * @return
-	 */
-	public static String capitalize(final String str) {
-		return concatCapitalize(null, str);
-	}
-
-	/**
-	 * <p>
-	 * 判断对象是否为空
-	 * </p>
-	 *
-	 * @param object
-	 * @return
-	 */
-	public static boolean checkValNotNull(Object object) {
-		if (object instanceof CharSequence) {
-			return isNotEmpty((CharSequence) object);
-		}
-		return object != null;
-	}
-
-	/**
-	 * <p>
-	 * 判断对象是否为空
-	 * </p>
-	 *
-	 * @param object
-	 * @return
-	 */
-	public static boolean checkValNull(Object object) {
-		return !checkValNotNull(object);
-	}
-
-	/**
-	 * <p>
-	 * 包含大写字母
-	 * </p>
-	 * 
-	 * @param word
-	 *            待判断字符串
-	 * @return
-	 */
-	public static boolean containsUpperCase(String word) {
-		for (int i = 0; i < word.length(); i++) {
-			char c = word.charAt(i);
-			if (Character.isUpperCase(c)) {
-				return true;
-			}
-		}
-		return false;
-	}
-
-	/**
-	 * <p>
-	 * 是否为大写命名
-	 * </p>
-	 * 
-	 * @param word
-	 *            待判断字符串
-	 * @return
-	 */
-	public static boolean isCapitalMode(String word) {
-		return null != word && word.matches("^[0-9A-Z/_]+$");
-	}
-
-	/**
-	 * <p>
-	 * Check if a String ends with a specified suffix.
-	 * </p>
-	 *
-	 * <p>
-	 * <code>null</code>s are handled without exceptions. Two <code>null</code>
-	 * references are considered to be equal. The comparison is case sensitive.
-	 * </p>
-	 *
-	 * <pre>
-	 * StringUtils.endsWith(null, null)      = true
-	 * StringUtils.endsWith(null, "abcdef")  = false
-	 * StringUtils.endsWith("def", null)     = false
-	 * StringUtils.endsWith("def", "abcdef") = true
-	 * StringUtils.endsWith("def", "ABCDEF") = false
-	 * </pre>
-	 *
-	 * @see java.lang.String#endsWith(String)
-	 * @param str
-	 *            the String to check, may be null
-	 * @param suffix
-	 *            the suffix to find, may be null
-	 * @return <code>true</code> if the String ends with the suffix, case
-	 *         sensitive, or both <code>null</code>
-	 * @since 2.4
-	 */
-	public static boolean endsWith(String str, String suffix) {
-		return endsWith(str, suffix, false);
-	}
-
-	/**
-	 * <p>
-	 * Case insensitive check if a String ends with a specified suffix.
-	 * </p>
-	 *
-	 * <p>
-	 * <code>null</code>s are handled without exceptions. Two <code>null</code>
-	 * references are considered to be equal. The comparison is case
-	 * insensitive.
-	 * </p>
-	 *
-	 * <pre>
-	 * StringUtils.endsWithIgnoreCase(null, null)      = true
-	 * StringUtils.endsWithIgnoreCase(null, "abcdef")  = false
-	 * StringUtils.endsWithIgnoreCase("def", null)     = false
-	 * StringUtils.endsWithIgnoreCase("def", "abcdef") = true
-	 * StringUtils.endsWithIgnoreCase("def", "ABCDEF") = false
-	 * </pre>
-	 *
-	 * @see java.lang.String#endsWith(String)
-	 * @param str
-	 *            the String to check, may be null
-	 * @param suffix
-	 *            the suffix to find, may be null
-	 * @return <code>true</code> if the String ends with the suffix, case
-	 *         insensitive, or both <code>null</code>
-	 * @since 2.4
-	 */
-	public static boolean endsWithIgnoreCase(String str, String suffix) {
-		return endsWith(str, suffix, true);
-	}
-
-	/**
-	 * <p>
-	 * Check if a String ends with a specified suffix (optionally case
-	 * insensitive).
-	 * </p>
-	 *
-	 * @see java.lang.String#endsWith(String)
-	 * @param str
-	 *            the String to check, may be null
-	 * @param suffix
-	 *            the suffix to find, may be null
-	 * @param ignoreCase
-	 *            inidicates whether the compare should ignore case (case
-	 *            insensitive) or not.
-	 * @return <code>true</code> if the String starts with the prefix or both
-	 *         <code>null</code>
-	 */
-	private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
-		if (str == null || suffix == null) {
-			return (str == null && suffix == null);
-		}
-		if (suffix.length() > str.length()) {
-			return false;
-		}
-		int strOffset = str.length() - suffix.length();
-		return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
-	}
-
-	/**
-	 * <p>
-	 * Splits the provided text into an array, separators specified. This is an
-	 * alternative to using StringTokenizer.
-	 * </p>
-	 *
-	 * <p>
-	 * The separator is not included in the returned String array. Adjacent
-	 * separators are treated as one separator. For more control over the split
-	 * use the StrTokenizer class.
-	 * </p>
-	 *
-	 * <p>
-	 * A {@code null} input String returns {@code null}. A {@code null}
-	 * separatorChars splits on whitespace.
-	 * </p>
-	 *
-	 * <pre>
-	 * StringUtils.split(null, *)         = null
-	 * StringUtils.split("", *)           = []
-	 * StringUtils.split("abc def", null) = ["abc", "def"]
-	 * StringUtils.split("abc def", " ")  = ["abc", "def"]
-	 * StringUtils.split("abc  def", " ") = ["abc", "def"]
-	 * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
-	 * </pre>
-	 *
-	 * @param str
-	 *            the String to parse, may be null
-	 * @param separatorChars
-	 *            the characters used as the delimiters, {@code null} splits on
-	 *            whitespace
-	 * @return an array of parsed Strings, {@code null} if null String input
-	 */
-	public static String[] split(final String str, final String separatorChars) {
-		List<String> strings = splitWorker(str, separatorChars, -1, false);
-		return strings.toArray(new String[strings.size()]);
-	}
-
-	/**
-	 * Performs the logic for the {@code split} and
-	 * {@code splitPreserveAllTokens} methods that return a maximum array
-	 * length.
-	 *
-	 * @param str
-	 *            the String to parse, may be {@code null}
-	 * @param separatorChars
-	 *            the separate character
-	 * @param max
-	 *            the maximum number of elements to include in the array. A zero
-	 *            or negative value implies no limit.
-	 * @param preserveAllTokens
-	 *            if {@code true}, adjacent separators are treated as empty
-	 *            token separators; if {@code false}, adjacent separators are
-	 *            treated as one separator.
-	 * @return an array of parsed Strings, {@code null} if null String input
-	 */
-	public static List<String> splitWorker(final String str, final String separatorChars, final int max,
-			final boolean preserveAllTokens) {
-		// Performance tuned for 2.0 (JDK1.4)
-		// Direct code is quicker than StringTokenizer.
-		// Also, StringTokenizer uses isSpace() not isWhitespace()
-
-		if (str == null) {
-			return null;
-		}
-		final int len = str.length();
-		if (len == 0) {
-			return Collections.emptyList();
-		}
-		final List<String> list = new ArrayList<String>();
-		int sizePlus1 = 1;
-		int i = 0, start = 0;
-		boolean match = false;
-		boolean lastMatch = false;
-		if (separatorChars == null) {
-			// Null separator means use whitespace
-			while (i < len) {
-				if (Character.isWhitespace(str.charAt(i))) {
-					if (match || preserveAllTokens) {
-						lastMatch = true;
-						if (sizePlus1++ == max) {
-							i = len;
-							lastMatch = false;
-						}
-						list.add(str.substring(start, i));
-						match = false;
-					}
-					start = ++i;
-					continue;
-				}
-				lastMatch = false;
-				match = true;
-				i++;
-			}
-		} else if (separatorChars.length() == 1) {
-			// Optimise 1 character case
-			final char sep = separatorChars.charAt(0);
-			while (i < len) {
-				if (str.charAt(i) == sep) {
-					if (match || preserveAllTokens) {
-						lastMatch = true;
-						if (sizePlus1++ == max) {
-							i = len;
-							lastMatch = false;
-						}
-						list.add(str.substring(start, i));
-						match = false;
-					}
-					start = ++i;
-					continue;
-				}
-				lastMatch = false;
-				match = true;
-				i++;
-			}
-		} else {
-			// standard case
-			while (i < len) {
-				if (separatorChars.indexOf(str.charAt(i)) >= 0) {
-					if (match || preserveAllTokens) {
-						lastMatch = true;
-						if (sizePlus1++ == max) {
-							i = len;
-							lastMatch = false;
-						}
-						list.add(str.substring(start, i));
-						match = false;
-					}
-					start = ++i;
-					continue;
-				}
-				lastMatch = false;
-				match = true;
-				i++;
-			}
-		}
-		if (match || preserveAllTokens && lastMatch) {
-			list.add(str.substring(start, i));
-		}
-		return list;
-	}
-
-	/**
-	 * 是否为CharSequence类型
-	 *
-	 * @param cls
-	 * @return
-	 */
-	public static Boolean isCharSequence(Class<?> cls) {
-		return cls != null && CharSequence.class.isAssignableFrom(cls);
-	}
-
-	/**
-	 * 是否为CharSequence类型
-	 *
-	 * @param propertyType
-	 * @return
-	 */
-	public static Boolean isCharSequence(String propertyType) {
-		Class<?> cls;
-		try {
-			cls = Class.forName(propertyType);
-		} catch (ClassNotFoundException e) {
-			return false;
-		}
-		return isCharSequence(cls);
-	}
+    /**
+     * 空字符
+     */
+    public static final String EMPTY = "";
+
+    /**
+     * 下划线字符
+     */
+    public static final char UNDERLINE = '_';
+
+    /**
+     * 占位符
+     */
+    public static final String PLACE_HOLDER = "{%s}";
+
+    private StringUtils() {
+    }
+
+    /**
+     * <p>
+     * 判断字符串是否为空
+     * </p>
+     *
+     * @param cs 需要判断字符串
+     * @return 判断结果
+     */
+    public static boolean isEmpty(final CharSequence cs) {
+        int strLen;
+        if (cs == null || (strLen = cs.length()) == 0) {
+            return true;
+        }
+        for (int i = 0; i < strLen; i++) {
+            if (!Character.isWhitespace(cs.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * <p>
+     * 判断字符串是否不为空
+     * </p>
+     *
+     * @param cs 需要判断字符串
+     * @return 判断结果
+     */
+    public static boolean isNotEmpty(final CharSequence cs) {
+        return !isEmpty(cs);
+    }
+
+    /**
+     * <p>
+     * 字符串驼峰转下划线格式
+     * </p>
+     *
+     * @param param 需要转换的字符串
+     * @return 转换好的字符串
+     */
+    public static String camelToUnderline(String param) {
+        if (isEmpty(param)) {
+            return EMPTY;
+        }
+        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 temp = param.toLowerCase();
+        int len = temp.length();
+        StringBuilder sb = new StringBuilder(len);
+        for (int i = 0; i < len; i++) {
+            char c = temp.charAt(i);
+            if (c == UNDERLINE) {
+                if (++i < len) {
+                    sb.append(Character.toUpperCase(temp.charAt(i)));
+                }
+            } else {
+                sb.append(c);
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * <p>
+     * 首字母转换小写
+     * </p>
+     *
+     * @param param 需要转换的字符串
+     * @return 转换好的字符串
+     */
+    public static String firstToLowerCase(String param) {
+        if (isEmpty(param)) {
+            return EMPTY;
+        }
+        StringBuilder sb = new StringBuilder(param.length());
+        sb.append(param.substring(0, 1).toLowerCase());
+        sb.append(param.substring(1));
+        return sb.toString();
+    }
+
+    /**
+     * <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>
+     * SQL 参数填充
+     * </p>
+     *
+     * @param content 填充内容
+     * @param args    填充参数
+     * @return
+     */
+    public static String sqlArgsFill(String content, Object... args) {
+        if (StringUtils.isEmpty(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;
+    }
+
+    /**
+     * 获取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 obj 原字符串
+     * @return 单引号包含的原字符串
+     */
+    public static String quotaMark(Object obj) {
+        String srcStr = String.valueOf(obj);
+        if (obj instanceof CharSequence) {
+            // fix #79
+            return StringEscape.escapeString(srcStr);
+        }
+        return srcStr;
+    }
+
+    /**
+     * <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());
+            sqlBuild.append(tempVal);
+            if (i + 1 < _size) {
+                sqlBuild.append(",");
+            }
+            i++;
+        }
+        sqlBuild.append(")");
+        return sqlBuild.toString();
+    }
+
+    /**
+     * <p>
+     * 拼接字符串第二个字符串第一个字母大写
+     * </p>
+     *
+     * @param concatStr
+     * @param str
+     * @return
+     */
+    public static String concatCapitalize(String concatStr, final String str) {
+        if (isEmpty(concatStr)) {
+            concatStr = EMPTY;
+        }
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+
+        final char firstChar = str.charAt(0);
+        if (Character.isTitleCase(firstChar)) {
+            // already capitalized
+            return str;
+        }
+
+        StringBuilder sb = new StringBuilder(strLen);
+        sb.append(concatStr);
+        sb.append(Character.toTitleCase(firstChar));
+        sb.append(str.substring(1));
+        return sb.toString();
+    }
+
+    /**
+     * <p>
+     * 字符串第一个字母大写
+     * </p>
+     *
+     * @param str
+     * @return
+     */
+    public static String capitalize(final String str) {
+        return concatCapitalize(null, str);
+    }
+
+    /**
+     * <p>
+     * 判断对象是否为空
+     * </p>
+     *
+     * @param object
+     * @return
+     */
+    public static boolean checkValNotNull(Object object) {
+        if (object instanceof CharSequence) {
+            return isNotEmpty((CharSequence) object);
+        }
+        return object != null;
+    }
+
+    /**
+     * <p>
+     * 判断对象是否为空
+     * </p>
+     *
+     * @param object
+     * @return
+     */
+    public static boolean checkValNull(Object object) {
+        return !checkValNotNull(object);
+    }
+
+    /**
+     * <p>
+     * 包含大写字母
+     * </p>
+     *
+     * @param word 待判断字符串
+     * @return
+     */
+    public static boolean containsUpperCase(String word) {
+        for (int i = 0; i < word.length(); i++) {
+            char c = word.charAt(i);
+            if (Character.isUpperCase(c)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * <p>
+     * 是否为大写命名
+     * </p>
+     *
+     * @param word 待判断字符串
+     * @return
+     */
+    public static boolean isCapitalMode(String word) {
+        return null != word && word.matches("^[0-9A-Z/_]+$");
+    }
+
+    /**
+     * <p>
+     * Check if a String ends with a specified suffix.
+     * </p>
+     * <p>
+     * <p>
+     * <code>null</code>s are handled without exceptions. Two <code>null</code>
+     * references are considered to be equal. The comparison is case sensitive.
+     * </p>
+     * <p>
+     * <pre>
+     * StringUtils.endsWith(null, null)      = true
+     * StringUtils.endsWith(null, "abcdef")  = false
+     * StringUtils.endsWith("def", null)     = false
+     * StringUtils.endsWith("def", "abcdef") = true
+     * StringUtils.endsWith("def", "ABCDEF") = false
+     * </pre>
+     *
+     * @param str    the String to check, may be null
+     * @param suffix the suffix to find, may be null
+     * @return <code>true</code> if the String ends with the suffix, case
+     * sensitive, or both <code>null</code>
+     * @see java.lang.String#endsWith(String)
+     * @since 2.4
+     */
+    public static boolean endsWith(String str, String suffix) {
+        return endsWith(str, suffix, false);
+    }
+
+    /**
+     * <p>
+     * Case insensitive check if a String ends with a specified suffix.
+     * </p>
+     * <p>
+     * <p>
+     * <code>null</code>s are handled without exceptions. Two <code>null</code>
+     * references are considered to be equal. The comparison is case
+     * insensitive.
+     * </p>
+     * <p>
+     * <pre>
+     * StringUtils.endsWithIgnoreCase(null, null)      = true
+     * StringUtils.endsWithIgnoreCase(null, "abcdef")  = false
+     * StringUtils.endsWithIgnoreCase("def", null)     = false
+     * StringUtils.endsWithIgnoreCase("def", "abcdef") = true
+     * StringUtils.endsWithIgnoreCase("def", "ABCDEF") = false
+     * </pre>
+     *
+     * @param str    the String to check, may be null
+     * @param suffix the suffix to find, may be null
+     * @return <code>true</code> if the String ends with the suffix, case
+     * insensitive, or both <code>null</code>
+     * @see java.lang.String#endsWith(String)
+     * @since 2.4
+     */
+    public static boolean endsWithIgnoreCase(String str, String suffix) {
+        return endsWith(str, suffix, true);
+    }
+
+    /**
+     * <p>
+     * Check if a String ends with a specified suffix (optionally case
+     * insensitive).
+     * </p>
+     *
+     * @param str        the String to check, may be null
+     * @param suffix     the suffix to find, may be null
+     * @param ignoreCase inidicates whether the compare should ignore case (case
+     *                   insensitive) or not.
+     * @return <code>true</code> if the String starts with the prefix or both
+     * <code>null</code>
+     * @see java.lang.String#endsWith(String)
+     */
+    private static boolean endsWith(String str, String suffix, boolean ignoreCase) {
+        if (str == null || suffix == null) {
+            return (str == null && suffix == null);
+        }
+        if (suffix.length() > str.length()) {
+            return false;
+        }
+        int strOffset = str.length() - suffix.length();
+        return str.regionMatches(ignoreCase, strOffset, suffix, 0, suffix.length());
+    }
+
+    /**
+     * <p>
+     * Splits the provided text into an array, separators specified. This is an
+     * alternative to using StringTokenizer.
+     * </p>
+     * <p>
+     * <p>
+     * The separator is not included in the returned String array. Adjacent
+     * separators are treated as one separator. For more control over the split
+     * use the StrTokenizer class.
+     * </p>
+     * <p>
+     * <p>
+     * A {@code null} input String returns {@code null}. A {@code null}
+     * separatorChars splits on whitespace.
+     * </p>
+     * <p>
+     * <pre>
+     * StringUtils.split(null, *)         = null
+     * StringUtils.split("", *)           = []
+     * StringUtils.split("abc def", null) = ["abc", "def"]
+     * StringUtils.split("abc def", " ")  = ["abc", "def"]
+     * StringUtils.split("abc  def", " ") = ["abc", "def"]
+     * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+     * </pre>
+     *
+     * @param str            the String to parse, may be null
+     * @param separatorChars the characters used as the delimiters, {@code null} splits on
+     *                       whitespace
+     * @return an array of parsed Strings, {@code null} if null String input
+     */
+    public static String[] split(final String str, final String separatorChars) {
+        List<String> strings = splitWorker(str, separatorChars, -1, false);
+        return strings.toArray(new String[strings.size()]);
+    }
+
+    /**
+     * Performs the logic for the {@code split} and
+     * {@code splitPreserveAllTokens} methods that return a maximum array
+     * length.
+     *
+     * @param str               the String to parse, may be {@code null}
+     * @param separatorChars    the separate character
+     * @param max               the maximum number of elements to include in the array. A zero
+     *                          or negative value implies no limit.
+     * @param preserveAllTokens if {@code true}, adjacent separators are treated as empty
+     *                          token separators; if {@code false}, adjacent separators are
+     *                          treated as one separator.
+     * @return an array of parsed Strings, {@code null} if null String input
+     */
+    public static List<String> splitWorker(final String str, final String separatorChars, final int max,
+                                           final boolean preserveAllTokens) {
+        // Performance tuned for 2.0 (JDK1.4)
+        // Direct code is quicker than StringTokenizer.
+        // Also, StringTokenizer uses isSpace() not isWhitespace()
+
+        if (str == null) {
+            return null;
+        }
+        final int len = str.length();
+        if (len == 0) {
+            return Collections.emptyList();
+        }
+        final List<String> list = new ArrayList<String>();
+        int sizePlus1 = 1;
+        int i = 0, start = 0;
+        boolean match = false;
+        boolean lastMatch = false;
+        if (separatorChars == null) {
+            // Null separator means use whitespace
+            while (i < len) {
+                if (Character.isWhitespace(str.charAt(i))) {
+                    if (match || preserveAllTokens) {
+                        lastMatch = true;
+                        if (sizePlus1++ == max) {
+                            i = len;
+                            lastMatch = false;
+                        }
+                        list.add(str.substring(start, i));
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                }
+                lastMatch = false;
+                match = true;
+                i++;
+            }
+        } else if (separatorChars.length() == 1) {
+            // Optimise 1 character case
+            final char sep = separatorChars.charAt(0);
+            while (i < len) {
+                if (str.charAt(i) == sep) {
+                    if (match || preserveAllTokens) {
+                        lastMatch = true;
+                        if (sizePlus1++ == max) {
+                            i = len;
+                            lastMatch = false;
+                        }
+                        list.add(str.substring(start, i));
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                }
+                lastMatch = false;
+                match = true;
+                i++;
+            }
+        } else {
+            // standard case
+            while (i < len) {
+                if (separatorChars.indexOf(str.charAt(i)) >= 0) {
+                    if (match || preserveAllTokens) {
+                        lastMatch = true;
+                        if (sizePlus1++ == max) {
+                            i = len;
+                            lastMatch = false;
+                        }
+                        list.add(str.substring(start, i));
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                }
+                lastMatch = false;
+                match = true;
+                i++;
+            }
+        }
+        if (match || preserveAllTokens && lastMatch) {
+            list.add(str.substring(start, i));
+        }
+        return list;
+    }
+
+    /**
+     * 是否为CharSequence类型
+     *
+     * @param cls
+     * @return
+     */
+    public static Boolean isCharSequence(Class<?> cls) {
+        return cls != null && CharSequence.class.isAssignableFrom(cls);
+    }
+
+    /**
+     * 是否为CharSequence类型
+     *
+     * @param propertyType
+     * @return
+     */
+    public static Boolean isCharSequence(String propertyType) {
+        Class<?> cls;
+        try {
+            cls = Class.forName(propertyType);
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+        return isCharSequence(cls);
+    }
 }

+ 14 - 13
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SystemClock.java

@@ -1,12 +1,12 @@
 /**
  * Copyright (c) 2011-2020, 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
@@ -50,14 +50,18 @@ public class SystemClock {
         scheduleClockUpdating();
     }
 
-    private static class InstanceHolder {
-        public static final SystemClock INSTANCE = new SystemClock(1);
-    }
-
     private static SystemClock instance() {
         return InstanceHolder.INSTANCE;
     }
 
+    public static long now() {
+        return instance().currentTimeMillis();
+    }
+
+    public static String nowDate() {
+        return new Timestamp(instance().currentTimeMillis()).toString();
+    }
+
     private void scheduleClockUpdating() {
         ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
             public Thread newThread(Runnable runnable) {
@@ -77,12 +81,9 @@ public class SystemClock {
         return now.get();
     }
 
-    public static long now() {
-        return instance().currentTimeMillis();
+    private static class InstanceHolder {
+
+        public static final SystemClock INSTANCE = new SystemClock(1);
     }
-    
-	public static String nowDate() {
-		return new Timestamp(instance().currentTimeMillis()).toString();
-	}
 
 }

+ 1 - 1
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/TableInfoHelper.java

@@ -196,7 +196,7 @@ public class TableInfoHelper {
         if (tableId != null) {
             if (StringUtils.isEmpty(tableInfo.getKeyColumn())) {
                 /*
-				 * 主键策略( 注解 > 全局 > 默认 )
+                 * 主键策略( 注解 > 全局 > 默认 )
 				 */
                 if (IdType.NONE != tableId.type()) {
                     tableInfo.setIdType(tableId.type());

+ 38 - 38
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/VersionUtils.java

@@ -12,43 +12,43 @@ import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
  */
 public class VersionUtils {
 
-	/**
-	 * 比较版本号的大小,前者大则返回一个正数,后者大返回一个负数,相等则返回0
-	 * 
-	 * @param version1
-	 * @param version2
-	 * @return
-	 */
-	public static int compareVersion(String version1, String version2) {
-		if (StringUtils.isEmpty(version1) || StringUtils.isEmpty(version2)) {
-			throw new MybatisPlusException("Error: CompareVersion Error: Illegal Argument !");
-		}
-		// 切割点 ".";
-		String[] versionArray1 = version1.split("\\.");
-		String[] versionArray2 = version2.split("\\.");
-		int idx = 0;
-		// 取最小长度值
-		int minLength = Math.min(versionArray1.length, versionArray2.length);
-		int diff = 0;
-		// 先比较长度 再比较字符
-		while (idx < minLength && (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0
-				&& (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {
-			++idx;
-		}
-		// 如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大;
-		diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length;
-		return diff;
-	}
+    /**
+     * 比较版本号的大小,前者大则返回一个正数,后者大返回一个负数,相等则返回0
+     *
+     * @param version1
+     * @param version2
+     * @return
+     */
+    public static int compareVersion(String version1, String version2) {
+        if (StringUtils.isEmpty(version1) || StringUtils.isEmpty(version2)) {
+            throw new MybatisPlusException("Error: CompareVersion Error: Illegal Argument !");
+        }
+        // 切割点 ".";
+        String[] versionArray1 = version1.split("\\.");
+        String[] versionArray2 = version2.split("\\.");
+        int idx = 0;
+        // 取最小长度值
+        int minLength = Math.min(versionArray1.length, versionArray2.length);
+        int diff = 0;
+        // 先比较长度 再比较字符
+        while (idx < minLength && (diff = versionArray1[idx].length() - versionArray2[idx].length()) == 0
+                && (diff = versionArray1[idx].compareTo(versionArray2[idx])) == 0) {
+            ++idx;
+        }
+        // 如果已经分出大小,则直接返回,如果未分出大小,则再比较位数,有子版本的为大;
+        diff = (diff != 0) ? diff : versionArray1.length - versionArray2.length;
+        return diff;
+    }
 
-	/**
-	 * 比较版本号 true
-	 * 
-	 * @param version1
-	 * @param version2
-	 * @return boolean true v1>=v2 false相反
-	 */
-	public static boolean compare(String version1, String version2) {
-		int num = compareVersion(version1, version2);
-		return num >= 0;
-	}
+    /**
+     * 比较版本号 true
+     *
+     * @param version1
+     * @param version2
+     * @return boolean true v1>=v2 false相反
+     */
+    public static boolean compare(String version1, String version2) {
+        int num = compareVersion(version1, version2);
+        return num >= 0;
+    }
 }

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor