diff --git a/src/main/java/com/github/pagehelper/dialect/AbstractHelperDialect.java b/src/main/java/com/github/pagehelper/dialect/AbstractHelperDialect.java index fa30ad4c..c3e3fec3 100644 --- a/src/main/java/com/github/pagehelper/dialect/AbstractHelperDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/AbstractHelperDialect.java @@ -24,10 +24,15 @@ package com.github.pagehelper.dialect; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import com.github.pagehelper.Constant; import com.github.pagehelper.Page; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageRowBounds; +import com.github.pagehelper.cache.Cache; +import com.github.pagehelper.cache.CacheFactory; import com.github.pagehelper.util.ExecutorUtil; import com.github.pagehelper.util.MetaObjectUtil; import com.github.pagehelper.util.StringUtil; @@ -48,6 +53,16 @@ * @since 2016-12-04 14:32 */ public abstract class AbstractHelperDialect extends AbstractDialect implements Constant { + /** + * Logger for this class. + */ + private static final Logger logger = LoggerFactory.getLogger(AbstractHelperDialect.class); + + protected Cache CACHE_COUNTSQL; + protected Cache CACHE_PAGESQL; + + public static boolean cacheOnFlag = true;// 临时性开关,为了方便切换,以验证缓存前后对比. + public static boolean tracingOn = false;// 临时性开关 /** * 获取分页参数 @@ -61,7 +76,7 @@ public Page getLocalPage() { @Override public final boolean skip(MappedStatement ms, Object parameterObject, RowBounds rowBounds) { - //该方法不会被调用 + // 该方法不会被调用 return true; } @@ -72,13 +87,48 @@ public boolean beforeCount(MappedStatement ms, Object parameterObject, RowBounds } @Override - public String getCountSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey countKey) { + public String getCountSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, + CacheKey countKey) { + final long startTime = tracingOn || logger.isDebugEnabled() ? System.nanoTime() : 0; + if (startTime > 0) { + logger.info("getCountSql start ..."); + } Page page = getLocalPage(); String countColumn = page.getCountColumn(); + final String sql = boundSql.getSql(); + final String countSqlKey; + String cachedSql; + final boolean cacheOn = cacheOnFlag && CACHE_COUNTSQL != null; if (StringUtil.isNotEmpty(countColumn)) { - return countSqlParser.getSmartCountSql(boundSql.getSql(), countColumn); + countSqlKey = sql + countColumn; + cachedSql = cacheOn ? CACHE_COUNTSQL.get(countSqlKey) : null; + if (cachedSql != null) { + logCountSqlEnd(startTime); + return cachedSql; + } + cachedSql = countSqlParser.getSmartCountSql(sql, countColumn); + } else { + countSqlKey = sql; + cachedSql = cacheOn ? CACHE_COUNTSQL.get(countSqlKey) : null; + if (cachedSql != null) { + logCountSqlEnd(startTime); + return cachedSql; + } + cachedSql = countSqlParser.getSmartCountSql(sql); + } + if (cacheOn) { + CACHE_COUNTSQL.put(countSqlKey, cachedSql); + } + logCountSqlEnd(startTime); + return cachedSql; + } + + private void logCountSqlEnd(final long startTime) { + if (startTime > 0) { + final long time = System.nanoTime() - startTime; + logger.info("getCountSql(cacheOn={}) end: {}", cacheOnFlag, + Double.toString(time == 0 ? 0 : time / 1000000d)); } - return countSqlParser.getSmartCountSql(boundSql.getSql()); } @Override @@ -88,27 +138,28 @@ public boolean afterCount(long count, Object parameterObject, RowBounds rowBound if (rowBounds instanceof PageRowBounds) { ((PageRowBounds) rowBounds).setTotal(count); } - //pageSize < 0 的时候,不执行分页查询 - //pageSize = 0 的时候,还需要执行后续查询,但是不会分页 + // pageSize < 0 的时候,不执行分页查询 + // pageSize = 0 的时候,还需要执行后续查询,但是不会分页 if (page.getPageSizeZero() != null) { - //PageSizeZero=false&&pageSize<=0 + // PageSizeZero=false&&pageSize<=0 if (!page.getPageSizeZero() && page.getPageSize() <= 0) { return false; } - //PageSizeZero=true&&pageSize<0 返回 false,只有>=0才需要执行后续的 + // PageSizeZero=true&&pageSize<0 返回 false,只有>=0才需要执行后续的 else if (page.getPageSizeZero() && page.getPageSize() < 0) { return false; } } - //页码>0 && 开始行数<总行数即可,不需要考虑 pageSize(上面的 if 已经处理不符合要求的值了) + // 页码>0 && 开始行数<总行数即可,不需要考虑 pageSize(上面的 if 已经处理不符合要求的值了) return page.getPageNum() > 0 && count > page.getStartRow(); } @Override - public Object processParameterObject(MappedStatement ms, Object parameterObject, BoundSql boundSql, CacheKey pageKey) { - //处理参数 + public Object processParameterObject(MappedStatement ms, Object parameterObject, BoundSql boundSql, + CacheKey pageKey) { + // 处理参数 Page page = getLocalPage(); - //如果只是 order by 就不必处理参数 + // 如果只是 order by 就不必处理参数 if (page.isOrderByOnly()) { return parameterObject; } @@ -116,30 +167,32 @@ public Object processParameterObject(MappedStatement ms, Object parameterObject, if (parameterObject == null) { paramMap = new HashMap(); } else if (parameterObject instanceof Map) { - //解决不可变Map的情况 + // 解决不可变Map的情况 paramMap = new HashMap(); paramMap.putAll((Map) parameterObject); } else { paramMap = new HashMap(); // sqlSource为ProviderSqlSource时,处理只有1个参数的情况 if (ms.getSqlSource() instanceof ProviderSqlSource) { - String[] providerMethodArgumentNames = ExecutorUtil.getProviderMethodArgumentNames((ProviderSqlSource) ms.getSqlSource()); + String[] providerMethodArgumentNames = ExecutorUtil + .getProviderMethodArgumentNames((ProviderSqlSource) ms.getSqlSource()); if (providerMethodArgumentNames != null && providerMethodArgumentNames.length == 1) { paramMap.put(providerMethodArgumentNames[0], parameterObject); paramMap.put("param1", parameterObject); } } - //动态sql时的判断条件不会出现在ParameterMapping中,但是必须有,所以这里需要收集所有的getter属性 - //TypeHandlerRegistry可以直接处理的会作为一个直接使用的对象进行处理 - boolean hasTypeHandler = ms.getConfiguration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass()); + // 动态sql时的判断条件不会出现在ParameterMapping中,但是必须有,所以这里需要收集所有的getter属性 + // TypeHandlerRegistry可以直接处理的会作为一个直接使用的对象进行处理 + boolean hasTypeHandler = ms.getConfiguration().getTypeHandlerRegistry() + .hasTypeHandler(parameterObject.getClass()); MetaObject metaObject = MetaObjectUtil.forObject(parameterObject); - //需要针对注解形式的MyProviderSqlSource保存原值 + // 需要针对注解形式的MyProviderSqlSource保存原值 if (!hasTypeHandler) { for (String name : metaObject.getGetterNames()) { paramMap.put(name, metaObject.getValue(name)); } } - //下面这段方法,主要解决一个常见类型的参数时的问题 + // 下面这段方法,主要解决一个常见类型的参数时的问题 if (boundSql.getParameterMappings() != null && boundSql.getParameterMappings().size() > 0) { for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) { String name = parameterMapping.getProperty(); @@ -168,7 +221,8 @@ public Object processParameterObject(MappedStatement ms, Object parameterObject, * @param pageKey * @return */ - public abstract Object processPageParameter(MappedStatement ms, Map paramMap, Page page, BoundSql boundSql, CacheKey pageKey); + public abstract Object processPageParameter(MappedStatement ms, Map paramMap, Page page, + BoundSql boundSql, CacheKey pageKey); @Override public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds rowBounds) { @@ -180,19 +234,51 @@ public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds } @Override - public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) { + public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, + CacheKey pageKey) { String sql = boundSql.getSql(); Page page = getLocalPage(); - //支持 order by + // 支持 order by String orderBy = page.getOrderBy(); + String cacheSqlKey = getPageCacheSqlKey(page, sql); + final boolean cacheOn = cacheOnFlag && CACHE_PAGESQL != null; + final boolean orderByOnly = page.isOrderByOnly(); if (StringUtil.isNotEmpty(orderBy)) { + if (cacheOn) { + cacheSqlKey += orderBy; + if (orderByOnly) { + cacheSqlKey += "-orderByOnly"; + } + } pageKey.update(orderBy); - sql = orderBySqlParser.converToOrderBySql(sql, orderBy); + + String cachedSql = cacheOn ? CACHE_PAGESQL.get(cacheSqlKey) : null; + if (cachedSql == null) { + cachedSql = orderBySqlParser.converToOrderBySql(sql, orderBy); + if (cacheOn && orderByOnly) { + CACHE_PAGESQL.put(cacheSqlKey, cachedSql); + } + } + sql = cachedSql; } - if (page.isOrderByOnly()) { + if (orderByOnly) { return sql; } - return getPageSql(sql, page, pageKey); + String pageSql = cacheOn ? CACHE_PAGESQL.get(cacheSqlKey) : null; + if (pageSql == null) { + pageSql = getPageSql(sql, page, pageKey); + if (cacheOn) { + CACHE_PAGESQL.put(cacheSqlKey, pageSql); + } + } + return pageSql; + } + + protected String getPageCacheSqlKey(final Page page, final String sql) { + if (page.getStartRow() == 0) { + return sql; + } + return sql + "-1"; } /** @@ -212,7 +298,7 @@ public Object afterPage(List pageList, Object parameterObject, RowBounds rowBoun return pageList; } page.addAll(pageList); - //调整判断顺序,如果查全部,total就是size,如果只排序,也是全部,其他情况下如果不查询count就是-1 + // 调整判断顺序,如果查全部,total就是size,如果只排序,也是全部,其他情况下如果不查询count就是-1 if ((page.getPageSizeZero() != null && page.getPageSizeZero()) && page.getPageSize() == 0) { page.setTotal(pageList.size()); } else if (page.isOrderByOnly()) { @@ -231,12 +317,21 @@ public void afterAll() { @Override public void setProperties(Properties properties) { super.setProperties(properties); + final String sqlCacheClass = properties.getProperty("sqlCacheClass"); + if (StringUtil.isNotEmpty(sqlCacheClass) && !sqlCacheClass.equalsIgnoreCase("false")) { + CACHE_COUNTSQL = CacheFactory.createCache(sqlCacheClass, "count", properties); + CACHE_PAGESQL = CacheFactory.createCache(sqlCacheClass, "page", properties); + } else if (!"false".equalsIgnoreCase(sqlCacheClass)) { + CACHE_COUNTSQL = CacheFactory.createCache(null, "count", properties); + CACHE_PAGESQL = CacheFactory.createCache(null, "page", properties); + } } /** * @param boundSql * @param ms - * @deprecated use {@code handleParameter(BoundSql boundSql, MappedStatement ms, Class firstClass, Class secondClass)} + * @deprecated use + * {@code handleParameter(BoundSql boundSql, MappedStatement ms, Class firstClass, Class secondClass)} */ @Deprecated protected void handleParameter(BoundSql boundSql, MappedStatement ms) { @@ -247,9 +342,12 @@ protected void handleParameter(BoundSql boundSql, MappedStatement ms) { protected void handleParameter(BoundSql boundSql, MappedStatement ms, Class firstClass, Class secondClass) { if (boundSql.getParameterMappings() != null) { - List newParameterMappings = new ArrayList(boundSql.getParameterMappings()); - newParameterMappings.add(new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_FIRST, firstClass).build()); - newParameterMappings.add(new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_SECOND, secondClass).build()); + List newParameterMappings = new ArrayList( + boundSql.getParameterMappings()); + newParameterMappings + .add(new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_FIRST, firstClass).build()); + newParameterMappings.add( + new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_SECOND, secondClass).build()); MetaObject metaObject = MetaObjectUtil.forObject(boundSql); metaObject.setValue("parameterMappings", newParameterMappings); } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/AS400Dialect.java b/src/main/java/com/github/pagehelper/dialect/helper/AS400Dialect.java index 6e07e473..ffef0bca 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/AS400Dialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/AS400Dialect.java @@ -53,4 +53,9 @@ public Object processPageParameter(MappedStatement ms, Map param public String getPageSql(String sql, Page page, CacheKey pageKey) { return sql + " OFFSET ? ROWS FETCH FIRST ? ROWS ONLY"; } + + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/CirroDataDialect.java b/src/main/java/com/github/pagehelper/dialect/helper/CirroDataDialect.java index 59a882da..fd200d36 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/CirroDataDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/CirroDataDialect.java @@ -56,4 +56,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { return sqlBuilder.toString(); } + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/Db2Dialect.java b/src/main/java/com/github/pagehelper/dialect/helper/Db2Dialect.java index 4e6fc933..ad1e1ba4 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/Db2Dialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/Db2Dialect.java @@ -58,4 +58,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { return sqlBuilder.toString(); } + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/FirebirdDialect.java b/src/main/java/com/github/pagehelper/dialect/helper/FirebirdDialect.java index fc35e632..d0c7dd3c 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/FirebirdDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/FirebirdDialect.java @@ -64,4 +64,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { return sqlBuilder.toString(); } + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/HsqldbDialect.java b/src/main/java/com/github/pagehelper/dialect/helper/HsqldbDialect.java index 9e78a24f..3a55b5a0 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/HsqldbDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/HsqldbDialect.java @@ -76,4 +76,16 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { } return sqlBuilder.toString(); } + + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + String cacheKey = sql; + if (page.getPageSize() > 0) { + cacheKey += "-p"; + } + if (page.getStartRow() > 0) { + cacheKey += "-s"; + } + return cacheKey; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/Oracle9iDialect.java b/src/main/java/com/github/pagehelper/dialect/helper/Oracle9iDialect.java index 0c4d4bff..7873f76f 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/Oracle9iDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/Oracle9iDialect.java @@ -65,4 +65,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { return sqlBuilder.toString(); } + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/OracleDialect.java b/src/main/java/com/github/pagehelper/dialect/helper/OracleDialect.java index 254016da..698c309f 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/OracleDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/OracleDialect.java @@ -60,4 +60,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { return sqlBuilder.toString(); } + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/SqlServer2012Dialect.java b/src/main/java/com/github/pagehelper/dialect/helper/SqlServer2012Dialect.java index c2e04d77..c0cd7bf4 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/SqlServer2012Dialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/SqlServer2012Dialect.java @@ -57,4 +57,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { return sqlBuilder.toString(); } + @Override + protected String getPageCacheSqlKey(final Page page, final String sql) { + return sql; + } } diff --git a/src/main/java/com/github/pagehelper/dialect/helper/SqlServerDialect.java b/src/main/java/com/github/pagehelper/dialect/helper/SqlServerDialect.java index b659e92f..17b792aa 100644 --- a/src/main/java/com/github/pagehelper/dialect/helper/SqlServerDialect.java +++ b/src/main/java/com/github/pagehelper/dialect/helper/SqlServerDialect.java @@ -25,8 +25,6 @@ package com.github.pagehelper.dialect.helper; import com.github.pagehelper.Page; -import com.github.pagehelper.cache.Cache; -import com.github.pagehelper.cache.CacheFactory; import com.github.pagehelper.dialect.AbstractHelperDialect; import com.github.pagehelper.dialect.ReplaceSql; import com.github.pagehelper.dialect.replace.RegexWithNolockReplaceSql; @@ -48,14 +46,13 @@ */ public class SqlServerDialect extends AbstractHelperDialect { protected SqlServerSqlParser sqlServerSqlParser; - protected Cache CACHE_COUNTSQL; - protected Cache CACHE_PAGESQL; - protected ReplaceSql replaceSql; + protected ReplaceSql replaceSql; @Override - public String getCountSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey countKey) { + public String getCountSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, + CacheKey countKey) { String sql = boundSql.getSql(); - String cacheSql = CACHE_COUNTSQL.get(sql); + String cacheSql = CACHE_COUNTSQL == null ? null : CACHE_COUNTSQL.get(sql); if (cacheSql != null) { return cacheSql; } else { @@ -64,27 +61,32 @@ public String getCountSql(MappedStatement ms, BoundSql boundSql, Object paramete cacheSql = replaceSql.replace(cacheSql); cacheSql = countSqlParser.getSmartCountSql(cacheSql); cacheSql = replaceSql.restore(cacheSql); - CACHE_COUNTSQL.put(sql, cacheSql); + if (CACHE_COUNTSQL != null) { + CACHE_COUNTSQL.put(sql, cacheSql); + } return cacheSql; } @Override - public Object processPageParameter(MappedStatement ms, Map paramMap, Page page, BoundSql boundSql, CacheKey pageKey) { + public Object processPageParameter(MappedStatement ms, Map paramMap, Page page, BoundSql boundSql, + CacheKey pageKey) { return paramMap; } @Override public String getPageSql(String sql, Page page, CacheKey pageKey) { - //处理pageKey + // 处理pageKey pageKey.update(page.getStartRow()); pageKey.update(page.getPageSize()); - String cacheSql = CACHE_PAGESQL.get(sql); + String cacheSql = CACHE_PAGESQL == null ? null : CACHE_PAGESQL.get(sql); if (cacheSql == null) { cacheSql = sql; cacheSql = replaceSql.replace(cacheSql); cacheSql = sqlServerSqlParser.convertToPageSql(cacheSql, null, null); cacheSql = replaceSql.restore(cacheSql); - CACHE_PAGESQL.put(sql, cacheSql); + if (CACHE_PAGESQL != null) { + CACHE_PAGESQL.put(sql, cacheSql); + } } cacheSql = cacheSql.replace(String.valueOf(Long.MIN_VALUE), String.valueOf(page.getStartRow())); cacheSql = cacheSql.replace(String.valueOf(Long.MAX_VALUE), String.valueOf(page.getPageSize())); @@ -99,7 +101,8 @@ public String getPageSql(String sql, Page page, CacheKey pageKey) { * 3. this.replaceSql.restore(sql);最后再恢复成真的with(nolock) */ @Override - public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, CacheKey pageKey) { + public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameterObject, RowBounds rowBounds, + CacheKey pageKey) { String sql = boundSql.getSql(); Page page = this.getLocalPage(); String orderBy = page.getOrderBy(); @@ -116,7 +119,8 @@ public String getPageSql(MappedStatement ms, BoundSql boundSql, Object parameter @Override public void setProperties(Properties properties) { super.setProperties(properties); - this.sqlServerSqlParser = ClassUtil.newInstance(properties.getProperty("sqlServerSqlParser"), SqlServerSqlParser.class, properties, DefaultSqlServerSqlParser::new); + this.sqlServerSqlParser = ClassUtil.newInstance(properties.getProperty("sqlServerSqlParser"), + SqlServerSqlParser.class, properties, DefaultSqlServerSqlParser::new); String replaceSql = properties.getProperty("replaceSql"); if (StringUtil.isEmpty(replaceSql) || "regex".equalsIgnoreCase(replaceSql)) { this.replaceSql = new RegexWithNolockReplaceSql(); @@ -125,13 +129,5 @@ public void setProperties(Properties properties) { } else { this.replaceSql = ClassUtil.newInstance(replaceSql, properties); } - String sqlCacheClass = properties.getProperty("sqlCacheClass"); - if (StringUtil.isNotEmpty(sqlCacheClass) && !sqlCacheClass.equalsIgnoreCase("false")) { - CACHE_COUNTSQL = CacheFactory.createCache(sqlCacheClass, "count", properties); - CACHE_PAGESQL = CacheFactory.createCache(sqlCacheClass, "page", properties); - } else { - CACHE_COUNTSQL = CacheFactory.createCache(null, "count", properties); - CACHE_PAGESQL = CacheFactory.createCache(null, "page", properties); - } } }