如何解决mysql深度分页问题

  package com.ciih.qbbs.config;

  import cn.hutool.core.util.ReUtil;

  import cn.hutool.core.util.StrUtil;

  import com.baomidou.mybatisplus.annotation.TableId;

  import com.ejlchina.searcher.SearchSql;

  import com.ejlchina.searcher.SqlInterceptor;

  import com.ejlchina.searcher.SqlSnippet;

  import com.ejlchina.searcher.param.FetchType;

  import org.springframework.stereotype.Component;

  import java.lang.reflect.Field;

  import java.util.List;

  import java.util.Map;

  /**

  * BeanSearcher的Sql拦截器:优化深度分页

  *

  * @author sunziwen

  */

  @Component

  public class SqlInterceptorImpl implements SqlInterceptor {

  @Override

  public SearchSql intercept(SearchSql searchSql, Map paraMap, FetchType fetchType) {

  /**

  * 改造思路

  *

  * <>

  * 前:SELECT * FROM table1 t1 LIMIT 200000,20;

  * 后:SELECT * FROM table1 t1 JOIN ( SELECT id FROM table1 LIMIT 200000, 20 ) t99 ON t1.id = t99.id;

  *

  */

  Field[] fields = searchSql.getBeanMeta().getBeanClass().getDeclaredFields();

  String primaryColumnName = null;

  for (Field field : fields) {

  //这里使用了mybatis_plus的注解作为主键标识

  TableId tableId = field.getAnnotation(TableId.class);

  if (tableId != null) {

  if (!"".equals(tableId.value())) {

  primaryColumnName = tableId.value();

  } else {

  //驼峰转下划线

  primaryColumnName = StrUtil.toUnderlineCase(field.getName());

  }

  }

  }

  //如果没有主键标识,则不能进行SQL优化。

  if (primaryColumnName == null) {

  return searchSql;

  }

  //正则表达式获取where之后语句

  List limits = ReUtil.findAll("where[\s\S]*limit[ ]+[?]{1}[ ]*,[ ]+[?]{1}", searchSql.getListSqlString(), 0);

  //如果不分页,则不进行SQL优化,即语句中没有limit关键字不优化。

  if (limits.size() == 0) {

  return searchSql;

  }

  //表名小片段

  SqlSnippet tableSnippet = searchSql.getBeanMeta().getTableSnippet();

  //合成子查询SQL

  String inSql = "JOIN ( SELECT " + primaryColumnName + " FROM " + tableSnippet.getSql() + " " + limits.get(0) + " ) t99 ON t1." + primaryColumnName + " = t99." + primaryColumnName + ";";

  //合成整条SQL

  String replace = searchSql.getListSqlString().replace(limits.get(0), inSql);

  //替换

  searchSql.setListSqlString(replace);

  return searchSql;

  }

  }