= 7 lat temu
rodzic
commit
3e68744146

+ 127 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/plugins/CachePaginationInterceptor.java

@@ -0,0 +1,127 @@
+/*
+ * 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.Properties;
+
+import org.apache.ibatis.executor.Executor;
+import org.apache.ibatis.executor.statement.StatementHandler;
+import org.apache.ibatis.mapping.BoundSql;
+import org.apache.ibatis.mapping.MappedStatement;
+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.session.ResultHandler;
+import org.apache.ibatis.session.RowBounds;
+
+import com.baomidou.mybatisplus.plugins.pagination.Pagination;
+import com.baomidou.mybatisplus.plugins.parser.ISqlParser;
+import com.baomidou.mybatisplus.plugins.parser.SqlInfo;
+import com.baomidou.mybatisplus.toolkit.SqlUtils;
+
+/**
+ * <p>
+ * 缓存分页拦截器
+ * </p>
+ *
+ * @author hubin
+ * @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})})
+public class CachePaginationInterceptor extends PaginationInterceptor implements Interceptor {
+
+    /**
+     * COUNT SQL 解析
+     */
+    private ISqlParser sqlParser;
+    /**
+     * 溢出总页数,设置第一页
+     */
+    private boolean overflowCurrent = false;
+
+    /**
+     * Physical Pagination Interceptor for all the queries with parameter
+     * {@link org.apache.ibatis.session.RowBounds}
+     */
+    @Override
+    public Object intercept(Invocation invocation) throws Throwable {
+
+        Object target = invocation.getTarget();
+        if (target instanceof StatementHandler) {
+            return super.intercept(invocation);
+        } else {
+            RowBounds rowBounds = (RowBounds) invocation.getArgs()[2];
+            if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
+                return invocation.proceed();
+            }
+            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
+            Executor executor = (Executor) invocation.getTarget();
+            Connection connection = executor.getTransaction().getConnection();
+            Object parameterObject = invocation.getArgs()[1];
+            BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
+            String originalSql = boundSql.getSql();
+            if (rowBounds instanceof Pagination) {
+                Pagination page = (Pagination) rowBounds;
+                if (page.isSearchCount()) {
+                    SqlInfo sqlInfo = SqlUtils.getOptimizeCountSql(page.isOptimizeCountSql(), sqlParser, originalSql);
+                    super.queryTotal(overflowCurrent, sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
+                    if (page.getTotal() <= 0) {
+                        return invocation.proceed();
+                    }
+                }
+            }
+        }
+        return invocation.proceed();
+    }
+
+    @Override
+    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;
+    }
+
+    @Override
+    public void setProperties(Properties prop) {
+
+    }
+
+    @Override
+    public CachePaginationInterceptor setDialectType(String dialectType) {
+        return this;
+    }
+
+    @Override
+    public CachePaginationInterceptor setSqlParser(ISqlParser sqlParser) {
+        this.sqlParser = sqlParser;
+        return this;
+    }
+
+    @Override
+    public CachePaginationInterceptor setOverflowCurrent(boolean overflowCurrent) {
+        this.overflowCurrent = overflowCurrent;
+        return this;
+    }
+
+}

+ 56 - 142
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/plugins/PaginationInterceptor.java

@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2011-2020, hubin (jobob@qq.com).
  * <p>
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -18,21 +18,14 @@ package com.baomidou.mybatisplus.plugins;
 import java.sql.Connection;
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
 import java.util.Properties;
 
-import org.apache.ibatis.builder.StaticSqlSource;
-import org.apache.ibatis.cache.CacheKey;
-import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.executor.statement.StatementHandler;
 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.mapping.SqlCommandType;
-import org.apache.ibatis.mapping.SqlSource;
 import org.apache.ibatis.plugin.Interceptor;
 import org.apache.ibatis.plugin.Intercepts;
 import org.apache.ibatis.plugin.Invocation;
@@ -41,8 +34,6 @@ import org.apache.ibatis.plugin.Signature;
 import org.apache.ibatis.reflection.MetaObject;
 import org.apache.ibatis.reflection.SystemMetaObject;
 import org.apache.ibatis.scripting.defaults.DefaultParameterHandler;
-import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.session.ResultHandler;
 import org.apache.ibatis.session.RowBounds;
 
 import com.baomidou.mybatisplus.MybatisDefaultParameterHandler;
@@ -65,21 +56,13 @@ import com.baomidou.mybatisplus.toolkit.StringUtils;
  * @author hubin
  * @Date 2016-01-23
  */
-@Intercepts({
-    @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 = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class})
-})
+@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
 public class PaginationInterceptor extends SqlParserHandler implements Interceptor {
 
     /**
      * 日志
      */
     private static final Log logger = LogFactory.getLog(PaginationInterceptor.class);
-    /**
-     * Count MappedStatement
-     */
-    private static final Map<String, MappedStatement> countMappedStatements = new HashMap<>();
     /**
      * COUNT SQL 解析
      */
@@ -102,112 +85,82 @@ public class PaginationInterceptor extends SqlParserHandler implements Intercept
     private boolean localPage = false;
 
     /**
-     * Physical Pagination Interceptor for all the queries with parameter {@link RowBounds}
+     * Physical Pagination Interceptor for all the queries with parameter {@link org.apache.ibatis.session.RowBounds}
      */
     @Override
     public Object intercept(Invocation invocation) throws Throwable {
-        Object target = invocation.getTarget();
-        if (target instanceof StatementHandler) {
-            /**
-             * SQL 解析链处理
-             */
-            StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
-            MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
-            this.sqlParser(metaObject);
+        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())) {
             return invocation.proceed();
-        } else if (target instanceof Executor) {
-            /**
-             * PAGE 分页逻辑处理
-             */
-            // 先判断是不是SELECT操作
-            Object[] args = invocation.getArgs();
-            MappedStatement mappedStatement = (MappedStatement) args[0];
-            if (!SqlCommandType.SELECT.equals(mappedStatement.getSqlCommandType())) {
-                return invocation.proceed();
-            }
-            RowBounds rowBounds = (RowBounds) args[2];
-            /* 不需要分页的场合 */
-            if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
-                // 本地线程分页
-                if (localPage) {
-                    // 采用ThreadLocal变量处理的分页
-                    rowBounds = PageHelper.getPagination();
-                    if (rowBounds == null) {
-                        return invocation.proceed();
-                    }
-                } else {
-                    // 无需分页
+        }
+        RowBounds rowBounds = (RowBounds) metaObject.getValue("delegate.rowBounds");
+        /* 不需要分页的场合 */
+        if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
+            // 本地线程分页
+            if (localPage) {
+                // 采用ThreadLocal变量处理的分页
+                rowBounds = PageHelper.getPagination();
+                if (rowBounds == null) {
                     return invocation.proceed();
                 }
-            }
-            Object parameter = args[1];
-            ResultHandler resultHandler = (ResultHandler) args[3];
-            Executor executor = (Executor) invocation.getTarget();
-            CacheKey cacheKey;
-            BoundSql boundSql;
-            if (args.length == 4) {
-                // 4 个参数时
-                boundSql = mappedStatement.getBoundSql(parameter);
-                cacheKey = executor.createCacheKey(mappedStatement, parameter, rowBounds, boundSql);
             } else {
-                // 6 个参数时
-                cacheKey = (CacheKey) args[4];
-                boundSql = (BoundSql) args[5];
+                // 无需分页
+                return invocation.proceed();
             }
-
-            // 针对定义了rowBounds,做为mapper接口方法的参数
-            String originalSql = boundSql.getSql();
-            Connection connection = executor.getTransaction().getConnection();
-            DBType dbType = StringUtils.isNotEmpty(dialectType) ? DBType.getDBType(dialectType) : JdbcUtils.getDbType(connection.getMetaData().getURL());
-            Configuration configuration = mappedStatement.getConfiguration();
-            if (rowBounds instanceof Pagination) {
-                Pagination page = (Pagination) rowBounds;
-                boolean orderBy = true;
-                if (page.isSearchCount()) {
-                    SqlInfo sqlInfo = SqlUtils.getOptimizeCountSql(page.isOptimizeCountSql(), sqlParser, originalSql);
-                    orderBy = sqlInfo.isOrderBy();
-                    // 查询总记录数
-                    this.queryTotal(overflowCurrent, mappedStatement, boundSql, connection, parameter, sqlInfo, page);
+        }
+        // 针对定义了rowBounds,做为mapper接口方法的参数
+        BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
+        String originalSql = boundSql.getSql();
+        Connection connection = (Connection) invocation.getArgs()[0];
+        DBType dbType = StringUtils.isNotEmpty(dialectType) ? DBType.getDBType(dialectType) : JdbcUtils.getDbType(connection.getMetaData().getURL());
+        if (rowBounds instanceof Pagination) {
+            Pagination page = (Pagination) rowBounds;
+            boolean orderBy = true;
+            if (page.isSearchCount()) {
+                SqlInfo sqlInfo = SqlUtils.getOptimizeCountSql(page.isOptimizeCountSql(), sqlParser, originalSql);
+                orderBy = sqlInfo.isOrderBy();
+                this.queryTotal(overflowCurrent, sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
+                if (page.getTotal() <= 0) {
+                    return invocation.proceed();
                 }
-                originalSql = DialectFactory.buildPaginationSql(page, SqlUtils.concatOrderBy(originalSql, page, orderBy), dbType, dialectClazz);
-            } else {
-                // support physical Pagination for RowBounds
-                originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dbType, dialectClazz);
-            }
-            // 查询记录数
-            BoundSql pageBoundSql = new BoundSql(configuration, originalSql, boundSql.getParameterMappings(), parameter);
-            List records = executor.query(mappedStatement, parameter, RowBounds.DEFAULT, resultHandler, cacheKey, pageBoundSql);
-            if (rowBounds instanceof Page) {
-                Page page = (Page) rowBounds;
-                page.setRecords(records);
             }
-            return records;
+            String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
+            originalSql = DialectFactory.buildPaginationSql(page, buildSql, dbType, dialectClazz);
+        } else {
+            // support physical Pagination for RowBounds
+            originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dbType, dialectClazz);
         }
+
+        /*
+         * <p> 禁用内存分页 </p>
+         * <p> 内存分页会查询所有结果出来处理(这个很吓人的),如果结果变化频繁这个数据还会不准。</p>
+         */
+        metaObject.setValue("delegate.boundSql.sql", originalSql);
+        metaObject.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
+        metaObject.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
         return invocation.proceed();
     }
 
     /**
-     * <p>
      * 查询总记录条数
-     * </p>
      *
-     * @param overflowCurrent
+     * @param sql
      * @param mappedStatement
      * @param boundSql
-     * @param connection
-     * @param parameter
-     * @param sqlInfo
      * @param page
      */
-    protected void queryTotal(boolean overflowCurrent, MappedStatement mappedStatement, BoundSql boundSql, Connection connection, Object parameter, SqlInfo sqlInfo, Pagination page) {
-        MappedStatement countMappedStatement = this.getCountMappedStatement(mappedStatement, boundSql, sqlInfo, parameter);
-        try (PreparedStatement statement = connection.prepareStatement(sqlInfo.getSql())) {
-            DefaultParameterHandler parameterHandler = new MybatisDefaultParameterHandler(countMappedStatement, boundSql.getParameterObject(), boundSql);
+    protected void queryTotal(boolean overflowCurrent, String sql, MappedStatement mappedStatement, BoundSql boundSql, Pagination page, Connection connection) {
+        try (PreparedStatement statement = connection.prepareStatement(sql)) {
+            DefaultParameterHandler parameterHandler = new MybatisDefaultParameterHandler(mappedStatement, boundSql.getParameterObject(), boundSql);
             parameterHandler.setParameters(statement);
-            int total = 0;
+            long total = 0;
             try (ResultSet resultSet = statement.executeQuery()) {
                 if (resultSet.next()) {
-                    total = resultSet.getInt(1);
+                    total = resultSet.getLong(1);
                 }
             }
             page.setTotal(total);
@@ -215,7 +168,7 @@ public class PaginationInterceptor extends SqlParserHandler implements Intercept
              * 溢出总页数,设置第一页
              */
             long pages = page.getPages();
-            if (overflowCurrent && (Long.valueOf(page.getCurrent()) > pages)) {
+            if (overflowCurrent && (page.getCurrent() > pages)) {
                 // 设置为第一条
                 page.setCurrent(1);
             }
@@ -224,48 +177,9 @@ public class PaginationInterceptor extends SqlParserHandler implements Intercept
         }
     }
 
-    /**
-     * <p>
-     * 获取 Count MappedStatement 如果存在 countStatementId 使用 XML 中的 SQL 如果不存在构建一个
-     * </p>
-     * <p>
-     * 例如: selectPage 分页查询,自定义 XML COUNT 查询未 selectPageCount
-     * </p>
-     *
-     * @param mappedStatement
-     * @param boundSql
-     * @param sqlInfo
-     * @param parameter
-     * @return
-     */
-    private MappedStatement getCountMappedStatement(MappedStatement mappedStatement, BoundSql boundSql, SqlInfo sqlInfo, Object parameter) {
-        String countStatementId = mappedStatement.getId() + "Count";
-        MappedStatement countMappedStatement = countMappedStatements.get(countStatementId);
-        if (null != countMappedStatement) {
-            // Get Cache
-            return countMappedStatement;
-        }
-        Configuration configuration = mappedStatement.getConfiguration();
-        try {
-            countMappedStatement = configuration.getMappedStatement(countStatementId, false);
-        } catch (Throwable t) {
-            if (null == countMappedStatement) {
-                // 查询结果集
-                BoundSql countBoundSql = new BoundSql(configuration, sqlInfo.getSql(), boundSql.getParameterMappings(), parameter);
-                SqlSource sqlsource = new StaticSqlSource(configuration, countBoundSql.getSql(), countBoundSql.getParameterMappings());
-                MappedStatement.Builder builder = new MappedStatement.Builder(configuration, countStatementId, sqlsource,
-                    SqlCommandType.SELECT);
-                countMappedStatement = builder.build();
-            }
-        }
-        // Cache Count MappedStatement
-        countMappedStatements.put(countStatementId, countMappedStatement);
-        return countMappedStatement;
-    }
-
     @Override
     public Object plugin(Object target) {
-        if (target instanceof StatementHandler || target instanceof Executor) {
+        if (target instanceof StatementHandler) {
             return Plugin.wrap(target, this);
         }
         return target;

+ 6 - 6
mybatis-plus-support/src/main/java/com/baomidou/mybatisplus/service/impl/ServiceImpl.java

@@ -160,7 +160,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
                 } else {
                     /*
                      * 更新成功直接返回,失败执行插入逻辑
-					 */
+                     */
                     return updateById(entity) || insert(entity);
                 }
             } else {
@@ -183,7 +183,7 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
                 } else {
                     /*
                      * 更新成功直接返回,失败执行插入逻辑
-					 */
+                     */
                     return updateAllColumnById(entity) || insertAllColumn(entity);
                 }
             } else {
@@ -405,15 +405,15 @@ public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {
 
     @Override
     public Page<Map<String, Object>> selectMapsPage(Page page, Wrapper<T> wrapper) {
-        wrapper = (Wrapper<T>) SqlHelper.fillWrapper(page,  wrapper);
-        baseMapper.selectMapsPage(page, wrapper);
+        wrapper = (Wrapper<T>) SqlHelper.fillWrapper(page, wrapper);
+        page.setRecords(baseMapper.selectMapsPage(page, wrapper));
         return page;
     }
 
     @Override
     public Page<T> selectPage(Page<T> page, Wrapper<T> wrapper) {
-        wrapper = (Wrapper<T>) SqlHelper.fillWrapper(page,  wrapper);
-        baseMapper.selectPage(page, wrapper);
+        wrapper = (Wrapper<T>) SqlHelper.fillWrapper(page, wrapper);
+        page.setRecords(baseMapper.selectPage(page, wrapper));
         return page;
     }
 }