diff --git a/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/IPage.java b/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/IPage.java index 6768c22f6beadcbfb1b218f13347fa7703b27fe2..6b26f1f569d4d38dda91cabe0d484b129fc3fd1d 100644 --- a/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/IPage.java +++ b/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/IPage.java @@ -65,6 +65,16 @@ public interface IPage extends Serializable { return true; } + /** + * 查询最近N页数据 + * N 建议等于10 N取值范围5-50 + * !searchCount && recentPage!=null 才执行查询最近N页数据逻辑 + * @return 默认返回为null + */ + default Long recentPage() { + return null; + } + /** * 计算当前分页偏移量 */ diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/PaginationInnerInterceptor.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/PaginationInnerInterceptor.java index 549f5596f1fe4748d94dffa499963cafe51d1c68..7b04e013564ea14d5ce802318ff26c93f452bb58 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/PaginationInnerInterceptor.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/PaginationInnerInterceptor.java @@ -115,17 +115,33 @@ public class PaginationInnerInterceptor implements InnerInterceptor { @Override public boolean willDoQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException { IPage page = ParameterUtils.findPage(parameter).orElse(null); - if (page == null || page.getSize() < 0 || !page.searchCount() || resultHandler != Executor.NO_RESULT_HANDLER) { + if (page == null || page.getSize() < 0 || (!page.searchCount() && page.recentPage()==null) || resultHandler != Executor.NO_RESULT_HANDLER) { return true; } + boolean recentPageFlag = false; + long limitParam = 0L; + if (!page.searchCount() && page.recentPage()!=null) { + recentPageFlag = true; + limitParam = page.getSize() * (page.getCurrent() < (page.recentPage() / 2 + 1 + page.recentPage() % 2) ? page.recentPage() : (page.getCurrent() + (page.recentPage() / 2 + page.recentPage() % 2 - 1))); + } BoundSql countSql; + String countSqlSourceStr = null; + String countSqlStr; MappedStatement countMs = buildCountMappedStatement(ms, page.countId()); if (countMs != null) { countSql = countMs.getBoundSql(parameter); } else { countMs = buildAutoCountMappedStatement(ms); - String countSqlStr = autoCountSql(page, boundSql.getSql()); + countSqlSourceStr = countSqlStr = autoCountSql(page, boundSql.getSql()); + // countSql 有两种形式 + // 第一种 "SELECT COUNT(*) FROM (%s) TOTAL" + // 第二种 "SELECT COUNT(*) AS TOTAL FROM XXX" + //处理 各种数据库对应的 limit关键词对应的语句 + if (recentPageFlag) { + IDialect dialect = findIDialect(executor); + countSqlStr = dialect.buildRecentPaginationCountSql(countSqlStr, limitParam, 1L).replace("SELECT COUNT(*)","SELECT 1"); + } PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql); countSql = new BoundSql(countMs.getConfiguration(), countSqlStr, mpBoundSql.parameterMappings(), parameter); PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters()); @@ -141,6 +157,24 @@ public class PaginationInnerInterceptor implements InnerInterceptor { total = Long.parseLong(o.toString()); } } + if (recentPageFlag) { + if (total == 1) { + total = limitParam; + }else { + PluginUtils.MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql); + countSql = new BoundSql(countMs.getConfiguration(), countSqlSourceStr, mpBoundSql.parameterMappings(), parameter); + PluginUtils.setAdditionalParameter(countSql, mpBoundSql.additionalParameters()); + CacheKey cacheKeyRecentPage = executor.createCacheKey(countMs, parameter, rowBounds, countSql); + List resultRecentPage = executor.query(countMs, parameter, rowBounds, resultHandler, cacheKeyRecentPage, countSql); + if (CollectionUtils.isNotEmpty(resultRecentPage)) { + // 个别数据库 count 没数据不会返回 0 + Object o = resultRecentPage.get(0); + if (o != null) { + total = Long.parseLong(o.toString()); + } + } + } + } page.setTotal(total); return continuePage(page); } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/Page.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/Page.java index 3fd0a60f336c6fa6ebcae4f14ac6d7b36faa0292..87a8ddff63b7fa90e180ce7aa3508e9499ede136 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/Page.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/Page.java @@ -250,6 +250,9 @@ public class Page implements IPage { public static Page of(long current, long size, long total, boolean searchCount) { return new Page<>(current, size, total, searchCount); } + public static Page of(long current, long size, long total, boolean searchCount, Long recentPage) { + return new Page<>(current, size, total, searchCount, recentPage); + } @Override public boolean optimizeJoinOfCountSql() { @@ -292,4 +295,34 @@ public class Page implements IPage { } return searchCount; } + + + /** + * 查询最近N页数据 + * !searchCount && recentPage!=null 才执行查询最近N页数据逻辑 + */ + protected Long recentPage = null; + + public Page(long current, long size, boolean searchCount, Long recentPage) { + this(current, size, 0, searchCount, recentPage); + } + + public Page(long current, long size, long total, boolean searchCount, Long recentPage) { + if (current > 1) { + this.current = current; + } + this.size = size; + this.total = total; + this.searchCount = searchCount; + this.recentPage = recentPage; + } + + @Override + public Long recentPage() { + if (!searchCount && (recentPage >= 5 && recentPage <= 50)) { + return recentPage; + } + return null; + } + } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/DB2Dialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/DB2Dialect.java index fa8fe778c637cb0db0a951cfa0d15de70a5c9241..f23272d058e057553c718837568fb3e4ec50f1f8 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/DB2Dialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/DB2Dialect.java @@ -33,4 +33,11 @@ public class DB2Dialect implements IDialect { " ) AS TMP_PAGE) TMP_PAGE WHERE ROW_ID BETWEEN " + FIRST_MARK + " AND " + SECOND_MARK; return new DialectModel(sql, firstParam, secondParam).setConsumerChain(); } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + long firstParam = offset + 1; + return "SELECT * FROM (SELECT TMP_PAGE.*,ROWNUMBER() OVER() AS ROW_ID FROM ( " + originalSql + + " ) AS TMP_PAGE) TMP_PAGE WHERE ROW_ID BETWEEN " + firstParam + " AND " + limit; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/GBase8sDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/GBase8sDialect.java index a50564784e9296795b3ae4a0af8f395a2caedd03..f26e8caa92aeea8f8a1a8e5f965b98f4ab01e30b 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/GBase8sDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/GBase8sDialect.java @@ -32,4 +32,11 @@ public class GBase8sDialect implements IDialect { .insert(6, " SKIP " + offset + " FIRST " + limit); return new DialectModel(sql.toString()); } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return new StringBuilder(originalSql) + .insert(6, " SKIP " + offset + " FIRST " + limit).toString(); + } + } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialect.java index a42b62f11eb8eebe896551778d2af6d88f40a817..310103aaea03e7c283c87a088a2c119e0df6eab6 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialect.java @@ -41,4 +41,15 @@ public interface IDialect { * @return 分页模型 */ DialectModel buildPaginationSql(String originalSql, long offset, long limit); + + /** + * 组装查询最近n页数据总条数语句 + * 实际执行逻辑 判断第 偏移量(n*pageSize)之后 数据是否存在 + * 类似mysql的执行逻辑 SELECT 1 FROM table_name WHERE (条件拼接) LIMIT 100,1 + * @param originalSql 原始语句 + * @param offset 偏移量 + * @param limit 界限 固定值1 + * @return 查询最近n页数据总条数语句 + */ + String buildRecentPaginationCountSql(String originalSql, long offset, long limit); } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/InformixDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/InformixDialect.java index a1127ce2294f45931c17f6436463804ddbbd89eb..2d53de0ab3ab2e8d31fd4a3d6223fe99fcb5f91e 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/InformixDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/InformixDialect.java @@ -26,4 +26,12 @@ public class InformixDialect implements IDialect { ret.append(originalSql.replaceFirst("(?i)select", "")); return new DialectModel(ret.toString()); } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + StringBuilder ret = new StringBuilder(); + ret.append(String.format("select skip %s first %s ", offset + "", limit + "")); + ret.append(originalSql.replaceFirst("(?i)select", "")); + return ret.toString(); + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/MySqlDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/MySqlDialect.java index 20eefd636b466ebba0afa53a7fd67e4822885240..3474f87ef125f2d2d0c92e98bfd7742dbf166cf1 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/MySqlDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/MySqlDialect.java @@ -15,6 +15,7 @@ */ package com.baomidou.mybatisplus.extension.plugins.pagination.dialects; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel; @@ -36,4 +37,9 @@ public class MySqlDialect implements IDialect { return new DialectModel(sql.toString(), limit).setConsumer(true); } } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return originalSql + " LIMIT " + offset + Constants.COMMA + limit; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/Oracle12cDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/Oracle12cDialect.java index dd7ccfd28ab1f0da576f38ff7ee37ad4f22aa882..7050023c9e3b8d13ea2893425055935d09dc7f8c 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/Oracle12cDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/Oracle12cDialect.java @@ -30,4 +30,9 @@ public class Oracle12cDialect implements IDialect { String sql = originalSql + " OFFSET " + FIRST_MARK + " ROWS FETCH NEXT " + SECOND_MARK + " ROWS ONLY"; return new DialectModel(sql, offset, limit).setConsumerChain(); } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return originalSql + " OFFSET " + offset + " ROWS FETCH NEXT " + limit + " ROWS ONLY"; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/OracleDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/OracleDialect.java index c02a0dfb75d79136a4dcf144d17491dbaf4f30c9..e61942e54425dcd6d2c2dc24a400c44f2b950633 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/OracleDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/OracleDialect.java @@ -33,4 +33,10 @@ public class OracleDialect implements IDialect { originalSql + " ) TMP WHERE ROWNUM <=" + FIRST_MARK + ") WHERE ROW_ID > " + SECOND_MARK; return new DialectModel(sql, limit, offset).setConsumerChain(); } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return "SELECT * FROM ( SELECT TMP.*, ROWNUM ROW_ID FROM ( " + + originalSql + " ) TMP WHERE ROWNUM <=" + offset + ") WHERE ROW_ID > " + limit; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/PostgreDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/PostgreDialect.java index 247cf06a1f2031b2ebe031be864240ec86f84d8b..3e9ba39e9ddabf45e3a28b60038ee5e49d0da046 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/PostgreDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/PostgreDialect.java @@ -15,6 +15,7 @@ */ package com.baomidou.mybatisplus.extension.plugins.pagination.dialects; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel; /** @@ -35,4 +36,9 @@ public class PostgreDialect implements IDialect { return new DialectModel(sql.toString(), limit).setConsumer(true); } } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return originalSql + " LIMIT " + offset + " OFFSET " + limit; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SQLServer2005Dialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SQLServer2005Dialect.java index ad6eb2a9517fea5beebc4eae87c0e5650e52460f..b2a2d92427c0d0bfeb8b1808638eeef84555075e 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SQLServer2005Dialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SQLServer2005Dialect.java @@ -77,4 +77,36 @@ public class SQLServer2005Dialect implements IDialect { firstParam + " AND " + secondParam + " ORDER BY __row_number__"; return new DialectModel(sql); } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + StringBuilder pagingBuilder = new StringBuilder(); + String orderby = getOrderByPart(originalSql); + String distinctStr = StringPool.EMPTY; + + String loweredString = originalSql.toLowerCase(); + String sqlPartString = originalSql; + if (loweredString.trim().startsWith("select")) { + int index = 6; + if (loweredString.startsWith("select distinct")) { + distinctStr = "DISTINCT "; + index = 15; + } + sqlPartString = sqlPartString.substring(index); + } + pagingBuilder.append(sqlPartString); + + // if no ORDER BY is specified use fake ORDER BY field to avoid errors + if (StringUtils.isBlank(orderby)) { + orderby = "ORDER BY CURRENT_TIMESTAMP"; + } + long firstParam = offset + 1; +// long secondParam = offset + limit; + String sql = "WITH selectTemp AS (SELECT " + distinctStr + "TOP 100 PERCENT " + + " ROW_NUMBER() OVER (" + orderby + ") as __row_number__, " + pagingBuilder + + ") SELECT * FROM selectTemp WHERE __row_number__ BETWEEN " + + //FIX#299:原因:mysql中limit 10(offset,size) 是从第10开始(不包含10),;而这里用的BETWEEN是两边都包含,所以改为offset+1 + firstParam + " AND " + limit + " ORDER BY __row_number__"; + return sql; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SybaseDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SybaseDialect.java index b9e688c6ec174907e704f291c5b38382ddf97f77..ed16d51a45c2732eb24f6c6a1829dc58c87a1276 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SybaseDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/SybaseDialect.java @@ -57,6 +57,22 @@ public class SybaseDialect implements IDialect { return new DialectModel(sql, offset, offset + limit).setConsumerChain(); } + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + int index = findMainFROM(originalSql); + if(index == -1){ + index = originalSql.toUpperCase().indexOf(" FROM "); + } + String sql = "select"; + if (hasTop) { + sql += " top " + (offset + limit); + } + sql += " rownum=identity(12)," + originalSql.substring(6, index) + " into #t " + originalSql.substring(index); + sql += " select * from #t where rownum > " + offset + " and rownum <= " + limit; + sql += "drop table #t "; + return sql; + } + /** * 查找主查询的FROM位置 * @param sql 需要查找的SQL diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/TrinoDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/TrinoDialect.java index c0971c55d6de0e3c5b504430f24fb4ee1afa472a..e28ea1229db67d011d929c4f6a42e6718addaab5 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/TrinoDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/TrinoDialect.java @@ -1,5 +1,6 @@ package com.baomidou.mybatisplus.extension.plugins.pagination.dialects; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.extension.plugins.pagination.DialectModel; /** @@ -22,4 +23,9 @@ public class TrinoDialect implements IDialect { return new DialectModel(sql.toString(), limit).setConsumer(true); } } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return originalSql + " OFFSET " + offset + " LIMIT " + limit; + } } diff --git a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/XCloudDialect.java b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/XCloudDialect.java index a1f3b9d751626e297a37f04a0cd614a454024639..18b9d613c18ac973e900aa3fade7ac3e942d5a88 100644 --- a/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/XCloudDialect.java +++ b/mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/XCloudDialect.java @@ -36,4 +36,9 @@ public class XCloudDialect implements IDialect { return new DialectModel(sql.toString(), limit).setConsumer(true); } } + + @Override + public String buildRecentPaginationCountSql(String originalSql, long offset, long limit) { + return originalSql + " LIMIT " + " (" + offset + 1 + "," + limit + ") "; + } } diff --git a/mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialectTest.java b/mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialectTest.java index 2cc4f7489e4683d9fb794bd578f93a3f2846259e..2d9ffd41dc94cfa055b25802ec8753fcb05e265d 100644 --- a/mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialectTest.java +++ b/mybatis-plus-extension/src/test/java/com/baomidou/mybatisplus/extension/plugins/pagination/dialects/IDialectTest.java @@ -48,4 +48,29 @@ class IDialectTest { }).isEqualTo(1); }); } + + @Test + void buildRecentPaginationCountSqlTest() { + List> classList = ReflectionUtils.findAllClassesInPackage( + "com.baomidou.mybatisplus.extension.plugins.pagination.dialects", + i -> !i.isInterface() && IDialect.class.isAssignableFrom(i), i -> true); + + Map>> map = new ConcurrentHashMap<>(); + classList.forEach(i -> { + IDialect o = (IDialect) ReflectionUtils.newInstance(i); + String sql = o.buildRecentPaginationCountSql("select * from table", 100, 1); + if (!map.containsKey(sql)) { + map.put(sql, Lists.newArrayList(i)); + } else { + map.get(sql).add(i); + } + }); + map.forEach((k, v) -> { + List> list = v.stream().filter(i -> i.getAnnotation(Deprecated.class) == null).collect(Collectors.toList()); + assertThat(list.size()).as(() -> { + String s = list.stream().map(Class::getSimpleName).collect(Collectors.joining("与")); + return s + "的sql重复"; + }).isEqualTo(1); + }); + } }