24
24
25
25
package com .github .pagehelper .dialect ;
26
26
27
+ import org .slf4j .Logger ;
28
+ import org .slf4j .LoggerFactory ;
29
+
27
30
import com .github .pagehelper .Constant ;
28
31
import com .github .pagehelper .Page ;
29
32
import com .github .pagehelper .PageHelper ;
30
33
import com .github .pagehelper .PageRowBounds ;
34
+ import com .github .pagehelper .cache .Cache ;
35
+ import com .github .pagehelper .cache .CacheFactory ;
31
36
import com .github .pagehelper .util .ExecutorUtil ;
32
37
import com .github .pagehelper .util .MetaObjectUtil ;
33
38
import com .github .pagehelper .util .StringUtil ;
48
53
* @since 2016-12-04 14:32
49
54
*/
50
55
public abstract class AbstractHelperDialect extends AbstractDialect implements Constant {
56
+ /**
57
+ * Logger for this class.
58
+ */
59
+ private static final Logger logger = LoggerFactory .getLogger (AbstractHelperDialect .class );
60
+
61
+ protected Cache <String , String > CACHE_COUNTSQL ;
62
+ protected Cache <String , String > CACHE_PAGESQL ;
63
+
64
+ public static boolean cacheOnFlag = true ;// 临时性开关,为了方便切换,以验证缓存前后对比.
65
+ public static boolean tracingOn = false ;// 临时性开关
51
66
52
67
/**
53
68
* 获取分页参数
@@ -61,7 +76,7 @@ public <T> Page<T> getLocalPage() {
61
76
62
77
@ Override
63
78
public final boolean skip (MappedStatement ms , Object parameterObject , RowBounds rowBounds ) {
64
- //该方法不会被调用
79
+ // 该方法不会被调用
65
80
return true ;
66
81
}
67
82
@@ -72,13 +87,48 @@ public boolean beforeCount(MappedStatement ms, Object parameterObject, RowBounds
72
87
}
73
88
74
89
@ Override
75
- public String getCountSql (MappedStatement ms , BoundSql boundSql , Object parameterObject , RowBounds rowBounds , CacheKey countKey ) {
90
+ public String getCountSql (MappedStatement ms , BoundSql boundSql , Object parameterObject , RowBounds rowBounds ,
91
+ CacheKey countKey ) {
92
+ final long startTime = tracingOn || logger .isDebugEnabled () ? System .nanoTime () : 0 ;
93
+ if (startTime > 0 ) {
94
+ logger .info ("getCountSql start ..." );
95
+ }
76
96
Page <Object > page = getLocalPage ();
77
97
String countColumn = page .getCountColumn ();
98
+ final String sql = boundSql .getSql ();
99
+ final String countSqlKey ;
100
+ String cachedSql ;
101
+ final boolean cacheOn = cacheOnFlag && CACHE_COUNTSQL != null ;
78
102
if (StringUtil .isNotEmpty (countColumn )) {
79
- return countSqlParser .getSmartCountSql (boundSql .getSql (), countColumn );
103
+ countSqlKey = sql + countColumn ;
104
+ cachedSql = cacheOn ? CACHE_COUNTSQL .get (countSqlKey ) : null ;
105
+ if (cachedSql != null ) {
106
+ logCountSqlEnd (startTime );
107
+ return cachedSql ;
108
+ }
109
+ cachedSql = countSqlParser .getSmartCountSql (sql , countColumn );
110
+ } else {
111
+ countSqlKey = sql ;
112
+ cachedSql = cacheOn ? CACHE_COUNTSQL .get (countSqlKey ) : null ;
113
+ if (cachedSql != null ) {
114
+ logCountSqlEnd (startTime );
115
+ return cachedSql ;
116
+ }
117
+ cachedSql = countSqlParser .getSmartCountSql (sql );
118
+ }
119
+ if (cacheOn ) {
120
+ CACHE_COUNTSQL .put (countSqlKey , cachedSql );
121
+ }
122
+ logCountSqlEnd (startTime );
123
+ return cachedSql ;
124
+ }
125
+
126
+ private void logCountSqlEnd (final long startTime ) {
127
+ if (startTime > 0 ) {
128
+ final long time = System .nanoTime () - startTime ;
129
+ logger .info ("getCountSql(cacheOn={}) end: {}" , cacheOnFlag ,
130
+ Double .toString (time == 0 ? 0 : time / 1000000d ));
80
131
}
81
- return countSqlParser .getSmartCountSql (boundSql .getSql ());
82
132
}
83
133
84
134
@ Override
@@ -88,58 +138,61 @@ public boolean afterCount(long count, Object parameterObject, RowBounds rowBound
88
138
if (rowBounds instanceof PageRowBounds ) {
89
139
((PageRowBounds ) rowBounds ).setTotal (count );
90
140
}
91
- //pageSize < 0 的时候,不执行分页查询
92
- //pageSize = 0 的时候,还需要执行后续查询,但是不会分页
141
+ // pageSize < 0 的时候,不执行分页查询
142
+ // pageSize = 0 的时候,还需要执行后续查询,但是不会分页
93
143
if (page .getPageSizeZero () != null ) {
94
- //PageSizeZero=false&&pageSize<=0
144
+ // PageSizeZero=false&&pageSize<=0
95
145
if (!page .getPageSizeZero () && page .getPageSize () <= 0 ) {
96
146
return false ;
97
147
}
98
- //PageSizeZero=true&&pageSize<0 返回 false,只有>=0才需要执行后续的
148
+ // PageSizeZero=true&&pageSize<0 返回 false,只有>=0才需要执行后续的
99
149
else if (page .getPageSizeZero () && page .getPageSize () < 0 ) {
100
150
return false ;
101
151
}
102
152
}
103
- //页码>0 && 开始行数<总行数即可,不需要考虑 pageSize(上面的 if 已经处理不符合要求的值了)
153
+ // 页码>0 && 开始行数<总行数即可,不需要考虑 pageSize(上面的 if 已经处理不符合要求的值了)
104
154
return page .getPageNum () > 0 && count > page .getStartRow ();
105
155
}
106
156
107
157
@ Override
108
- public Object processParameterObject (MappedStatement ms , Object parameterObject , BoundSql boundSql , CacheKey pageKey ) {
109
- //处理参数
158
+ public Object processParameterObject (MappedStatement ms , Object parameterObject , BoundSql boundSql ,
159
+ CacheKey pageKey ) {
160
+ // 处理参数
110
161
Page page = getLocalPage ();
111
- //如果只是 order by 就不必处理参数
162
+ // 如果只是 order by 就不必处理参数
112
163
if (page .isOrderByOnly ()) {
113
164
return parameterObject ;
114
165
}
115
166
Map <String , Object > paramMap = null ;
116
167
if (parameterObject == null ) {
117
168
paramMap = new HashMap <String , Object >();
118
169
} else if (parameterObject instanceof Map ) {
119
- //解决不可变Map的情况
170
+ // 解决不可变Map的情况
120
171
paramMap = new HashMap <String , Object >();
121
172
paramMap .putAll ((Map ) parameterObject );
122
173
} else {
123
174
paramMap = new HashMap <String , Object >();
124
175
// sqlSource为ProviderSqlSource时,处理只有1个参数的情况
125
176
if (ms .getSqlSource () instanceof ProviderSqlSource ) {
126
- String [] providerMethodArgumentNames = ExecutorUtil .getProviderMethodArgumentNames ((ProviderSqlSource ) ms .getSqlSource ());
177
+ String [] providerMethodArgumentNames = ExecutorUtil
178
+ .getProviderMethodArgumentNames ((ProviderSqlSource ) ms .getSqlSource ());
127
179
if (providerMethodArgumentNames != null && providerMethodArgumentNames .length == 1 ) {
128
180
paramMap .put (providerMethodArgumentNames [0 ], parameterObject );
129
181
paramMap .put ("param1" , parameterObject );
130
182
}
131
183
}
132
- //动态sql时的判断条件不会出现在ParameterMapping中,但是必须有,所以这里需要收集所有的getter属性
133
- //TypeHandlerRegistry可以直接处理的会作为一个直接使用的对象进行处理
134
- boolean hasTypeHandler = ms .getConfiguration ().getTypeHandlerRegistry ().hasTypeHandler (parameterObject .getClass ());
184
+ // 动态sql时的判断条件不会出现在ParameterMapping中,但是必须有,所以这里需要收集所有的getter属性
185
+ // TypeHandlerRegistry可以直接处理的会作为一个直接使用的对象进行处理
186
+ boolean hasTypeHandler = ms .getConfiguration ().getTypeHandlerRegistry ()
187
+ .hasTypeHandler (parameterObject .getClass ());
135
188
MetaObject metaObject = MetaObjectUtil .forObject (parameterObject );
136
- //需要针对注解形式的MyProviderSqlSource保存原值
189
+ // 需要针对注解形式的MyProviderSqlSource保存原值
137
190
if (!hasTypeHandler ) {
138
191
for (String name : metaObject .getGetterNames ()) {
139
192
paramMap .put (name , metaObject .getValue (name ));
140
193
}
141
194
}
142
- //下面这段方法,主要解决一个常见类型的参数时的问题
195
+ // 下面这段方法,主要解决一个常见类型的参数时的问题
143
196
if (boundSql .getParameterMappings () != null && boundSql .getParameterMappings ().size () > 0 ) {
144
197
for (ParameterMapping parameterMapping : boundSql .getParameterMappings ()) {
145
198
String name = parameterMapping .getProperty ();
@@ -168,7 +221,8 @@ public Object processParameterObject(MappedStatement ms, Object parameterObject,
168
221
* @param pageKey
169
222
* @return
170
223
*/
171
- public abstract Object processPageParameter (MappedStatement ms , Map <String , Object > paramMap , Page page , BoundSql boundSql , CacheKey pageKey );
224
+ public abstract Object processPageParameter (MappedStatement ms , Map <String , Object > paramMap , Page page ,
225
+ BoundSql boundSql , CacheKey pageKey );
172
226
173
227
@ Override
174
228
public boolean beforePage (MappedStatement ms , Object parameterObject , RowBounds rowBounds ) {
@@ -180,19 +234,51 @@ public boolean beforePage(MappedStatement ms, Object parameterObject, RowBounds
180
234
}
181
235
182
236
@ Override
183
- public String getPageSql (MappedStatement ms , BoundSql boundSql , Object parameterObject , RowBounds rowBounds , CacheKey pageKey ) {
237
+ public String getPageSql (MappedStatement ms , BoundSql boundSql , Object parameterObject , RowBounds rowBounds ,
238
+ CacheKey pageKey ) {
184
239
String sql = boundSql .getSql ();
185
240
Page page = getLocalPage ();
186
- //支持 order by
241
+ // 支持 order by
187
242
String orderBy = page .getOrderBy ();
243
+ String cacheSqlKey = getPageCacheSqlKey (page , sql );
244
+ final boolean cacheOn = cacheOnFlag && CACHE_PAGESQL != null ;
245
+ final boolean orderByOnly = page .isOrderByOnly ();
188
246
if (StringUtil .isNotEmpty (orderBy )) {
247
+ if (cacheOn ) {
248
+ cacheSqlKey += orderBy ;
249
+ if (orderByOnly ) {
250
+ cacheSqlKey += "-orderByOnly" ;
251
+ }
252
+ }
189
253
pageKey .update (orderBy );
190
- sql = orderBySqlParser .converToOrderBySql (sql , orderBy );
254
+
255
+ String cachedSql = cacheOn ? CACHE_PAGESQL .get (cacheSqlKey ) : null ;
256
+ if (cachedSql == null ) {
257
+ cachedSql = orderBySqlParser .converToOrderBySql (sql , orderBy );
258
+ if (cacheOn && orderByOnly ) {
259
+ CACHE_PAGESQL .put (cacheSqlKey , cachedSql );
260
+ }
261
+ }
262
+ sql = cachedSql ;
191
263
}
192
- if (page . isOrderByOnly () ) {
264
+ if (orderByOnly ) {
193
265
return sql ;
194
266
}
195
- return getPageSql (sql , page , pageKey );
267
+ String pageSql = cacheOn ? CACHE_PAGESQL .get (cacheSqlKey ) : null ;
268
+ if (pageSql == null ) {
269
+ pageSql = getPageSql (sql , page , pageKey );
270
+ if (cacheOn ) {
271
+ CACHE_PAGESQL .put (cacheSqlKey , pageSql );
272
+ }
273
+ }
274
+ return pageSql ;
275
+ }
276
+
277
+ protected String getPageCacheSqlKey (final Page page , final String sql ) {
278
+ if (page .getStartRow () == 0 ) {
279
+ return sql ;
280
+ }
281
+ return sql + "-1" ;
196
282
}
197
283
198
284
/**
@@ -212,7 +298,7 @@ public Object afterPage(List pageList, Object parameterObject, RowBounds rowBoun
212
298
return pageList ;
213
299
}
214
300
page .addAll (pageList );
215
- //调整判断顺序,如果查全部,total就是size,如果只排序,也是全部,其他情况下如果不查询count就是-1
301
+ // 调整判断顺序,如果查全部,total就是size,如果只排序,也是全部,其他情况下如果不查询count就是-1
216
302
if ((page .getPageSizeZero () != null && page .getPageSizeZero ()) && page .getPageSize () == 0 ) {
217
303
page .setTotal (pageList .size ());
218
304
} else if (page .isOrderByOnly ()) {
@@ -231,12 +317,21 @@ public void afterAll() {
231
317
@ Override
232
318
public void setProperties (Properties properties ) {
233
319
super .setProperties (properties );
320
+ final String sqlCacheClass = properties .getProperty ("sqlCacheClass" );
321
+ if (StringUtil .isNotEmpty (sqlCacheClass ) && !sqlCacheClass .equalsIgnoreCase ("false" )) {
322
+ CACHE_COUNTSQL = CacheFactory .createCache (sqlCacheClass , "count" , properties );
323
+ CACHE_PAGESQL = CacheFactory .createCache (sqlCacheClass , "page" , properties );
324
+ } else if (!"false" .equalsIgnoreCase (sqlCacheClass )) {
325
+ CACHE_COUNTSQL = CacheFactory .createCache (null , "count" , properties );
326
+ CACHE_PAGESQL = CacheFactory .createCache (null , "page" , properties );
327
+ }
234
328
}
235
329
236
330
/**
237
331
* @param boundSql
238
332
* @param ms
239
- * @deprecated use {@code handleParameter(BoundSql boundSql, MappedStatement ms, Class<?> firstClass, Class<?> secondClass)}
333
+ * @deprecated use
334
+ * {@code handleParameter(BoundSql boundSql, MappedStatement ms, Class<?> firstClass, Class<?> secondClass)}
240
335
*/
241
336
@ Deprecated
242
337
protected void handleParameter (BoundSql boundSql , MappedStatement ms ) {
@@ -247,9 +342,12 @@ protected void handleParameter(BoundSql boundSql, MappedStatement ms) {
247
342
248
343
protected void handleParameter (BoundSql boundSql , MappedStatement ms , Class <?> firstClass , Class <?> secondClass ) {
249
344
if (boundSql .getParameterMappings () != null ) {
250
- List <ParameterMapping > newParameterMappings = new ArrayList <ParameterMapping >(boundSql .getParameterMappings ());
251
- newParameterMappings .add (new ParameterMapping .Builder (ms .getConfiguration (), PAGEPARAMETER_FIRST , firstClass ).build ());
252
- newParameterMappings .add (new ParameterMapping .Builder (ms .getConfiguration (), PAGEPARAMETER_SECOND , secondClass ).build ());
345
+ List <ParameterMapping > newParameterMappings = new ArrayList <ParameterMapping >(
346
+ boundSql .getParameterMappings ());
347
+ newParameterMappings
348
+ .add (new ParameterMapping .Builder (ms .getConfiguration (), PAGEPARAMETER_FIRST , firstClass ).build ());
349
+ newParameterMappings .add (
350
+ new ParameterMapping .Builder (ms .getConfiguration (), PAGEPARAMETER_SECOND , secondClass ).build ());
253
351
MetaObject metaObject = MetaObjectUtil .forObject (boundSql );
254
352
metaObject .setValue ("parameterMappings" , newParameterMappings );
255
353
}
0 commit comments