Browse Source

Merge remote-tracking branch 'origin/3.0' into 3.0

achao 3 năm trước cách đây
mục cha
commit
ac924713e8

+ 5 - 5
build.gradle

@@ -2,7 +2,7 @@ import java.time.LocalDateTime
 
 allprojects {
     group = 'com.baomidou'
-    version = "3.5.0"
+    version = "3.5.0.2-SNAPSHOT"
 }
 
 ext {
@@ -13,7 +13,7 @@ ext {
     libraries = [
         mybatisVersion = '3.5.9',
         mybatisSpringVersion = '2.0.6',
-        mybatisSpringBootStarterVersion = '2.2.0',
+        mybatisSpringBootStarterVersion = '2.2.1',
         springVersion = '5.3.9',
         springBootVersion = '2.5.3',
         jsqlparserVersion = '4.3',
@@ -47,7 +47,7 @@ ext {
         "mybatis-spring-boot-starter": "org.mybatis.spring.boot:mybatis-spring-boot-starter:${mybatisSpringBootStarterVersion}",
         //test
         "spring-test"                : "org.springframework:spring-test:${springVersion}",
-        "assertj-core"               : "org.assertj:assertj-core:3.19.0",
+        "assertj-core"               : "org.assertj:assertj-core:3.22.0",
         "junit-jupiter"              : "org.junit.jupiter:junit-jupiter:${junitVersion}",
         "fastjson"                   : "com.alibaba:fastjson:1.2.76",
         "jackson"                    : "com.fasterxml.jackson.core:jackson-databind:2.12.5",
@@ -60,10 +60,10 @@ ext {
         "oracle"                     : fileTree(dir: 'libs', includes: ['ojdbc-11.2.0.3-jdk16.jar']),
         "dm"                         : fileTree(dir: 'libs', includes: ["jdbcDriver-18.jar"]),
         "kingbase"                   : fileTree(dir: 'libs', includes: ["kingbase8-8.2.0.jar"]),
-        "h2"                         : "com.h2database:h2:1.4.200",
+        "h2"                         : "com.h2database:h2:2.0.206",
         "mysql"                      : "mysql:mysql-connector-java:8.0.26",
         "sqlite"                     : "org.xerial:sqlite-jdbc:3.36.0.3",
-        "firebird"                   : "org.firebirdsql.jdbc:jaybird:4.0.4.java8",
+        "firebird"                   : "org.firebirdsql.jdbc:jaybird:4.0.5.java8",
         //cache
         "mybatis-ehcache"            : "org.mybatis.caches:mybatis-ehcache:1.2.1",
         "mybatis-redis"              : "org.mybatis.caches:mybatis-redis:1.0.0-beta2",

+ 4 - 0
mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/DbType.java

@@ -139,6 +139,10 @@ public enum DbType {
      * CSIIDB
      */
     SAP_HANA("hana", "SAP_HANA数据库"),
+    /**
+     * Impala
+     */
+    IMPALA("impala", "impala数据库"),
     /**
      * UNKONWN DB
      */

+ 3 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfo.java

@@ -28,6 +28,7 @@ import org.apache.ibatis.mapping.ResultFlag;
 import org.apache.ibatis.mapping.ResultMap;
 import org.apache.ibatis.mapping.ResultMapping;
 import org.apache.ibatis.reflection.Reflector;
+import org.apache.ibatis.reflection.SystemMetaObject;
 import org.apache.ibatis.session.Configuration;
 
 import java.lang.reflect.Constructor;
@@ -46,7 +47,6 @@ import static java.util.stream.Collectors.joining;
 @Data
 @Setter(AccessLevel.PACKAGE)
 @Accessors(chain = true)
-@SuppressWarnings("serial")
 public class TableInfo implements Constants {
 
     /**
@@ -189,6 +189,7 @@ public class TableInfo implements Constants {
     @Deprecated
     public TableInfo(Class<?> entityType) {
         this.entityType = entityType;
+        this.reflector = SystemMetaObject.NULL_META_OBJECT.getReflectorFactory().findForClass(entityType);
     }
 
     /**
@@ -224,6 +225,7 @@ public class TableInfo implements Constants {
         Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
         this.configuration = configuration;
         this.underCamel = configuration.isMapUnderscoreToCamelCase();
+        this.reflector = configuration.getReflectorFactory().findForClass(this.entityType);
     }
 
     /**

+ 39 - 0
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/metadata/TableInfoTest.java

@@ -0,0 +1,39 @@
+package com.baomidou.mybatisplus.core.metadata;
+
+import org.apache.ibatis.session.Configuration;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author nieiqurong
+ */
+public class TableInfoTest {
+
+    static class Demo {
+
+        String name;
+
+    }
+
+    @Test
+    void testCreate() {
+        TableInfo tableInfo;
+        Configuration configuration = new Configuration();
+        configuration.setMapUnderscoreToCamelCase(true);
+        tableInfo = new TableInfo(Demo.class);
+        Demo demo = tableInfo.newInstance();
+        tableInfo.setPropertyValue(demo, "name", "test");
+        assertThat(tableInfo.getPropertyValue(demo, "name")).isEqualTo("test");
+        assertThat(tableInfo.isUnderCamel()).isFalse();
+        assertThat(tableInfo.getReflector()).isNotNull();
+        tableInfo.setConfiguration(configuration);
+        assertThat(tableInfo.isUnderCamel()).isTrue();
+        assertThat(tableInfo.getReflector()).isNotNull();
+        tableInfo = new TableInfo(configuration, Object.class);
+        assertThat(tableInfo.isUnderCamel()).isTrue();
+        assertThat(tableInfo.getReflector()).isNotNull();
+    }
+
+
+}

+ 19 - 26
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptor.java

@@ -41,14 +41,7 @@ import org.apache.ibatis.session.RowBounds;
 
 import java.sql.Connection;
 import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Deque;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Properties;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -106,9 +99,9 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
             processSelectBody(withItem.getSubSelect().getSelectBody());
         } else {
             SetOperationList operationList = (SetOperationList) selectBody;
-            List<SelectBody> selectBodys = operationList.getSelects();
-            if (CollectionUtils.isNotEmpty(selectBodys)) {
-                selectBodys.forEach(this::processSelectBody);
+            List<SelectBody> selectBodyList = operationList.getSelects();
+            if (CollectionUtils.isNotEmpty(selectBodyList)) {
+                selectBodyList.forEach(this::processSelectBody);
             }
         }
     }
@@ -280,9 +273,7 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
         // 无 join 时的处理逻辑
         if (fromItem instanceof Table) {
             Table fromTable = (Table) fromItem;
-            if (!tenantLineHandler.ignoreTable(fromTable.getName())) {
-                mainTables.add(fromTable);
-            }
+            mainTables.add(fromTable);
         } else if (fromItem instanceof SubJoin) {
             // SubJoin 类型则还需要添加上 where 条件
             List<Table> tables = processSubJoin((SubJoin) fromItem);
@@ -397,7 +388,7 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
                 processSelectBody(subSelect.getSelectBody());
             }
         } else if (fromItem instanceof ValuesList) {
-            logger.debug("Perform a subquery, if you do not give us feedback");
+            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) {
@@ -433,15 +424,14 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
      * @return List<Table> 右连接查询的 Table 列表
      */
     private List<Table> processJoins(List<Table> mainTables, List<Join> joins) {
-        if (mainTables == null) {
-            mainTables = new ArrayList<>();
-        }
-
         // join 表达式中最终的主表
         Table mainTable = null;
         // 当前 join 的左表
         Table leftTable = null;
-        if (mainTables.size() == 1) {
+
+        if (mainTables == null) {
+            mainTables = new ArrayList<>();
+        } else if (mainTables.size() == 1) {
             mainTable = mainTables.get(0);
             leftTable = mainTable;
         }
@@ -471,19 +461,16 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
 
                 // 当前表是否忽略
                 Table joinTable = joinTables.get(0);
-                boolean joinTableNeedIgnore = tenantLineHandler.ignoreTable(joinTable.getName());
 
                 List<Table> onTables = null;
                 // 如果不要忽略,且是右连接,则记录下当前表
                 if (join.isRight()) {
-                    mainTable = joinTableNeedIgnore ? null : joinTable;
+                    mainTable = joinTable;
                     if (leftTable != null) {
                         onTables = Collections.singletonList(leftTable);
                     }
                 } else if (join.isLeft()) {
-                    if (!joinTableNeedIgnore) {
-                        onTables = Collections.singletonList(joinTable);
-                    }
+                     onTables = Collections.singletonList(joinTable);
                 } else if (join.isInner()) {
                     if (mainTable == null) {
                         onTables = Collections.singletonList(joinTable);
@@ -492,6 +479,7 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
                     }
                     mainTable = null;
                 }
+
                 mainTables = new ArrayList<>();
                 if (mainTable != null) {
                     mainTables.add(mainTable);
@@ -527,7 +515,6 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
                 processOtherFromItem(joinItem);
                 leftTable = null;
             }
-
         }
 
         return mainTables;
@@ -545,8 +532,14 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
         Expression tenantId = tenantLineHandler.getTenantId();
         // 构造每张表的条件
         List<EqualsTo> equalsTos = tables.stream()
+            .filter(x -> !tenantLineHandler.ignoreTable(x.getName()))
             .map(item -> new EqualsTo(getAliasColumn(item), tenantId))
             .collect(Collectors.toList());
+
+        if(CollectionUtils.isEmpty(equalsTos)){
+            return currentExpression;
+        }
+
         // 注入的表达式
         Expression injectExpression = equalsTos.get(0);
         // 如果有多表,则用 and 连接

+ 2 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/DialectFactory.java

@@ -63,7 +63,8 @@ public class DialectFactory {
                 || dbType == DbType.HSQL
                 || dbType == DbType.KINGBASE_ES
                 || dbType == DbType.PHOENIX
-                || dbType == DbType.SAP_HANA) {
+                || dbType == DbType.SAP_HANA
+                || dbType == DbType.IMPALA) {
                 dialect = new PostgreDialect();
             } else if (dbType == DbType.HIGH_GO) {
                 dialect = new HighGoDialect();

+ 6 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/JdbcUtils.java

@@ -25,6 +25,8 @@ import org.apache.ibatis.logging.LogFactory;
 
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Pattern;
 
 /**
@@ -36,6 +38,7 @@ import java.util.regex.Pattern;
 public class JdbcUtils {
 
     private static final Log logger = LogFactory.getLog(JdbcUtils.class);
+    private static final Map<String, DbType> JDBC_DB_TYPE_CACHE = new ConcurrentHashMap<>();
 
     /**
      * 不关闭 Connection,因为是从事务里获取的,sqlSession会负责关闭
@@ -46,7 +49,7 @@ public class JdbcUtils {
     public static DbType getDbType(Executor executor) {
         try {
             Connection conn = executor.getTransaction().getConnection();
-            return getDbType(conn.getMetaData().getURL());
+            return JDBC_DB_TYPE_CACHE.computeIfAbsent(conn.getMetaData().getURL(), k -> getDbType(k));
         } catch (SQLException e) {
             throw ExceptionUtils.mpe(e);
         }
@@ -113,6 +116,8 @@ public class JdbcUtils {
             return DbType.CSIIDB;
         } else if (url.contains(":sap:")) {
             return DbType.SAP_HANA;
+        } else if (url.contains(":impala:")) {
+            return DbType.IMPALA;
         } else {
             logger.warn("The jdbcUrl is " + jdbcUrl + ", Mybatis Plus Cannot Read Database type or The Database's Not Supported!");
             return DbType.OTHER;

+ 3 - 5
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/toolkit/SimpleQuery.java

@@ -178,13 +178,11 @@ public class SimpleQuery {
     public static <A, E> Map<A, List<E>> listGroupBy(List<E> list, SFunction<E, A> sFunction, boolean isParallel, Consumer<E>... peeks) {
         return peekStream(list, isParallel, peeks).collect(HashMap::new, (m, v) -> {
             A key = Optional.ofNullable(v).map(sFunction).orElse(null);
-            List<E> values = m.getOrDefault(key, new ArrayList<>(list.size()));
+            List<E> values = m.computeIfAbsent(key, k -> new ArrayList<>(list.size()));
             values.add(v);
-            m.put(key, values);
-        }, (totalMap, nowMap) -> nowMap.forEach((k, v) -> {
-            List<E> values = totalMap.getOrDefault(k, new ArrayList<>(list.size()));
+        }, (totalMap, nowMap) -> nowMap.forEach((key, v) -> {
+            List<E> values = totalMap.computeIfAbsent(key, k -> new ArrayList<>(list.size()));
             values.addAll(v);
-            totalMap.put(k, values);
         }));
     }
 

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

@@ -94,7 +94,7 @@ public final class SqlHelper {
      */
     public static TableInfo table(Class<?> clazz) {
         TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
-        Assert.notNull(tableInfo, "Error: Cannot execute table Method, ClassGenricType not found .");
+        Assert.notNull(tableInfo, "Error: Cannot execute table Method, ClassGenericType not found.");
         return tableInfo;
     }
 

+ 23 - 0
mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptorTest.java

@@ -5,6 +5,8 @@ import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.LongValue;
 import org.junit.jupiter.api.Test;
 
+import java.util.Objects;
+
 import static org.assertj.core.api.Assertions.assertThat;
 
 /**
@@ -21,6 +23,9 @@ class TenantLineInnerInterceptorTest {
 
         @Override
         public boolean ignoreTable(String tableName) {
+            if (Objects.equals(tableName, "sys_dict")) {
+                return true;
+            }
             return tableName.startsWith("with_as");
         }
     });
@@ -362,6 +367,17 @@ class TenantLineInnerInterceptorTest {
             "SELECT * FROM entity, entity1 " +
                 "WHERE entity.id = entity1.id AND entity.tenant_id = 1 AND entity1.tenant_id = 1");
 
+        // 隐式内连接
+        assertSql("SELECT * FROM entity a, with_as_entity1 b " +
+                "WHERE a.id = b.id",
+            "SELECT * FROM entity a, with_as_entity1 b " +
+                "WHERE a.id = b.id AND a.tenant_id = 1");
+
+        assertSql("SELECT * FROM with_as_entity a, with_as_entity1 b " +
+                "WHERE a.id = b.id",
+            "SELECT * FROM with_as_entity a, with_as_entity1 b " +
+                "WHERE a.id = b.id");
+
         // SubJoin with 隐式内连接
         assertSql("SELECT * FROM (entity,entity1) " +
                 "WHERE entity.id = entity1.id",
@@ -397,6 +413,13 @@ class TenantLineInnerInterceptorTest {
             "WITH with_as_A AS (SELECT * FROM entity WHERE entity.tenant_id = 1) SELECT * FROM with_as_A");
     }
 
+
+    @Test
+    void selectIgnoreTable() {
+        assertSql(" SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)",
+            "SELECT dict.dict_code, item.item_text AS \"text\", item.item_value AS \"value\" FROM sys_dict_item item INNER JOIN sys_dict dict ON dict.id = item.dict_id AND item.tenant_id = 1 WHERE dict.dict_code IN (1, 2, 3) AND item.item_value IN (1, 2, 3)");
+    }
+
     void assertSql(String sql, String targetSql) {
         assertThat(interceptor.parserSingle(sql, null)).isEqualTo(targetSql);
     }