miemie 4 rokov pred
rodič
commit
c249c60648

+ 21 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/PluginUtils.java

@@ -21,6 +21,7 @@ import org.apache.ibatis.executor.statement.StatementHandler;
 import org.apache.ibatis.mapping.BoundSql;
 import org.apache.ibatis.mapping.MappedStatement;
 import org.apache.ibatis.mapping.ParameterMapping;
+import org.apache.ibatis.mapping.SqlSource;
 import org.apache.ibatis.reflection.MetaObject;
 import org.apache.ibatis.reflection.SystemMetaObject;
 import org.apache.ibatis.session.Configuration;
@@ -66,6 +67,10 @@ public abstract class PluginUtils {
         return new MPBoundSql(boundSql);
     }
 
+    public static MpSqlSource mpSqlSource(SqlSource sqlSource) {
+        return new MpSqlSource(sqlSource);
+    }
+
     public static MPStatementHandler mpStatementHandler(StatementHandler statementHandler) {
         statementHandler = realTarget(statementHandler);
         MetaObject object = SystemMetaObject.forObject(statementHandler);
@@ -154,4 +159,20 @@ public abstract class PluginUtils {
             return (T) boundSql.getValue(property);
         }
     }
+
+    public static class MpSqlSource {
+        private final MetaObject sqlSource;
+
+        public MpSqlSource(SqlSource sqlSource) {
+            this.sqlSource = SystemMetaObject.forObject(sqlSource);
+        }
+
+        public String sql() {
+            return (String) sqlSource.getValue("sqlSource.sql");
+        }
+
+        public void sql(String sql) {
+            sqlSource.setValue("sqlSource.sql", sql);
+        }
+    }
 }

+ 105 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/ReplaceSelectBodyInnerInterceptor.java

@@ -0,0 +1,105 @@
+package com.baomidou.mybatisplus.extension.plugins.inner;
+
+import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.logging.Log;
+import org.apache.ibatis.logging.LogFactory;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+import org.apache.ibatis.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author miemie
+ * @since 2020-11-19
+ */
+public class ReplaceSelectBodyInnerInterceptor implements InnerInterceptor {
+
+    private static final Pattern pattern = Pattern.compile("\\{@((\\w+?)|(\\w+?:\\w+?)|(\\w+?:\\w+?:\\w+?))}");
+    protected final Log logger = LogFactory.getLog(this.getClass());
+
+    @Override
+    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
+        PluginUtils.MpSqlSource source = PluginUtils.mpSqlSource(ms.getSqlSource());
+        String sourceSql = source.sql();
+        List<String> list = find(sourceSql);
+        if (CollectionUtils.isNotEmpty(list)) {
+            sourceSql = getTargetSql(sourceSql, list);
+            source.sql(sourceSql);
+            // then
+            String sql = boundSql.getSql();
+            List<String> find = find(sql);
+            if (CollectionUtils.isNotEmpty(find)) {
+                sql = getTargetSql(sql, find);
+                PluginUtils.mpBoundSql(boundSql).sql(sql);
+            }
+        }
+    }
+
+    protected List<String> find(String sql) {
+        Matcher matcher = pattern.matcher(sql);
+        List<String> list = new ArrayList<>();
+        while (matcher.find()) {
+            list.add(matcher.group());
+        }
+        return list;
+    }
+
+    protected String getTargetSql(String sql, List<String> find) {
+        for (String s : find) {
+            String s1 = s.substring(2, s.length() - 1);
+            int i1 = s1.indexOf(StringPool.COLON);
+            String tableName;
+            String alisa = null;
+            String asAlisa = null;
+            if (i1 < 0) {
+                tableName = s1;
+            } else {
+                tableName = s1.substring(0, i1);
+                s1 = s1.substring(i1 + 1);
+                i1 = s1.indexOf(StringPool.COLON);
+                if (i1 < 0) {
+                    alisa = s1;
+                } else {
+                    alisa = s1.substring(0, i1);
+                    asAlisa = s1.substring(i1 + 1);
+                }
+            }
+            sql = sql.replace(s, getTargetSelectBody(tableName, alisa, asAlisa));
+        }
+        return sql;
+    }
+
+    protected String getTargetSelectBody(String tableName, String alisa, String asAlisa) {
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(tableName);
+        Assert.notNull(tableInfo, "can not find TableInfo Cache by \"%s\"", tableName);
+        String s = tableInfo.chooseSelect(TableFieldInfo::isSelect);
+        if (alisa == null) {
+            return s;
+        }
+        return newSelectBody(s, alisa, asAlisa);
+    }
+
+    protected String newSelectBody(String selectBody, String alisa, String asAlisa) {
+        String[] split = selectBody.split(StringPool.COMMA);
+        StringBuilder sb = new StringBuilder();
+        if (asAlisa == null) {
+            for (String s : split) {
+                sb.append(alisa).append(StringPool.DOT).append(s).append(StringPool.COMMA);
+            }
+        }
+        return sb.deleteCharAt(sb.length() - 1).toString();
+    }
+}

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

@@ -0,0 +1,22 @@
+package com.baomidou.mybatisplus.extension.plugins.inner;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author miemie
+ * @since 2020-11-19
+ */
+class ReplaceSelectBodyInnerInterceptorTest {
+
+    private final ReplaceSelectBodyInnerInterceptor innerInterceptor = new ReplaceSelectBodyInnerInterceptor();
+
+    @Test
+    void find() {
+        List<String> list = innerInterceptor.find("select {@table},{@table:t},{@table:t:r} from table");
+        assertThat(list).contains("{@table}", "{@table:t}", "{@table:t:r}");
+    }
+}

+ 18 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/replaceselectbody/Entity.java

@@ -0,0 +1,18 @@
+package com.baomidou.mybatisplus.test.replaceselectbody;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author miemie
+ * @since 2020-06-23
+ */
+@Data
+public class Entity implements Serializable {
+    private static final long serialVersionUID = 6962439201546719734L;
+
+    private Long id;
+
+    private String name;
+}

+ 19 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/replaceselectbody/EntityMapper.java

@@ -0,0 +1,19 @@
+package com.baomidou.mybatisplus.test.replaceselectbody;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
+
+/**
+ * @author miemie
+ * @since 2020-06-23
+ */
+public interface EntityMapper extends BaseMapper<Entity> {
+
+    @Select("select {@entity} from entity")
+    List<Entity> selectAll();
+
+    @Select("select {@entity:e} from entity e")
+    List<Entity> selectAll2();
+}

+ 52 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/replaceselectbody/ReplaceSelectBodyTest.java

@@ -0,0 +1,52 @@
+package com.baomidou.mybatisplus.test.replaceselectbody;
+
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.ReplaceSelectBodyInnerInterceptor;
+import com.baomidou.mybatisplus.test.BaseDbTest;
+import org.apache.ibatis.plugin.Interceptor;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author miemie
+ * @since 2020-06-23
+ */
+public class ReplaceSelectBodyTest extends BaseDbTest<EntityMapper> {
+
+    @Test
+    void replace() {
+        doTest(i -> {
+            i.selectAll();
+            i.selectAll();
+            i.selectAll();
+            i.selectAll();
+            i.selectAll2();
+            i.selectAll2();
+            i.selectAll2();
+            i.selectAll2();
+        });
+    }
+
+    @Override
+    protected List<Interceptor> interceptors() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        interceptor.addInnerInterceptor(new ReplaceSelectBodyInnerInterceptor());
+        return Collections.singletonList(interceptor);
+    }
+
+    @Override
+    protected String tableDataSql() {
+        return "insert into entity(id,name) values(1,'1'),(2,'2');";
+    }
+
+    @Override
+    protected List<String> tableSql() {
+        return Arrays.asList("drop table if exists entity", "CREATE TABLE IF NOT EXISTS entity (" +
+            "id BIGINT NOT NULL," +
+            "name VARCHAR(30) NULL DEFAULT NULL," +
+            "PRIMARY KEY (id))");
+    }
+}