CachePaginationInterceptor.java 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /**
  2. * Copyright (c) 2011-2020, hubin (jobob@qq.com).
  3. * <p>
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. * <p>
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. * <p>
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.baomidou.mybatisplus.plugins;
  17. import java.sql.Connection;
  18. import java.util.Properties;
  19. import org.apache.ibatis.executor.Executor;
  20. import org.apache.ibatis.executor.statement.StatementHandler;
  21. import org.apache.ibatis.mapping.BoundSql;
  22. import org.apache.ibatis.mapping.MappedStatement;
  23. import org.apache.ibatis.plugin.Interceptor;
  24. import org.apache.ibatis.plugin.Intercepts;
  25. import org.apache.ibatis.plugin.Invocation;
  26. import org.apache.ibatis.plugin.Plugin;
  27. import org.apache.ibatis.plugin.Signature;
  28. import org.apache.ibatis.reflection.MetaObject;
  29. import org.apache.ibatis.reflection.SystemMetaObject;
  30. import org.apache.ibatis.session.ResultHandler;
  31. import org.apache.ibatis.session.RowBounds;
  32. import com.baomidou.mybatisplus.plugins.pagination.DialectFactory;
  33. import com.baomidou.mybatisplus.plugins.pagination.Pagination;
  34. import com.baomidou.mybatisplus.parser.AbstractSqlParser;
  35. import com.baomidou.mybatisplus.parser.SqlInfo;
  36. import com.baomidou.mybatisplus.toolkit.PluginUtils;
  37. import com.baomidou.mybatisplus.toolkit.SqlUtils;
  38. import com.baomidou.mybatisplus.toolkit.StringUtils;
  39. /**
  40. * <p>
  41. * 缓存分页拦截器
  42. * </p>
  43. *
  44. * @author hubin
  45. * @Date 2016-01-23
  46. */
  47. @Intercepts({@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
  48. @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
  49. public class CachePaginationInterceptor extends PaginationInterceptor implements Interceptor {
  50. // COUNT SQL 解析
  51. private AbstractSqlParser sqlParser;
  52. /* Count优化方式 */
  53. private String optimizeType = "default";
  54. /* 方言类型 */
  55. private String dialectType;
  56. /* 方言实现类 */
  57. private String dialectClazz;
  58. /**
  59. * Physical Pagination Interceptor for all the queries with parameter
  60. * {@link org.apache.ibatis.session.RowBounds}
  61. */
  62. public Object intercept(Invocation invocation) throws Throwable {
  63. Object target = invocation.getTarget();
  64. if (target instanceof StatementHandler) {
  65. StatementHandler statementHandler = (StatementHandler) PluginUtils.realTarget(invocation.getTarget());
  66. MetaObject metaStatementHandler = SystemMetaObject.forObject(statementHandler);
  67. RowBounds rowBounds = (RowBounds) metaStatementHandler.getValue("delegate.rowBounds");
  68. if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
  69. return invocation.proceed();
  70. }
  71. BoundSql boundSql = (BoundSql) metaStatementHandler.getValue("delegate.boundSql");
  72. String originalSql = boundSql.getSql();
  73. if (rowBounds instanceof Pagination) {
  74. Pagination page = (Pagination) rowBounds;
  75. boolean orderBy = true;
  76. if (page.isSearchCount()) {
  77. String tempSql = originalSql.replaceAll("(?i)ORDER[\\s]+BY", "ORDER BY");
  78. int orderByIndex = tempSql.toUpperCase().lastIndexOf("ORDER BY");
  79. if(orderByIndex <= -1) {
  80. orderBy = false;
  81. }
  82. }
  83. String buildSql = SqlUtils.concatOrderBy(originalSql, page, orderBy);
  84. originalSql = DialectFactory.buildPaginationSql(page, buildSql, dialectType, dialectClazz);
  85. } else {
  86. // support physical Pagination for RowBounds
  87. originalSql = DialectFactory.buildPaginationSql(rowBounds, originalSql, dialectType, dialectClazz);
  88. }
  89. metaStatementHandler.setValue("delegate.boundSql.sql", originalSql);
  90. metaStatementHandler.setValue("delegate.rowBounds.offset", RowBounds.NO_ROW_OFFSET);
  91. metaStatementHandler.setValue("delegate.rowBounds.limit", RowBounds.NO_ROW_LIMIT);
  92. } else {
  93. RowBounds rowBounds = (RowBounds) invocation.getArgs()[2];
  94. if (rowBounds == null || rowBounds == RowBounds.DEFAULT) {
  95. return invocation.proceed();
  96. }
  97. MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
  98. Executor executor = (Executor) invocation.getTarget();
  99. Connection connection = executor.getTransaction().getConnection();
  100. Object parameterObject = invocation.getArgs()[1];
  101. BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
  102. String originalSql = boundSql.getSql();
  103. if (rowBounds instanceof Pagination) {
  104. Pagination page = (Pagination) rowBounds;
  105. if (page.isSearchCount()) {
  106. SqlInfo sqlInfo = SqlUtils.getCountOptimize(sqlParser, originalSql, optimizeType,
  107. dialectType, page.isOptimizeCount());
  108. super.queryTotal(sqlInfo.getSql(), mappedStatement, boundSql, page, connection);
  109. if (page.getTotal() <= 0) {
  110. return invocation.proceed();
  111. }
  112. }
  113. }
  114. }
  115. return invocation.proceed();
  116. }
  117. public Object plugin(Object target) {
  118. if (target instanceof Executor) {
  119. return Plugin.wrap(target, this);
  120. }
  121. if (target instanceof StatementHandler) {
  122. return Plugin.wrap(target, this);
  123. }
  124. return target;
  125. }
  126. public void setProperties(Properties prop) {
  127. String dialectType = prop.getProperty("dialectType");
  128. String dialectClazz = prop.getProperty("dialectClazz");
  129. if (StringUtils.isNotEmpty(dialectType)) {
  130. this.dialectType = dialectType;
  131. }
  132. if (StringUtils.isNotEmpty(dialectClazz)) {
  133. this.dialectClazz = dialectClazz;
  134. }
  135. }
  136. public void setDialectType(String dialectType) {
  137. this.dialectType = dialectType;
  138. }
  139. public void setOptimizeType(String optimizeType) {
  140. this.optimizeType = optimizeType;
  141. }
  142. public void setSqlParser(AbstractSqlParser sqlParser) {
  143. this.sqlParser = sqlParser;
  144. }
  145. }