فهرست منبع

发布 2.1.1-SNAPSHOT 支持多租户

hubin 7 سال پیش
والد
کامیت
c12264ccef

+ 84 - 51
build.gradle

@@ -1,10 +1,10 @@
 apply plugin: 'java'
 apply plugin: 'maven'
+apply plugin: 'signing'
 
 ext {
-
     configuration = [
-        javaVersion = JavaVersion.VERSION_1_7
+            javaVersion = JavaVersion.VERSION_1_7
     ]
 
     libraries = [
@@ -12,11 +12,10 @@ ext {
             mybatisVersion = '3.4.5',
             springVersion = '4.3.5.RELEASE',
     ]
-
 }
 
 group = 'com.baomidou'
-version = '2.1.1'
+version = '2.1.1-SNAPSHOT'
 
 description = "Mybatis 增强工具包 - 只做增强不做改变,简化CRUD操作"
 
@@ -24,18 +23,51 @@ sourceCompatibility = "${javaVersion}"
 targetCompatibility = "${javaVersion}"
 
 tasks.withType(JavaCompile) {
-	options.encoding = 'UTF-8'
+    options.encoding = 'UTF-8'
 }
 
 repositories {
     mavenLocal()
-    maven { url 'http://repo.spring.io/plugins-release' }
-    maven { url "https://plugins.gradle.org/m2/" }
-    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/'}
-    mavenCentral()
+    maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
     jcenter()
 }
 
+def common = [
+        "org.springframework:spring-tx:${springVersion}",
+        "org.springframework:spring-jdbc:${springVersion}",
+        "org.springframework:spring-context-support:${springVersion}",
+        "com.zaxxer:HikariCP:2.7.0",
+        "org.apache.velocity:velocity-engine-core:2.0"
+]
+
+dependencies {
+    compile("org.mybatis:mybatis-spring:${mybatisSpringVersion}")
+    compile("org.mybatis:mybatis:${mybatisVersion}")
+    compile("com.github.jsqlparser:jsqlparser:1.1")
+    compileOnly common
+    testCompileOnly("javax.servlet:servlet-api:2.5")
+    testCompile("org.mybatis.caches:mybatis-ehcache:1.1.0")
+    testCompile("ch.qos.logback:logback-classic:1.2.2")
+    testCompile("junit:junit:4.12")
+    testCompile("org.apache.commons:commons-dbcp2:2.1.1") {
+        exclude(module: 'commons-logging')
+    }
+    testCompile("org.apache.commons:commons-pool2:2.4.2")
+    testCompile("com.microsoft.sqlserver:sqljdbc4:4.0")
+    testCompile("org.postgresql:postgresql:9.4.1212")
+    testCompile("com.oracle:ojdbc14:10.2.0.5.0")
+    testCompile("com.h2database:h2:1.4.194")
+    testCompile("mysql:mysql-connector-java:5.1.38")
+    testCompile common
+    testCompile("org.slf4j:slf4j-api:1.7.25")
+    testCompile("org.slf4j:jcl-over-slf4j:1.7.25")
+    testCompile("org.springframework:spring-test:${springVersion}")
+    testCompile("org.springframework:spring-webmvc:${springVersion}")
+    testCompile("org.aspectj:aspectjweaver:1.8.9")
+    testCompile("javax.servlet:servlet-api:2.5")
+    testCompile("org.projectlombok:lombok:1.16.16")
+}
+
 task sourcesJar(type: Jar, dependsOn: classes) {
     classifier = 'sources'
     from sourceSets.main.allSource
@@ -62,55 +94,56 @@ artifacts {
     archives javadocJar
 }
 
-//gradle uploadArchives -Durl=发布仓库地址 -DuserName=用户名 -DpassWord=密码
+signing {
+    sign configurations.archives
+}
+
+// gradle clean build uploadArchives -Dun=用户名 -Dps=密码
 uploadArchives {
-    def repositoryUrl = System.getProperty("url")
-    def userName = System.getProperty("userName")
-    def passWord = System.getProperty("passWord")
     repositories {
         mavenDeployer {
-            repository(url: "$repositoryUrl") {
-                authentication(userName: "${userName}", password: "${passWord}")
+            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }
+
+            def userName = System.getProperty("un")
+            def passWord = System.getProperty("ps")
+            repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
+                authentication(userName: userName, password: passWord)
             }
+
+            snapshotRepository(url: "https://oss.sonatype.org/content/repositories/snapshots/") {
+                authentication(userName: userName, password: passWord)
+            }
+
             pom.version = "$project.version"
             pom.artifactId = "$project.name"
             pom.groupId = "$project.group"
+            pom.project {
+                name 'kisso'
+                packaging 'jar'
+                description 'kisso is a lightweight Java SSO Framework and reusable components.'
+                url 'https://github.com/baomidou/kisso'
+
+                scm {
+                    connection 'scm:git@github.com:Codearte/gradle-nexus-staging-plugin.git'
+                    developerConnection 'scm:git@github.com:Codearte/gradle-nexus-staging-plugin.git'
+                    url 'https://github.com/baomidou/kisso'
+                }
+
+                licenses {
+                    license {
+                        name 'The Apache License, Version 2.0'
+                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
+                    }
+                }
+
+                developers {
+                    developer {
+                        id 'baomidou'
+                        name 'hubin'
+                        email 'jobob@qq.com'
+                    }
+                }
+            }
         }
     }
 }
-
-def common = [
-        "org.springframework:spring-tx:${springVersion}",
-        "org.springframework:spring-jdbc:${springVersion}",
-        "org.springframework:spring-context-support:${springVersion}",
-        "com.alibaba:druid:1.1.0",
-        "org.apache.velocity:velocity:1.7"
-]
-
-dependencies {
-    compile ("org.mybatis:mybatis-spring:${mybatisSpringVersion}")
-    compile ("org.mybatis:mybatis:${mybatisVersion}")
-    compile ("com.github.jsqlparser:jsqlparser:1.1")
-    compileOnly common
-    testCompileOnly("javax.servlet:servlet-api:2.5")
-    testCompile("org.mybatis.caches:mybatis-ehcache:1.1.0")
-    testCompile("ch.qos.logback:logback-classic:1.2.2")
-    testCompile("junit:junit:4.12")
-    testCompile("org.apache.commons:commons-dbcp2:2.1.1") {
-        exclude(module: 'commons-logging')
-    }
-    testCompile("org.apache.commons:commons-pool2:2.4.2")
-    testCompile("com.microsoft.sqlserver:sqljdbc4:4.0")
-    testCompile("org.postgresql:postgresql:9.4.1212")
-    testCompile("com.oracle:ojdbc14:10.2.0.5.0")
-    testCompile("com.h2database:h2:1.4.194")
-    testCompile("mysql:mysql-connector-java:5.1.38")
-    testCompile common
-    testCompile("org.slf4j:slf4j-api:1.7.25")
-    testCompile("org.slf4j:jcl-over-slf4j:1.7.25")
-    testCompile("org.springframework:spring-test:${springVersion}")
-    testCompile("org.springframework:spring-webmvc:${springVersion}")
-    testCompile("org.aspectj:aspectjweaver:1.8.9")
-    testCompile("javax.servlet:servlet-api:2.5")
-    testCompile("org.projectlombok:lombok:1.16.16")
-}

+ 0 - 1
src/main/java/com/baomidou/mybatisplus/generator/AutoGenerator.java

@@ -358,7 +358,6 @@ public class AutoGenerator {
             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);
         }

+ 2 - 1
src/main/java/com/baomidou/mybatisplus/plugins/PaginationInterceptor.java

@@ -57,7 +57,7 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @Date 2016-01-23
  */
 @Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
-public class PaginationInterceptor implements Interceptor {
+public class PaginationInterceptor extends SqlParserHandler implements Interceptor {
 
     // 日志
     private static final Log logger = LogFactory.getLog(PaginationInterceptor.class);
@@ -79,6 +79,7 @@ public class PaginationInterceptor implements Interceptor {
     public Object intercept(Invocation invocation) throws Throwable {
         StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
         MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
+        this.sqlParser(metaObject);
         // 先判断是不是SELECT操作
         MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
         if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {

+ 83 - 0
src/main/java/com/baomidou/mybatisplus/plugins/SqlParserHandler.java

@@ -0,0 +1,83 @@
+/**
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.plugins;
+
+import java.util.List;
+
+import org.apache.ibatis.reflection.MetaObject;
+
+import com.baomidou.mybatisplus.plugins.parser.ISqlParser;
+import com.baomidou.mybatisplus.plugins.parser.ISqlParserFilter;
+import com.baomidou.mybatisplus.plugins.parser.SqlInfo;
+import com.baomidou.mybatisplus.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.toolkit.PluginUtils;
+
+/**
+ * <p>
+ * SQL 解析处理器
+ * </p>
+ *
+ * @author hubin
+ * @Date 2016-08-31
+ */
+public abstract class SqlParserHandler {
+
+    private List<ISqlParser> sqlParserList;
+    private ISqlParserFilter sqlParserFilter;
+
+    /**
+     * 拦截 SQL 解析执行
+     */
+    protected void sqlParser(MetaObject metaObject) {
+        if (null != metaObject) {
+            if (null != this.sqlParserFilter && this.sqlParserFilter.doFilter(metaObject)) {
+                return;
+            }
+            // SQL 解析
+            if (CollectionUtils.isNotEmpty(this.sqlParserList)) {
+                int flag = 0;// 标记是否修改过 SQL
+                String originalSql = (String) metaObject.getValue(PluginUtils.DELEGATE_BOUNDSQL_SQL);
+                for (ISqlParser sqlParser : this.sqlParserList) {
+                    SqlInfo sqlInfo = sqlParser.optimizeSql(metaObject, originalSql);
+                    if (null != sqlInfo) {
+                        originalSql = sqlInfo.getSql();
+                        ++flag;
+                    }
+                }
+                if (flag >= 1) {
+                    metaObject.setValue(PluginUtils.DELEGATE_BOUNDSQL_SQL, originalSql);
+                }
+            }
+        }
+    }
+
+    public List<ISqlParser> getSqlParserList() {
+        return sqlParserList;
+    }
+
+    public SqlParserHandler setSqlParserList(List<ISqlParser> sqlParserList) {
+        this.sqlParserList = sqlParserList;
+        return this;
+    }
+
+    public ISqlParserFilter getSqlParserFilter() {
+        return sqlParserFilter;
+    }
+
+    public void setSqlParserFilter(ISqlParserFilter sqlParserFilter) {
+        this.sqlParserFilter = sqlParserFilter;
+    }
+}

+ 0 - 97
src/main/java/com/baomidou/mybatisplus/plugins/SqlParserInterceptor.java

@@ -1,97 +0,0 @@
-/**
- * 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
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.baomidou.mybatisplus.plugins;
-
-import java.sql.Connection;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.ibatis.executor.statement.StatementHandler;
-import org.apache.ibatis.plugin.Interceptor;
-import org.apache.ibatis.plugin.Intercepts;
-import org.apache.ibatis.plugin.Invocation;
-import org.apache.ibatis.plugin.Plugin;
-import org.apache.ibatis.plugin.Signature;
-import org.apache.ibatis.reflection.MetaObject;
-import org.apache.ibatis.reflection.SystemMetaObject;
-
-import com.baomidou.mybatisplus.plugins.parser.ISqlParser;
-import com.baomidou.mybatisplus.plugins.parser.SqlInfo;
-import com.baomidou.mybatisplus.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.toolkit.PluginUtils;
-
-/**
- * <p>
- * SQL 解析拦截器
- * </p>
- *
- * @author hubin
- * @Date 2016-08-31
- */
-@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
-public class SqlParserInterceptor implements Interceptor {
-
-    private static final String DELEGATE_BOUNDSQL_SQL = "delegate.boundSql.sql";
-    // SQL 解析
-    private List<ISqlParser> sqlParserList;
-
-    /**
-     * 拦截 SQL 解析执行
-     */
-    @Override
-    public Object intercept(Invocation invocation) throws Throwable {
-        StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
-        MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
-        // SQL 解析
-        if (CollectionUtils.isNotEmpty(sqlParserList)) {
-            int flag = 0;// 标记是否修改过 SQL
-            String originalSql = (String) metaObject.getValue(DELEGATE_BOUNDSQL_SQL);
-            for (ISqlParser sqlParser : sqlParserList) {
-                SqlInfo sqlInfo = sqlParser.optimizeSql(metaObject, originalSql);
-                if (null != sqlInfo) {
-                    originalSql = sqlInfo.getSql();
-                    ++flag;
-                }
-            }
-            if (flag >= 1) {
-                metaObject.setValue(DELEGATE_BOUNDSQL_SQL, originalSql);
-            }
-        }
-        return invocation.proceed();
-    }
-
-    @Override
-    public Object plugin(Object target) {
-        if (target instanceof StatementHandler) {
-            return Plugin.wrap(target, this);
-        }
-        return target;
-    }
-
-    @Override
-    public void setProperties(Properties prop) {
-        // to do nothing
-    }
-
-    public List<ISqlParser> getSqlParserList() {
-        return sqlParserList;
-    }
-
-    public SqlParserInterceptor setSqlParserList(List<ISqlParser> sqlParserList) {
-        this.sqlParserList = sqlParserList;
-        return this;
-    }
-}

+ 4 - 2
src/main/java/com/baomidou/mybatisplus/plugins/parser/AbstractJsqlParser.java

@@ -19,6 +19,8 @@ import org.apache.ibatis.logging.Log;
 import org.apache.ibatis.logging.LogFactory;
 import org.apache.ibatis.reflection.MetaObject;
 
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+
 import net.sf.jsqlparser.JSQLParserException;
 import net.sf.jsqlparser.parser.CCJSqlParserUtil;
 import net.sf.jsqlparser.statement.Statement;
@@ -51,12 +53,12 @@ public abstract class AbstractJsqlParser implements ISqlParser {
         if (this.allowProcess(metaObject)) {
             try {
                 Statement statement = CCJSqlParserUtil.parse(sql);
-                logger.debug("old sql: " + sql + ",statement: " + statement);
+                logger.debug("Original SQL: " + sql);
                 if (null != statement) {
                     return this.processParser(statement);
                 }
             } catch (JSQLParserException e) {
-                logger.error("解析sql: " + sql + ",异常: " + e.getMessage());
+                throw new MybatisPlusException("Failed to process, please exclude the tableName or statementId.\n Error SQL: " + sql, e);
             }
         }
         return null;

+ 32 - 0
src/main/java/com/baomidou/mybatisplus/plugins/parser/ISqlParserFilter.java

@@ -0,0 +1,32 @@
+/**
+ * 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
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.baomidou.mybatisplus.plugins.parser;
+
+import org.apache.ibatis.reflection.MetaObject;
+
+/**
+ * <p>
+ * SQL 解析过滤器
+ * </p>
+ *
+ * @author hubin
+ * @Date 2017-09-02
+ */
+public interface ISqlParserFilter {
+
+    boolean doFilter(MetaObject metaObject);
+
+}

+ 0 - 4
src/main/java/com/baomidou/mybatisplus/plugins/tenancy/package-info.java

@@ -1,4 +0,0 @@
-/**
- * mybatis 租户插件实现类
- */
-package com.baomidou.mybatisplus.plugins.tenancy;

+ 1 - 1
src/main/java/com/baomidou/mybatisplus/plugins/tenancy/TenantHandler.java → src/main/java/com/baomidou/mybatisplus/plugins/tenant/TenantHandler.java

@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.baomidou.mybatisplus.plugins.tenancy;
+package com.baomidou.mybatisplus.plugins.tenant;
 
 import net.sf.jsqlparser.expression.Expression;
 

+ 67 - 40
src/main/java/com/baomidou/mybatisplus/plugins/tenancy/TenancySqlParser.java → src/main/java/com/baomidou/mybatisplus/plugins/tenant/TenantSqlParser.java

@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.baomidou.mybatisplus.plugins.tenancy;
+package com.baomidou.mybatisplus.plugins.tenant;
 
 import java.util.List;
 
@@ -53,7 +53,7 @@ import net.sf.jsqlparser.statement.update.Update;
  * @author hubin
  * @since 2017-09-01
  */
-public class TenancySqlParser extends AbstractJsqlParser {
+public class TenantSqlParser extends AbstractJsqlParser {
 
     private TenantHandler tenantHandler;
 
@@ -68,13 +68,14 @@ public class TenancySqlParser extends AbstractJsqlParser {
         } else if (statement instanceof Delete) {
             this.processDelete((Delete) statement);
         }
+        logger.debug("parser sql: " + statement.toString());
         return SqlInfo.newInstance().setSql(statement.toString());
     }
 
     /**
      * select 语句处理
      */
-    public void processSelectBody(SelectBody selectBody) {
+    protected void processSelectBody(SelectBody selectBody) {
         if (selectBody instanceof PlainSelect) {
             processPlainSelect((PlainSelect) selectBody);
         } else if (selectBody instanceof WithItem) {
@@ -98,7 +99,7 @@ public class TenancySqlParser extends AbstractJsqlParser {
      * insert 语句处理
      * </p>
      */
-    public void processInsert(Insert insert) {
+    protected void processInsert(Insert insert) {
         if (this.tenantHandler.doTableFilter(insert.getTable().getName())) {
             // 过滤退出执行
             return;
@@ -109,7 +110,7 @@ public class TenancySqlParser extends AbstractJsqlParser {
         } else if (insert.getItemsList() != null) {
             ((ExpressionList) insert.getItemsList()).getExpressions().add(tenantHandler.getTenantId());
         } else {
-            throw new MybatisPlusException("无法处理的 sql");
+            throw new MybatisPlusException("Failed to process multiple-table update, please exclude the tableName or statementId");
         }
     }
 
@@ -118,20 +119,17 @@ public class TenancySqlParser extends AbstractJsqlParser {
      * update 语句处理
      * </p>
      */
-    public void processUpdate(Update update) {
-        //获得where条件表达式
-        Expression where = update.getWhere();
-        EqualsTo equalsTo = new EqualsTo();
-        if (where instanceof BinaryExpression) {
-            equalsTo.setLeftExpression(new Column(this.tenantHandler.getTenantIdColumn()));
-            equalsTo.setRightExpression(tenantHandler.getTenantId());
-            AndExpression andExpression = new AndExpression(equalsTo, where);
-            update.setWhere(andExpression);
-        } else {
-            equalsTo.setLeftExpression(new Column(this.tenantHandler.getTenantIdColumn()));
-            equalsTo.setRightExpression(tenantHandler.getTenantId());
-            update.setWhere(equalsTo);
+    protected void processUpdate(Update update) {
+        List<Table> tableList = update.getTables();
+        if (null == tableList || tableList.size() >= 2) {
+            throw new MybatisPlusException("Failed to process multiple-table update, please exclude the statementId");
         }
+        Table table = tableList.get(0);
+        if (this.tenantHandler.doTableFilter(table.getName())) {
+            // 过滤退出执行
+            return;
+        }
+        update.setWhere(this.andExpression(table, update.getWhere()));
     }
 
     /**
@@ -139,8 +137,30 @@ public class TenancySqlParser extends AbstractJsqlParser {
      * delete 语句处理
      * </p>
      */
-    public void processDelete(Delete delete) {
+    protected void processDelete(Delete delete) {
+        if (this.tenantHandler.doTableFilter(delete.getTable().getName())) {
+            // 过滤退出执行
+            return;
+        }
+        delete.setWhere(this.andExpression(delete.getTable(), delete.getWhere()));
+    }
 
+    /**
+     * <p>
+     * delete update 语句 where 处理
+     * </p>
+     */
+    protected BinaryExpression andExpression(Table table, Expression where) {
+        //获得where条件表达式
+        EqualsTo equalsTo = new EqualsTo();
+        if (where instanceof BinaryExpression) {
+            equalsTo.setLeftExpression(new Column(this.tenantHandler.getTenantIdColumn()));
+            equalsTo.setRightExpression(tenantHandler.getTenantId());
+            return new AndExpression(equalsTo, where);
+        }
+        equalsTo.setLeftExpression(this.getAliasColumn(table));
+        equalsTo.setRightExpression(tenantHandler.getTenantId());
+        return equalsTo;
     }
 
     /**
@@ -148,7 +168,7 @@ public class TenancySqlParser extends AbstractJsqlParser {
      * 处理 PlainSelect
      * </p>
      */
-    public void processPlainSelect(PlainSelect plainSelect) {
+    protected void processPlainSelect(PlainSelect plainSelect) {
         processPlainSelect(plainSelect, false);
     }
 
@@ -160,7 +180,7 @@ public class TenancySqlParser extends AbstractJsqlParser {
      * @param plainSelect
      * @param addColumn   是否添加租户列,insert into select语句中需要
      */
-    public void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
+    protected void processPlainSelect(PlainSelect plainSelect, boolean addColumn) {
         FromItem fromItem = plainSelect.getFromItem();
         if (fromItem instanceof Table) {
             Table fromTable = (Table) fromItem;
@@ -184,11 +204,10 @@ public class TenancySqlParser extends AbstractJsqlParser {
         }
     }
 
-
     /**
      * 处理子查询等
      */
-    public void processFromItem(FromItem fromItem) {
+    protected void processFromItem(FromItem fromItem) {
         if (fromItem instanceof SubJoin) {
             SubJoin subJoin = (SubJoin) fromItem;
             if (subJoin.getJoin() != null) {
@@ -203,7 +222,7 @@ public class TenancySqlParser extends AbstractJsqlParser {
                 processSelectBody(subSelect.getSelectBody());
             }
         } else if (fromItem instanceof ValuesList) {
-
+            logger.debug("Perform a subquery, if you do not give us feedback");
         } else if (fromItem instanceof LateralSubSelect) {
             LateralSubSelect lateralSubSelect = (LateralSubSelect) fromItem;
             if (lateralSubSelect.getSubSelect() != null) {
@@ -218,7 +237,7 @@ public class TenancySqlParser extends AbstractJsqlParser {
     /**
      * 处理联接语句
      */
-    public void processJoin(Join join) {
+    protected void processJoin(Join join) {
         if (join.getRightItem() instanceof Table) {
             Table fromTable = (Table) join.getRightItem();
             if (this.tenantHandler.doTableFilter(fromTable.getName())) {
@@ -232,25 +251,14 @@ public class TenancySqlParser extends AbstractJsqlParser {
     /**
      * 处理条件
      */
-    public Expression builderExpression(Expression expression, Table table) {
-        Expression tenantExpression = null;
-        //当传入table时,字段前加上别名或者table名
-        //别名优先使用
-        StringBuilder tenantIdColumnName = new StringBuilder();
-        if (table != null) {
-            tenantIdColumnName.append(table.getAlias() != null ? table.getAlias().getName() : table.getName());
-            tenantIdColumnName.append(".");
-        }
-        tenantIdColumnName.append(this.tenantHandler.getTenantIdColumn());
+    protected Expression builderExpression(Expression expression, Table table) {
         //生成字段名
-        Column tenantColumn = new Column(tenantIdColumnName.toString());
         EqualsTo equalsTo = new EqualsTo();
-        tenantExpression = equalsTo;
-        equalsTo.setLeftExpression(tenantColumn);
+        equalsTo.setLeftExpression(this.getAliasColumn(table));
         equalsTo.setRightExpression(tenantHandler.getTenantId());
         //加入判断防止条件为空时生成 "and null" 导致查询结果为空
         if (expression == null) {
-            return tenantExpression;
+            return equalsTo;
         } else {
             if (expression instanceof BinaryExpression) {
                 BinaryExpression binaryExpression = (BinaryExpression) expression;
@@ -261,8 +269,27 @@ public class TenancySqlParser extends AbstractJsqlParser {
                     processFromItem((FromItem) binaryExpression.getRightExpression());
                 }
             }
-            return new AndExpression(tenantExpression, expression);
+            return new AndExpression(equalsTo, expression);
+        }
+    }
+
+    /**
+     * <p>
+     * 字段是否添加别名设置
+     * </p>
+     *
+     * @param table 表对象
+     * @return 字段
+     */
+    protected Column getAliasColumn(Table table) {
+        if (null == table.getAlias()) {
+            return new Column(this.tenantHandler.getTenantIdColumn());
         }
+        StringBuilder column = new StringBuilder();
+        column.append(table.getAlias().getName());
+        column.append(".");
+        column.append(this.tenantHandler.getTenantIdColumn());
+        return new Column(column.toString());
     }
 
     public TenantHandler getTenantHandler() {

+ 4 - 0
src/main/java/com/baomidou/mybatisplus/plugins/tenant/package-info.java

@@ -0,0 +1,4 @@
+/**
+ * mybatis 租户插件实现类
+ */
+package com.baomidou.mybatisplus.plugins.tenant;

+ 16 - 0
src/main/java/com/baomidou/mybatisplus/toolkit/PluginUtils.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.toolkit;
 import java.lang.reflect.Proxy;
 import java.util.Properties;
 
+import org.apache.ibatis.mapping.MappedStatement;
 import org.apache.ibatis.reflection.MetaObject;
 import org.apache.ibatis.reflection.SystemMetaObject;
 
@@ -31,10 +32,25 @@ import org.apache.ibatis.reflection.SystemMetaObject;
  */
 public final class PluginUtils {
 
+    public static final String DELEGATE_BOUNDSQL_SQL = "delegate.boundSql.sql";
+    public static final String DELEGATE_MAPPEDSTATEMENT = "delegate.mappedStatement";
+
     private PluginUtils() {
         // to do nothing
     }
 
+    /**
+     * <p>
+     * 获取当前执行 MappedStatement
+     * </p>
+     *
+     * @param metaObject 元对象
+     * @return
+     */
+    public static MappedStatement getMappedStatement(MetaObject metaObject) {
+        return (MappedStatement) metaObject.getValue(DELEGATE_MAPPEDSTATEMENT);
+    }
+
     /**
      * <p>
      * 获得真正的处理对象,可能多层代理.

+ 1 - 1
src/test/java/com/baomidou/mybatisplus/test/generator/MysqlGenerator.java

@@ -91,7 +91,7 @@ public class MysqlGenerator {
                         })
                         .setDriverName("com.mysql.jdbc.Driver")
                         .setUsername("root")
-                        .setPassword("521")
+                        .setPassword("123456")
                         .setUrl("jdbc:mysql://127.0.0.1:3306/mybatis-plus?characterEncoding=utf8")
         ).setStrategy(
                 // 策略配置

+ 3 - 4
src/test/java/com/baomidou/mybatisplus/test/oracle/config/DruidOracleDBConfig.java

@@ -7,7 +7,7 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.jdbc.datasource.DataSourceTransactionManager;
 import org.springframework.transaction.annotation.EnableTransactionManagement;
 
-import com.alibaba.druid.pool.DruidDataSource;
+import com.zaxxer.hikari.HikariDataSource;
 
 /**
  * <p>
@@ -22,8 +22,8 @@ public class DruidOracleDBConfig {
 
     @Bean
     public DataSource getDruidDataSource() {
-        DruidDataSource dataSource = new DruidDataSource();
-        dataSource.setUrl("jdbc:oracle:thin:@192.168.10.169:1521:orcl");
+        HikariDataSource dataSource = new HikariDataSource();
+        dataSource.setJdbcUrl("jdbc:oracle:thin:@192.168.10.169:1521:orcl");
         dataSource.setUsername("sa");
         dataSource.setPassword("sa");
         return dataSource;
@@ -33,5 +33,4 @@ public class DruidOracleDBConfig {
     public DataSourceTransactionManager transactionManager(DataSource ds) {
         return new DataSourceTransactionManager(ds);
     }
-
 }

+ 0 - 67
src/test/java/com/baomidou/mybatisplus/test/sql/TenancySqlTest.java

@@ -1,67 +0,0 @@
-package com.baomidou.mybatisplus.test.sql;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.baomidou.mybatisplus.plugins.parser.SqlInfo;
-import com.baomidou.mybatisplus.plugins.tenancy.TenancySqlParser;
-import com.baomidou.mybatisplus.plugins.tenancy.TenantHandler;
-
-import net.sf.jsqlparser.expression.Expression;
-import net.sf.jsqlparser.expression.LongValue;
-
-/**
- * <p>
- * 租户 SQL 测试
- * </p>
- *
- * @author hubin
- * @since 2017-09-01
- */
-public class TenancySqlTest {
-
-    private TenancySqlParser tenancySqlParser;
-
-    @Before
-    public void setUp() throws Exception {
-        tenancySqlParser = new TenancySqlParser();
-        tenancySqlParser.setTenantHandler(new TenantHandler() {
-            @Override
-            public Expression getTenantId() {
-                return new LongValue(1000L);
-            }
-
-            @Override
-            public String getTenantIdColumn() {
-                return "tenant_id";
-            }
-
-            @Override
-            public boolean doTableFilter(String tableName) {
-                if ("user".equals(tableName)) {
-                    return true;
-                }
-                return false;
-            }
-        });
-    }
-
-    @Test
-    public void filter() {
-        SqlInfo sqlInfo = tenancySqlParser.optimizeSql(null, "select * from user");
-        Assert.assertEquals("SELECT * FROM user", sqlInfo.getSql());
-    }
-
-    @Test
-    public void test() {
-        SqlInfo sqlInfo = tenancySqlParser.optimizeSql(null, "select aaa, bbb,(select ccc from role) as ccc from user");
-        Assert.assertEquals("SELECT aaa, bbb, (SELECT ccc FROM role) AS ccc FROM user WHERE user.tenant_id = 1000", sqlInfo.getSql());
-    }
-
-    @Test
-    public void join() {
-        SqlInfo sqlInfo = tenancySqlParser.optimizeSql(null, "SELECT u.aaa, r.bbb FROM role r left JOIN user u WHERE r.id=u.id");
-        Assert.assertEquals("SELECT u.aaa, r.bbb FROM role r LEFT JOIN user u WHERE r.tenant_id = 1000 AND r.id = u.id", sqlInfo.getSql());
-    }
-}

+ 150 - 0
src/test/java/com/baomidou/mybatisplus/test/sql/TenantSqlTest.java

@@ -0,0 +1,150 @@
+package com.baomidou.mybatisplus.test.sql;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.plugins.parser.SqlInfo;
+import com.baomidou.mybatisplus.plugins.tenant.TenantSqlParser;
+import com.baomidou.mybatisplus.plugins.tenant.TenantHandler;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.expression.LongValue;
+
+/**
+ * <p>
+ * 租户 SQL 测试
+ * </p>
+ *
+ * @author hubin
+ * @since 2017-09-01
+ */
+public class TenantSqlTest {
+
+    private TenantSqlParser tenantSqlParser;
+
+    @Before
+    public void setUp() throws Exception {
+        tenantSqlParser = new TenantSqlParser();
+        tenantSqlParser.setTenantHandler(new TenantHandler() {
+            @Override
+            public Expression getTenantId() {
+                return new LongValue(1000L);
+            }
+
+            @Override
+            public String getTenantIdColumn() {
+                return "tenant_id";
+            }
+
+            @Override
+            public boolean doTableFilter(String tableName) {
+                if ("user".equals(tableName)) {
+                    return true;
+                }
+                return false;
+            }
+        });
+    }
+
+    // ----------------------------    insert 测试     ----------------------------
+    @Test
+    public void intsertFilter() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "INSERT INTO user (c1, c2, c3) VALUES (?, 'asd', 123)");
+        Assert.assertEquals("INSERT INTO user (c1, c2, c3) VALUES (?, 'asd', 123)", sqlInfo.getSql());
+    }
+
+    @Test
+    public void intsert() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "INSERT INTO role (c1, c2, c3) VALUES (?, 'asd', 123)");
+        Assert.assertEquals("INSERT INTO role (c1, c2, c3, tenant_id) VALUES (?, 'asd', 123, 1000)", sqlInfo.getSql());
+    }
+
+    @Test
+    public void intsertInto() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "insert into role (c1, c2, c3) SELECT * FROM bak");
+        System.out.println(sqlInfo.getSql());
+        Assert.assertEquals("INSERT INTO role (c1, c2, c3, tenant_id) SELECT *, tenant_id FROM bak WHERE tenant_id = 1000", sqlInfo.getSql());
+    }
+
+    // ----------------------------    delete 测试     ----------------------------
+    @Test
+    public void deleteFilter() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "DELETE FROM user t WHERE t.c1 = 9");
+        Assert.assertEquals("DELETE FROM user t WHERE t.c1 = 9", sqlInfo.getSql());
+    }
+
+    @Test(expected = MybatisPlusException.class)
+    public void deleteLimit() {
+        tenantSqlParser.optimizeSql(null, "delete FROM role WHERE A.cod_table = 'YYY' LIMIT 3,4");
+    }
+
+    @Test
+    public void deleteOrderBy() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "DELETE FROM tablename WHERE a = 1 AND b = 1 ORDER BY col");
+        Assert.assertEquals("DELETE FROM tablename WHERE tenant_id = 1000 AND a = 1 AND b = 1 ORDER BY col", sqlInfo.getSql());
+    }
+
+    @Test
+    public void deleteJoin() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "DELETE gc FROM guide_category AS gc LEFT JOIN guide AS g ON g.id_guide = gc.id_guide WHERE g.title IS NULL LIMIT 5");
+        Assert.assertEquals("DELETE gc FROM guide_category AS gc LEFT JOIN guide AS g ON g.id_guide = gc.id_guide WHERE gc.tenant_id = 1000 LIMIT 5", sqlInfo.getSql());
+    }
+
+    // ----------------------------    update 测试     ----------------------------
+    @Test
+    public void updateFilter() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "UPDATE user set c1='as', c2=?, c3=565 Where o >= 3");
+        Assert.assertEquals("UPDATE user SET c1 = 'as', c2 = ?, c3 = 565 WHERE o >= 3", sqlInfo.getSql());
+    }
+
+    @Test
+    public void updateSet() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "UPDATE role set c1='as', c2=?, c3=565 Where o >= 3");
+        Assert.assertEquals("UPDATE role SET c1 = 'as', c2 = ?, c3 = 565 WHERE tenant_id = 1000 AND o >= 3", sqlInfo.getSql());
+    }
+
+    @Test
+    public void updateSetJoin() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "UPDATE role SET c1 = 5 FROM role LEFT JOIN user ON c1 = c2 Where o >= 3");
+        Assert.assertEquals("UPDATE role SET c1 = 5 FROM role LEFT JOIN user ON c1 = c2 WHERE tenant_id = 1000 AND o >= 3", sqlInfo.getSql());
+    }
+
+    // ----------------------------    select 测试     ----------------------------
+    @Test
+    public void selectFilter() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "select * from user");
+        Assert.assertEquals("SELECT * FROM user", sqlInfo.getSql());
+    }
+
+    @Test
+    public void selectFilter1() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "select u.name,r.id FROM user u, role r");
+        Assert.assertEquals("SELECT u.name, r.id FROM user u, role r", sqlInfo.getSql());
+    }
+
+    @Test
+    public void selectChild() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "select aaa, bbb,(select ccc from user) as ccc from role");
+        Assert.assertEquals("SELECT aaa, bbb, (SELECT ccc FROM user) AS ccc FROM role WHERE tenant_id = 1000", sqlInfo.getSql());
+    }
+
+    @Test
+    public void selectChild1() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "select name from role where  id= (select rid from user where id=1 )");
+        Assert.assertEquals("SELECT name FROM role WHERE tenant_id = 1000 AND id = (SELECT rid FROM user WHERE id = 1)", sqlInfo.getSql());
+    }
+
+    @Test
+    public void selectJoin() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "SELECT u.aaa, r.bbb FROM role r left JOIN user u WHERE r.id=u.id");
+        Assert.assertEquals("SELECT u.aaa, r.bbb FROM role r LEFT JOIN user u WHERE r.tenant_id = 1000 AND r.id = u.id", sqlInfo.getSql());
+    }
+
+    @Test
+    public void selectJoin1() {
+        SqlInfo sqlInfo = tenantSqlParser.optimizeSql(null, "SELECT u.aaa, r.bbb FROM role r LEFT JOIN user u ON r.id=u.id LEFT JOIN teacher t ON r.id=t.id ");
+        Assert.assertEquals("SELECT u.aaa, r.bbb FROM role r LEFT JOIN user u ON r.id = u.id LEFT JOIN teacher t ON t.tenant_id = 1000 AND r.id = t.id WHERE r.tenant_id = 1000", sqlInfo.getSql());
+    }
+}

+ 52 - 68
src/test/resources/spring/spring-jdbc.xml

@@ -1,76 +1,60 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
-	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
 	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
-	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
-	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">
+	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
+	http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
 
-	<!-- 加载配置文件 -->
-	<context:property-placeholder location="classpath:properties/jdbc.properties" />
+    <!-- 加载配置文件 -->
+    <context:property-placeholder location="classpath:properties/jdbc.properties"/>
 
-	<!-- 数据库连接池 -->
-	<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
-		destroy-method="close">
-		<property name="url" value="${jdbc.url}" />
-		<property name="username" value="${jdbc.username}" />
-		<property name="password" value="${jdbc.password}" />
-		<property name="driverClassName" value="${jdbc.driver}" />
-		<!-- 初始化连接大小 -->
-		<property name="initialSize" value="0" />
-		<!-- 连接池最大使用连接数量 -->
-		<property name="maxActive" value="20" />
-		<!-- 连接池最大空闲 -->
-		<property name="maxIdle" value="20" />
-		<!-- 连接池最小空闲 -->
-		<property name="minIdle" value="0" />
-		<!-- 获取连接最大等待时间 -->
-		<property name="maxWait" value="60000" />
-		<property name="validationQuery" value="${validationQuery}" />
-		<property name="testOnBorrow" value="false" />
-		<property name="testOnReturn" value="false" />
-		<property name="testWhileIdle" value="true" />
-		<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
-		<property name="timeBetweenEvictionRunsMillis" value="60000" />
-		<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
-		<property name="minEvictableIdleTimeMillis" value="25200000" />
-		<!-- 打开removeAbandoned功能 -->
-		<property name="removeAbandoned" value="true" />
-		<!-- 1800秒,也就是30分钟 -->
-		<property name="removeAbandonedTimeout" value="1800" />
-		<!-- 关闭abanded连接时输出错误日志 -->
-		<property name="logAbandoned" value="true" />
-		<!-- 监控数据库 -->
-		<property name="filters" value="stat" />
-	</bean>
+    <!-- 数据库连接池 -->
+    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
+        <property name="driverClassName" value="${jdbc.driver}"/>
+        <property name="jdbcUrl" value="${jdbc.url}"/>
+        <property name="username" value="${jdbc.username}"/>
+        <property name="password" value="${jdbc.password}"/>
+        <property name="maximumPoolSize" value="100"/>
+        <property name="minimumIdle" value="10"/>
+        <property name="connectionTestQuery" value="select 1"/>
+        <property name="dataSourceProperties">
+            <props>
+                <prop key="cachePrepStmts">true</prop>
+                <prop key="prepStmtCacheSize">250</prop>
+                <prop key="prepStmtCacheSqlLimit">2048</prop>
+                <prop key="useServerPrepStmts">true</prop>
+            </props>
+        </property>
+    </bean>
 
-	<!-- 事务管理器 -->
-	<bean id="transactionManager"
-		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
-		<!-- 数据源 -->
-		<property name="dataSource" ref="dataSource" />
-	</bean>
+    <!-- 事务管理器 -->
+    <bean id="transactionManager"
+          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
+        <!-- 数据源 -->
+        <property name="dataSource" ref="dataSource"/>
+    </bean>
 
-	<!-- 通知 -->
-	<tx:advice id="txAdvice" transaction-manager="transactionManager">
-		<tx:attributes>
-			<!-- 传播行为 -->
-			<tx:method name="save*" propagation="REQUIRED" />
-			<tx:method name="insert*" propagation="REQUIRED" />
-			<tx:method name="add*" propagation="REQUIRED" />
-			<tx:method name="create*" propagation="REQUIRED" />
-			<tx:method name="delete*" propagation="REQUIRED" />
-			<tx:method name="update*" propagation="REQUIRED" />
-			<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
-			<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
-			<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
-		</tx:attributes>
-	</tx:advice>
-	<!-- 切面 -->
-	<aop:config>
-		<aop:advisor advice-ref="txAdvice"
-			pointcut="execution(* com.baomidou.*.service.*.*.*(..))" />
-	</aop:config>
+    <!-- 通知 -->
+    <tx:advice id="txAdvice" transaction-manager="transactionManager">
+        <tx:attributes>
+            <!-- 传播行为 -->
+            <tx:method name="save*" propagation="REQUIRED"/>
+            <tx:method name="insert*" propagation="REQUIRED"/>
+            <tx:method name="add*" propagation="REQUIRED"/>
+            <tx:method name="create*" propagation="REQUIRED"/>
+            <tx:method name="delete*" propagation="REQUIRED"/>
+            <tx:method name="update*" propagation="REQUIRED"/>
+            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
+            <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
+            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
+        </tx:attributes>
+    </tx:advice>
+    <!-- 切面 -->
+    <aop:config>
+        <aop:advisor advice-ref="txAdvice"
+                     pointcut="execution(* com.baomidou.*.service.*.*.*(..))"/>
+    </aop:config>
 </beans>