ソースを参照

抽取Count优化SQL并提供测试类测试

Caratacus 8 年 前
コミット
5661784bf2

+ 5 - 26
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/PaginationInterceptor.java

@@ -16,9 +16,11 @@
 package com.baomidou.mybatisplus.plugins;
 
 import com.baomidou.mybatisplus.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.plugins.entity.CountOptimize;
 import com.baomidou.mybatisplus.plugins.pagination.DialectFactory;
 import com.baomidou.mybatisplus.plugins.pagination.IDialect;
 import com.baomidou.mybatisplus.plugins.pagination.Pagination;
+import com.baomidou.mybatisplus.toolkit.SqlUtils;
 import com.baomidou.mybatisplus.toolkit.StringUtils;
 import org.apache.ibatis.executor.parameter.ParameterHandler;
 import org.apache.ibatis.executor.statement.StatementHandler;
@@ -124,32 +126,9 @@ public class PaginationInterceptor implements Interceptor {
 					/*
 					 * COUNT 查询,去掉 ORDER BY 优化执行 SQL
 					 */
-					StringBuffer countSql = new StringBuffer("SELECT COUNT(1) AS TOTAL ");
-					if (page.isOptimizeCount()) {
-						String tempSql = originalSql.replaceAll("(?i)ORDER[\\s]+BY", "ORDER BY");
-						String indexOfSql = tempSql.toUpperCase();
-						if (!indexOfSql.contains("DISTINCT")) {
-							int formIndex = indexOfSql.indexOf("FROM");
-							int orderByIndex = indexOfSql.lastIndexOf("ORDER BY");
-							if (formIndex > -1) {
-								// 无排序情况处理
-								if (orderByIndex > -1) {
-									tempSql = tempSql.substring(0, orderByIndex);
-									countSql.append(tempSql.substring(formIndex));
-									orderBy = false;
-								} else {
-									countSql.append(tempSql.substring(formIndex));
-								}
-							} else {
-								countSql.append("FROM (").append(originalSql).append(") A");
-							}
-						} else {
-							countSql.append("FROM (").append(originalSql).append(") A");
-						}
-					} else {
-						countSql.append("FROM (").append(originalSql).append(") A");
-					}
-					page = this.count(countSql.toString(), connection, mappedStatement, boundSql, page);
+					CountOptimize countOptimize = SqlUtils.getCountOptimize(originalSql, page.isOptimizeCount());
+					orderBy = countOptimize.isOrderBy();
+					page = this.count(countOptimize.getCountSQL(), connection, mappedStatement, boundSql, page);
 					/** 总数 0 跳出执行 */
 					if (page.getTotal() <= 0) {
 						return invocation.proceed();

+ 45 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/plugins/entity/CountOptimize.java

@@ -0,0 +1,45 @@
+package com.baomidou.mybatisplus.plugins.entity;
+
+/**
+ * <p>
+ * 优化Count SQL实体
+ * </p>
+ *
+ * @author Caratacus
+ * @Date 2016-11-13
+ */
+public class CountOptimize {
+	/**
+	 * 是否排序
+	 */
+	private boolean orderBy = true;
+	/**
+	 * 优化后计算Count的SQL
+	 */
+	private String countSQL;
+
+	public boolean isOrderBy() {
+		return orderBy;
+	}
+
+	public void setOrderBy(boolean orderBy) {
+		this.orderBy = orderBy;
+	}
+
+	public String getCountSQL() {
+		return countSQL;
+	}
+
+	public void setCountSQL(String countSQL) {
+		this.countSQL = countSQL;
+	}
+
+	public static CountOptimize newInstance() {
+		return new CountOptimize();
+	}
+
+	@Override
+	public String toString() {
+		return "CountOptimize{" + "orderBy=" + orderBy + ", countSQL='" + countSQL + '\'' + '}';
+	}
+}

+ 55 - 0
mybatis-plus/src/main/java/com/baomidou/mybatisplus/toolkit/SqlUtils.java

@@ -0,0 +1,55 @@
+package com.baomidou.mybatisplus.toolkit;
+
+
+import com.baomidou.mybatisplus.plugins.entity.CountOptimize;
+
+/**
+ * <p>
+ * SqlUtils工具类
+ * </p>
+ *
+ * @author Caratacus
+ * @Date 2016-11-13
+ */
+public class SqlUtils {
+	/**
+	 * 获取CountOptimize
+	 * 
+	 * @param originalSql
+	 *            需要计算Count SQL
+	 * @param isOptimizeCount
+	 *            是否需要优化Count
+	 * @return CountOptimize
+	 */
+	public static CountOptimize getCountOptimize(String originalSql, boolean isOptimizeCount) {
+		CountOptimize countOptimize = CountOptimize.newInstance();
+		StringBuffer countSql = new StringBuffer("SELECT COUNT(1) AS TOTAL ");
+		if (isOptimizeCount) {
+			String tempSql = originalSql.replaceAll("(?i)ORDER[\\s]+BY", "ORDER BY");
+			String indexOfSql = tempSql.toUpperCase();
+			if (!indexOfSql.contains("DISTINCT")) {
+				int formIndex = indexOfSql.indexOf("FROM");
+				int orderByIndex = indexOfSql.lastIndexOf("ORDER BY");
+				if (formIndex > -1) {
+					// 有排序情况
+					if (orderByIndex > -1) {
+						tempSql = tempSql.substring(0, orderByIndex);
+						countSql.append(tempSql.substring(formIndex));
+						countOptimize.setOrderBy(false);
+						// 无排序情况
+					} else {
+						countSql.append(tempSql.substring(formIndex));
+					}
+				} else {
+					countSql.append("FROM (").append(originalSql).append(") A");
+				}
+			} else {
+				countSql.append("FROM (").append(originalSql).append(") A");
+			}
+		} else {
+			countSql.append("FROM (").append(originalSql).append(") A");
+		}
+		countOptimize.setCountSQL(countSql.toString());
+		return countOptimize;
+	}
+}

+ 67 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/SqlUtilsTest.java

@@ -0,0 +1,67 @@
+package com.baomidou.mybatisplus.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.baomidou.mybatisplus.plugins.entity.CountOptimize;
+import com.baomidou.mybatisplus.toolkit.SqlUtils;
+
+/**
+ * <p>
+ * 测试SqlUtils工具类
+ * </p>
+ *
+ * @author Caratacus
+ * @Date 2016-11-3
+ */
+public class SqlUtilsTest {
+	/**
+	 * 测试不规则Order by
+	 */
+	@Test
+	public void test1() {
+		String sql = "select * from test orDer    \r\n   by name";
+		CountOptimize countOptimize = SqlUtils.getCountOptimize(sql, true);
+		Assert.assertEquals("CountOptimize{orderBy=false, countSQL='SELECT COUNT(1) AS TOTAL from test '}",
+				countOptimize.toString());
+
+	}
+
+	/**
+	 * 测试distinct 如果存在不优化count sql
+	 */
+	@Test
+	public void test2() {
+		String sql = "select distinct name from test orDer       by name";
+		CountOptimize countOptimize = SqlUtils.getCountOptimize(sql, true);
+		Assert.assertEquals("CountOptimize{orderBy=true, countSQL='SELECT COUNT(1) AS TOTAL FROM (select distinct name from test orDer       by name) A'}",
+				countOptimize.toString());
+
+	}
+
+	/**
+	 * 测试没有from的情况 并且有格式化时间的情况
+	 */
+	@Test
+	public void test3() {
+		String sql = "select DATE_FORMAT('2016-05-01 18:31:33','%Y-%m-%d')";
+		CountOptimize countOptimize = SqlUtils.getCountOptimize(sql, true);
+		Assert.assertEquals(
+				"CountOptimize{orderBy=true, countSQL='SELECT COUNT(1) AS TOTAL FROM (select DATE_FORMAT('2016-05-01 18:31:33','%Y-%m-%d')) A'}",
+				countOptimize.toString());
+
+	}
+
+	/**
+	 * 测试没有order by的情况
+	 */
+	@Test
+	public void test4() {
+		String sql = "select DATE_FORMAT('2016-05-01 18:31:33','%Y-%m-%d') from test";
+		CountOptimize countOptimize = SqlUtils.getCountOptimize(sql, true);
+		Assert.assertEquals("CountOptimize{orderBy=true, countSQL='SELECT COUNT(1) AS TOTAL from test'}",
+				countOptimize.toString());
+
+	}
+
+}