Browse Source

复用count缓存,减少count查询.

聂秋秋 5 năm trước cách đây
mục cha
commit
eb63b11cbb

+ 7 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/executor/MybatisCachingExecutor.java

@@ -122,13 +122,19 @@ public class MybatisCachingExecutor implements Executor {
                         if (page.isSearchCount()) {
                             // 这里的执行sql为原select语句,标准一点的是需要将此转换为count语句当做缓存key的,留做当优化把.
                             countCacheKey = getCountCacheKey(ms, boundSql, parameterObject, RowBounds.DEFAULT);
+                            // 复用count结果缓存,减少count查询.
+                            Number count = (Number) tcm.getObject(cache, countCacheKey);
+                            if (count != null) {
+                                page.hitCount(true);
+                                page.setTotal(count.longValue());
+                            }
                         }
                         // 切勿将这提取至上方,如果先查的话,需要提前将boundSql拷贝一份
                         result = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
                         List<E> records = (List<E>) result;
                         page.setRecords(records);
                         tcm.putObject(cache, key, records);
-                        if (countCacheKey != null) {
+                        if (countCacheKey != null && !page.isHitCount()) {
                             tcm.putObject(cache, countCacheKey, page.getTotal());
                         }
                         return new PageList(records, page.getTotal());

+ 20 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/IPage.java

@@ -116,6 +116,26 @@ public interface IPage<T> extends Serializable {
         return this;
     }
 
+    /**
+     * 设置是否命中count缓存
+     *
+     * @param hit 是否命中
+     * @since 3.3.1
+     */
+    default void hitCount(boolean hit) {
+
+    }
+
+    /**
+     * 是否命中count缓存
+     *
+     * @return 是否命中count缓存
+     * @since 3.3.1
+     */
+    default boolean isHitCount() {
+        return false;
+    }
+
     /**
      * 分页记录列表
      *

+ 1 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/PaginationInterceptor.java

@@ -213,7 +213,7 @@ public class PaginationInterceptor extends AbstractSqlParserHandler implements I
         String originalSql = boundSql.getSql();
         Connection connection = (Connection) invocation.getArgs()[0];
 
-        if (page.isSearchCount()) {
+        if (page.isSearchCount() && !page.isHitCount()) {
             SqlInfo sqlInfo = SqlParserUtils.getOptimizeCountSql(page.optimizeCountSql(), countSqlParser, originalSql);
             this.queryTotal(sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
             if (page.getTotal() <= 0) {

+ 14 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/Page.java

@@ -68,6 +68,10 @@ public class Page<T> implements IPage<T> {
      * 是否进行 count 查询
      */
     private boolean isSearchCount = true;
+    /**
+     * 是否命中count缓存
+     */
+    private boolean hitCount = false;
 
     public Page() {
     }
@@ -342,4 +346,14 @@ public class Page<T> implements IPage<T> {
         this.optimizeCountSql = optimizeCountSql;
         return this;
     }
+
+    @Override
+    public void hitCount(boolean hit) {
+        this.hitCount = hit;
+    }
+
+    @Override
+    public boolean isHitCount() {
+        return hitCount;
+    }
 }

+ 6 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/cache/CacheTest.java

@@ -30,16 +30,22 @@ class CacheTest {
     @Test
     @Order(1)
     void testPageCache() {
+        Cache cache = getCache();
         IPage<CacheModel> cacheModelIPage1 = cacheService.page(new Page<>(1, 3), new QueryWrapper<>());
         IPage<CacheModel> cacheModelIPage2 = cacheService.page(new Page<>(1, 3), new QueryWrapper<>());
+        //count+list
+        Assertions.assertEquals(cache.getSize(), 2);
         Assertions.assertEquals(cacheModelIPage1.getTotal(), cacheModelIPage2.getTotal());
         Assertions.assertEquals(cacheModelIPage1.getRecords().size(), cacheModelIPage2.getRecords().size());
         IPage<CacheModel> cacheModelIPage3 = cacheService.page(new Page<>(2, 3), new QueryWrapper<>());
         Assertions.assertEquals(cacheModelIPage1.getTotal(), cacheModelIPage3.getTotal());
         Assertions.assertEquals(cacheModelIPage3.getRecords().size(), 2);
+        //count语句命中,list翻页
+        Assertions.assertEquals(cache.getSize(), 3);
         IPage<CacheModel> cacheModelIPage4 = cacheService.page(new Page<>(2, 3, false), new QueryWrapper<>());
         Assertions.assertEquals(cacheModelIPage4.getTotal(), 0L);
         Assertions.assertEquals(cacheModelIPage4.getRecords().size(), 2);
+        Assertions.assertEquals(cache.getSize(), 4);
         IPage<CacheModel> cacheModelIPage5 = cacheService.page(new Page<>(2, 3, true), new QueryWrapper<>());
         Assertions.assertEquals(cacheModelIPage5.getTotal(), cacheModelIPage3.getTotal());
         Assertions.assertEquals(cacheModelIPage5.getRecords().size(), 2);