PageMySqlDialectPlus.java 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. package com.template.common.utils;
  2. import com.github.pagehelper.Page;
  3. import com.github.pagehelper.dialect.helper.MySqlDialect;
  4. import com.github.pagehelper.util.MetaObjectUtil;
  5. import lombok.extern.slf4j.Slf4j;
  6. import org.apache.commons.lang3.StringUtils;
  7. import org.apache.ibatis.cache.CacheKey;
  8. import org.apache.ibatis.mapping.BoundSql;
  9. import org.apache.ibatis.mapping.MappedStatement;
  10. import org.apache.ibatis.mapping.ParameterMapping;
  11. import org.apache.ibatis.reflection.MetaObject;
  12. import java.util.ArrayList;
  13. import java.util.List;
  14. import java.util.Map;
  15. import java.util.regex.Matcher;
  16. import java.util.regex.Pattern;
  17. @Slf4j
  18. public class PageMySqlDialectPlus extends MySqlDialect {
  19. //正则表达式
  20. private static final String pattern = "([\\s|\\S]*?)/\\*\\s*MAPPINGLIMIT\\s*\\*/\\s*([\\s|\\S]*)";
  21. private static final Pattern PATTERN = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
  22. /**
  23. * 把limit语句放到 MAPPINGLIMIT标记所在的位置,也就是主表的位置,对主表进行分页
  24. *
  25. * @return 加limit后的sql
  26. */
  27. @Override
  28. public String getPageSql(String sql, Page page, CacheKey pageKey) {
  29. //如果不匹配正则,走原始的sql
  30. if (!Pattern.matches(pattern, sql)) {
  31. return super.getPageSql(sql, page, pageKey);
  32. }
  33. String beforeLimitSql = "";
  34. String afterLimitsql = "";
  35. Matcher m = PATTERN.matcher(sql);
  36. if (m.find()) {
  37. //MAPPINGLIMIT标记前的sql语句
  38. beforeLimitSql = m.group(1);
  39. //MAPPINGLIMIT标记后的sql语句
  40. afterLimitsql = m.group(2);
  41. }
  42. String limitSql = "";
  43. if (page.getStartRow() == 0) {
  44. limitSql = " LIMIT ? ";
  45. } else {
  46. limitSql = " LIMIT ?, ? ";
  47. }
  48. String sqlString = beforeLimitSql + " " + limitSql + " " + afterLimitsql;
  49. return sqlString;
  50. }
  51. /**
  52. * 把分页参数放到参数列表里
  53. *
  54. * @return
  55. */
  56. @Override
  57. public Object processPageParameter(MappedStatement ms, Map<String, Object> paramMap, Page page, BoundSql boundSql, CacheKey pageKey) {
  58. //如果不匹配正则,走原始的sql设置
  59. if (!Pattern.matches(pattern, boundSql.getSql())) {
  60. return super.processPageParameter(ms, paramMap, page, boundSql, pageKey);
  61. }
  62. //设置参数
  63. paramMap.put(PAGEPARAMETER_FIRST, page.getStartRow());
  64. paramMap.put(PAGEPARAMETER_SECOND, page.getPageSize());
  65. pageKey.update(page.getStartRow());
  66. pageKey.update(page.getPageSize());
  67. //设置参数 因为limit放到中间位置,所以要计算出来分页数据的放置位置
  68. Matcher m = PATTERN.matcher(boundSql.getSql());
  69. String beforeLimitSql = null;
  70. int limitIndex;
  71. if (m.find()) {
  72. //MAPPINGLIMIT标记前的sql语句
  73. beforeLimitSql = m.group(1);
  74. }
  75. //计算sql里有几个参数,按数据位置添加page
  76. limitIndex = StringUtils.countMatches(beforeLimitSql, "?");
  77. if (boundSql.getParameterMappings() != null) {
  78. List<ParameterMapping> newParameterMappings = new ArrayList<ParameterMapping>(boundSql.getParameterMappings());
  79. if (page.getStartRow() == 0) {
  80. newParameterMappings.add(limitIndex,new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_SECOND, int.class).build());
  81. } else {
  82. newParameterMappings.add(limitIndex,new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_FIRST, long.class).build());
  83. newParameterMappings.add(limitIndex+1,new ParameterMapping.Builder(ms.getConfiguration(), PAGEPARAMETER_SECOND, int.class).build());
  84. }
  85. MetaObject metaObject = MetaObjectUtil.forObject(boundSql);
  86. metaObject.setValue("parameterMappings", newParameterMappings);
  87. }
  88. return paramMap;
  89. }
  90. }