服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Spring Boot 集成PageHelper的使用方法

Spring Boot 集成PageHelper的使用方法

2022-11-15 13:48剑圣无痕 Java教程

这篇文章主要介绍了Spring Boot 集成PageHelper的使用方法,文章内容围绕主题展开详细介绍,需要的小伙伴可以参考一下,希望对你的学习有所帮助

前言:

项目中数据分页是一个很常见的需求,目前大部分项目都会使用pagehelper进行分页,那么在使用的过程中是否考虑如下问题?

Spring Boot 集成PageHelper的使用方法

一、基本集成

引入jar包

?
1
2
3
4
5
<dependency>
       <groupId>com.github.pagehelper</groupId>
       <artifactId>pagehelper-spring-boot-starter</artifactId>
       <version>${pagehelper.version}</version>
</dependency>

Yml配置文件中添加相关配置

?
1
2
3
4
5
pagehelper:
    helperDialect: mysql
    reasonable: true
    supportMethodsArguments: true
    params: count=countSql

封装相关分页方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
分页参数类
 public class PageParam<T> implements Serializable
{
    private static final long serialVersionUID = -7916211163897873899L;
    private int pageNum=1;
    private int pageSize=10;
    //条件参数
    private T param;
    //排序字段
    private String orderBy;
 
    public int getPageSize()
    {
        return pageSize;
    }
    public void setPageSize(int pageSize)
    {
        this.pageSize = pageSize;
    }
    public int getPageNum()
    {
        return pageNum;
    }
    public void setPageNum(int pageNum)
    {
        this.pageNum = pageNum;
    }
    public T getParam()
    {
        return param;
    }
    public void setParam(T param)
    {
        this.param = param;
    }
    public String getOrderBy()
    {
        return orderBy;
    }
    public void setOrderBy(String orderBy)
    {
        //需要注意sql注入
        this.orderBy = orderBy;
    }
}
分页结果类
public class PagedList<T> implements Serializable
{
    private static final long serialVersionUID = -1253790062865437768L;
    private int pageNum = 1;
    private List<T> data = null;
    private int pageCount = 0;
    private int recordCount = -1;
    private int pagingType = 0;
    private int pageSize;
    private String orderBy;
    /**
     * @return the pageSize
     */
    public int getPageSize()
    {
        return pageSize;
    }
    /**
     * @param pageSize
     *            the pageSize to set
     */
    public void setPageSize(int pageSize)
    {
        if (pageSize <= 0)
        {
            return;
        }
        this.pageSize = pageSize;
    }
 
    /**
     * @return the pageCount
     */
    public int getPageCount()
    {
        return pageCount;
    }
    /**
     * @param pageCount
     *            the pageCount to set
     */
    public void setPageCount(int pageCount)
    {
        if (pageCount <= 0)
        {
            return;
        }
        this.pageCount = pageCount;
    }
    /**
     * @return the recordCount
     */
    public int getRecordCount()
    {
        return recordCount;
    }
    /**
     * @param recordCount
     *            the recordCount to set
     */
    public void setRecordCount(int recordCount)
    {
        this.recordCount = recordCount;
        calcPageCount();
    }
    private void calcPageCount()
    {
        if (this.recordCount < 0)
        {
            return;
        }
        int tmp = this.recordCount % getPageSize();
        this.pageCount = (tmp == 0 ? (this.recordCount / getPageSize())
                : (this.recordCount / getPageSize() + 1));
        if (this.pageNum > this.pageCount && this.pageCount != 0)
        {
            this.pageNum = this.pageCount;
        }
        this.pageNum = this.pageCount;
    }
    public void setData(List<T> data)
    {
        this.data = data;
        if (ObjectUtil.isNotEmpty(data) && this.recordCount == -1)
        {
            this.recordCount = data.size();
        }
    }
    public List<T> getData()
    {
        return data;
    }
    /**
     * @return the pagingType
     */
    public int getPagingType()
    {
        return pagingType;
    }
    /**
     * @param pagingType
     *            the pagingType to set
     */
    public void setPagingType(int pagingType)
    {
        this.pagingType = pagingType;
    }
 
    public void setOrderBy(String orderBy)
    {
        this.orderBy = orderBy;
    }
    public int getPageNum()
    {
        return pageNum;
    }
    public void setPageNum(int pageNum)
    {
        this.pageNum = pageNum;
    }
    public String getOrderBy()
    {
        return orderBy;
    }
}
分页工具类
public class PageUtils implements Serializable
{
    private static final long serialVersionUID = 377943433889798799L;
    public static <T> PagedList<T> exportPagedList(PageParam<T> pageParam)
    {
        PagedList<T> pl = new PagedList<T>();
        // pagesize
        int pageSize = pageParam.getPageSize();
        if (pageSize <= 0)
        {
            pageSize = 10;
        }
        else
        {
            pl.setPageSize(pageSize);
        }
        int pageNum  = pageParam.getPageNum();
        pl.setPageNum(pageNum);
       String orderBy= pageParam.getOrderBy();
       if(StringUtil.isNotEmpty(orderBy))
       {
           //防止sql注入
           String orderBySql=SQLFilter.sqlInject(orderBy);
           pl.setOrderBy(orderBySql);
       }
        return pl;
    }
    public static <T>PagedList<T> toPageList(PageInfo<T> spage)
    {
        PagedList<T> pagedList = new PagedList<T>();
        pagedList.setPageSize((int) spage.getPageSize());
        pagedList.setPageNum((int) spage.getPageNum());
        pagedList.setRecordCount((int) spage.getTotal());
        pagedList.setData(spage.getList());
        pagedList.setPageCount((int) spage.getPages());
        return pagedList;
    }
}

示例代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
@PostMapping("getPageList")
  public Result getPageList(@RequestBody PageParam<TUser> pageParm)
  {
     //接收参数
      PagedList<TUser> pl =PageUtils.exportPagedList(pageParm);
      return Result.success(userService.queryPageList(pl, pageParm.getParam()));
  }
public PagedList<TUser> queryPageList(PagedList<TUser> page,TUser user)
  {
     PageInfo<TUser> pageInfo= PageHelper.startPage(page).doSelectPageInfo(()-> list(user));
     //转换结果
     return PageUtils.toPageList(pageInfo);
  }

前段传入参数

?
1
2
3
4
5
6
7
8
9
10
{
    "pageSize":10,
    "pageNum":"1",
    //查询条件
     "param":{
         "name":"张三210001"
    },
    //排序字段
    "orderBy":"age desc"
}

执行结果

2022-04-15 22:26:39.914 [http-nio-9090-exec-9] DEBUG [613920d89eb54bfd8601c93ec8572dcf] c.s.f.m.UserMapper.queryPageList - ==>  Preparing: SELECT * FROM t_user u LEFT JOIN t_user_role ur ON ur.userOid = u.oid WHERE name = ? order by age desc LIMIT ? 
2022-04-15 22:26:39.919 [http-nio-9090-exec-9] DEBUG [613920d89eb54bfd8601c93ec8572dcf] c.s.f.m.UserMapper.queryPageList - ==> Parameters: 张三210001(String), 10(Integer)
2022-04-15 22:26:40.267 [http-nio-9090-exec-9] DEBUG [613920d89eb54bfd8601c93ec8572dcf] c.s.f.m.UserMapper.queryPageList - <==      Total: 1

基础的分页查询已经发完成了,下面解答上面的问题的方法

二、分页中的排序字段如何防止SQL注入问题

对于前段传入的排序字段,我们需要进行SQL过滤处理,关于这个问题其实在上述的分页封装类中已经进行了解决

Spring Boot 集成PageHelper的使用方法

示例代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class SQLFilter
{
    public static String sqlInject(String str)
    {
        if (StringUtil.isBlank(str))
        {
            return null;
        }
        // 去掉'|"|;|\字符
        str = StringUtil.replace(str, "'", "");
        str = StringUtil.replace(str, "\"", "");
        str = StringUtil.replace(str, ";", "");
        str = StringUtil.replace(str, "\\", "");
        // 转换成小写
        str = str.toLowerCase();
        // 非法字符
        String[] keywords = { "master", "truncate", "insert", "select",
                "delete", "update", "declare", "alert", "drop" };
        // 判断是否包含非法字符
        for (String keyword : keywords)
        {
            if (str.indexOf(keyword) != -1)
            {
                throw new SysException("包含非法字符");
            }
        }
        return str;
    }
}

三、复杂的SQL分页语句

复杂的SQL分页语句,需要自定义SQL的count语句如何实现呢?

PageHelper实现分页,默认是查询自定义的count语句是否存在,如果存在就用自定义的语句,否则就在外层包装查询的语句,而自定义count语句只需要在在查询语句名称后面添加_COUNT即可。例如

查询集合的语句名称为queryPageList,那么查询count的语句为queryPageList_COUNT,返回Long类型即可。

?
1
2
3
4
5
6
7
<select id="queryPageList_COUNT" resultType="java.lang.Long">
     select count(1) from t_user  u
     left join t_user_role ur on ur.userOid=u.oid
     <where>
      <if test="name != null">name=#{name}</if>
     </where>
</select>

四、分页失效的常见的场景有哪些?

1.pageHelper分页查询有个特殊的要求,查询下sql语句一定要紧跟在分页查询的后面,否则分页查询会失效。之前采用的如下写法容易失效,建议采用java8的写法

?
1
2
3
4
5
PageHelper.startPage(pagedList.getPageNum(),pagedList.getPageSize());
      //紧跟分页查询后面
      List<TUser> list = list(user);
      PageInfo<TUser> pageInfo =new PageInfo<>(list);
      return PageUtils.toPageList(pageInfo);

2.注意pagehelper的reasonable 默认为false,遇到查询页数大于总页数时,出现分页失败

pagehelper的reasonable 默认为false,遇到查询页数大于总页数时,查询为空;当reasonable设置为true时,遇到查询页数大于总页数时,查询最后一页数据;

3.PageHelper先开启分页,后对list数据操作将会导致分页错误

示例代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
public PageInfo<TUserVO> getUserPageList(int pageNum, int pageSize) {
    PageHelper.startPage(pageNum,pageSize);
    List<TUserVO> tUserVOsByView = userMapper.getUserList();
    List<TUserVO> TUserVOs = new ArrayList<>();
    for (TUserVO TUserVO : tUserVOsByView) {
        TUserVO TUserVOSingle = new TUserVO();
        TUserVOSingle.setHdId(TUserVO.getHdId());
        TUserVOs.add(TUserVOSingle);
    }
    PageInfo<TUserVO> pageViewInfo = new PageInfo<>(TUserVOs);
    return pageViewInfo;
}

4.PageHelper先对list数据操作,后开启分页,将会导致分页失效

示例代码:

?
1
2
3
4
5
6
7
8
9
10
11
public PageInfo<TUserVO> getUserPageList(int pageNum, int pageSize) {      
    List<TUserVO> tUserVOsByView = userMapper.getUserList();
    List<TUserVO> TUserVOs = new ArrayList<>();
    for (TUserVO TUserVO : tUserVOsByView) {
        TUserVO TUserVOSingle = new TUserVO();
        TUserVOSingle.setHdId(TUserVO.getHdId());
    }
    PageHelper.startPage(pageNo,pageSize);
    PageInfo<TUserVO> pageViewInfo = new PageInfo<>(TUserVOs);
    return pageViewInfo;
}

大家需要注意下,抽时间可以去验证下结果。

五、大表数据PageHelper分页性能如何

PageHelper 对于大表查询数据量越大,性能越差,这是因为PageHelper分页是自动在sql语句后面拼接limit没有进行相关的优化,一旦数据大,性能就比较慢。

例如:

优化前SQL语句:

?
1
SELECT d.* FROM tag_detail d LIMIT 10000000,10

查询的时间大概需要10秒左右,执行速度比较慢。

优化后SQL语句:

?
1
2
3
4
SELECT d.* FROM tag_detail d
INNER JOIN
    (SELECT oid FROM tag_detail LIMIT 10000000,10) t
ON d.oid= t.oid;

子查询先通过分页查询主键字段,然后进行关联查询,经过优化后,查询时间大概为1秒左右。性能大幅度提升。

总结:

本文讲解了PageHelper的基本的使用和相关的问题,这些都是我从实际的项目中总结出来的问题以及相关的解决方案,大家在使用的时候要特别注意,不要放同样的错误。

到此这篇关于Spring Boot 集成PageHelper的使用方法的文章就介绍到这了,更多相关Spring Boot 集成PageHelper内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://juejin.cn/post/7086854293080260639

延伸 · 阅读

精彩推荐