MybatisPlus-列表分页展示
# 540.MybatisPlus-列表分页展示
接下来我们使用 MybatisPlus,完成表格的渲染以及分页展示
# 新增 service 层
在之前,我们都是在接口层定义好方法,然后在实现类中调用 Mapper 接口中的方法。
为此 MybatisPlus 还给 service 层做了简化,我们只需继承 IService
类,即可直接调用 Mapper 中的方法:
package com.peterjxl.learnspringbootwebadmin.service;
public interface UserService {
}
2
3
4
而实现类,则只需实现 ServiceImpl
类即可,也不用自己做实现。第一个参数是 Mapper,第二个类是返回的类型:
package com.peterjxl.learnspringbootwebadmin.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.peterjxl.learnspringbootwebadmin.bean.User;
import com.peterjxl.learnspringbootwebadmin.mapper.UserMapper;
import com.peterjxl.learnspringbootwebadmin.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}
2
3
4
5
6
7
8
9
10
11
一般来说,都是给 service 层定义一个接口,然后定义一个实现类的。
为了规范,我们将之前的
StudentService
类,CityService
类也改造下
然后我们就可以查询数据了
@GetMapping("/dynamic_table")
public String dynamic_table(Model model){
List<User> list = userService.list();
model.addAttribute("users", list);
return "table/dynamic_table";
}
2
3
4
5
6
修改下前端表单 dynamic_table.html
:
<thead>
<tr>
<th>#</th>
<th>id</th>
<th>name</th>
<th>age</th>
<th>email</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr class="gradeX" th:each="user,stat: ${users}">
<td th:text="${stat.count}">count</td>
<td th:text="${user.id}">id</td>
<td th:text="${user.name}">name</td>
<td th:text="${user.age}">age</td>
<td >[[${user.email}]]</td>
</tr>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
重启,可以看到正常渲染:
# 分页
接下来我们优化下分页查询。首先根据官网文档配置下分页插件,也就是注入一个 Bean
package com.peterjxl.learnspringbootwebadmin.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisConfig {
/**
* MybatisPlusInterceptor
* @return
*/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,默认 500 条,-1 不受限制
// paginationInterceptor.setLimit(500);
// 开启 count 的 join 优化,只针对部分 left join
//这是分页拦截器
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
paginationInnerInterceptor.setOverflow(true); //设置请求的页面大于最大页后的操作,true调回到首页,false 继续请求 默认false
paginationInnerInterceptor.setMaxLimit(500L); //设置最大单页限制数量,默认 500 条,-1 不受限制
mybatisPlusInterceptor.addInnerInterceptor(paginationInnerInterceptor);
return mybatisPlusInterceptor;
}
}
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
首先,显示第几页是前端传的,因此我们在参数中获取,默认是 1:
public String dynamic_table(@RequestParam(value = "pn", defaultValue = "1") Integer pn, Model model)
//...............
2
然后我们就可以使用 Page 对象了。首先构建一个 page 对象,然后查询的时候传入 page 对象 :
Page<User> userPage = new Page<>(pn, 2); // 参数:第几页,每页显示的条数
Page<User> page = userService.page(userPage, null);
model.addAttribute("page", page);
return "table/dynamic_table";
2
3
4
page 对象会包含很多信息,例如查询出来的数据,当前是第几页,总共多少页等,例如:
System.out.println("当前页码:" + page.getCurrent());
System.out.println("总页码:" + page.getPages());
System.out.println("总记录数:" + page.getTotal());
System.out.println("每页显示的记录数:" + page.getSize());
System.out.println("是否有下一页:" + page.hasNext());
System.out.println("是否有上一页:" + page.hasPrevious());
2
3
4
5
6
相应的,前端也要修改,首先遍历是从 page 中取值。我们顺便在下方添加一个分页记录:
<tr class="gradeX" th:each="user,stat: ${page.records}">
<td th:text="${stat.count}">count</td>
<td th:text="${user.id}">id</td>
<td th:text="${user.name}">name</td>
<td th:text="${user.age}">age</td>
<td >[[${user.email}]]</td>
</tr>
</tbody>
<tfoot></tfoot>
</table>
<div class="row-fluid">
<div class="span6">
<div class="dataTables_info" id="dynamic-table_info">
当前第[[${page.current}]]页 总计 [[${page.pages}]]页 共[[${page.total}]]条记录
</div>
</div>
</div>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
重启项目,效果:
接下来我们处理下分页按钮
<div class="row-fluid">
<div class="span6">
<div class="dataTables_info" id="dynamic-table_info">
当前第[[${page.current}]]页 总计 [[${page.pages}]]页 共[[${page.total}]]条记录
</div>
</div>
<div class="span6">
<div class="dataTables_paginate paging_bootstrap pagination">
<ul>
<li class="prev disabled"><a href="#">← 前一页</a></li>
<li th:class="${num == page.current?'active':''}"
th:each="num:${#numbers.sequence(1,page.pages)}" >
<a th:href="@{/dynamic_table(pn=${num})}">[[${num}]]</a>
</li>
<li class="next disabled"><a href="#">下一页 → </a></li>
</ul>
</div>
</div>
</div>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
简单说下代码:首先 class 属性会将当前页高亮显示,然后遍历生成多个 li(数量由页数决定),然后超链接里面是跳转到第几页,并且会传参 num。前一页和下一页的功能,暂时先不做。
运行效果:
# 删除用户
接下来我们完成删除功能。需求:
- 在操作列中新增一个删除按
- 点击删除,能删除当前用户,然后重新渲染当前页面
新增一个删除用户的方法
@GetMapping("/user/delete/{id}")
public String deleteUser(@PathVariable("id") Long id,
@RequestParam(value = "pn", defaultValue = "1") Integer pn,
RedirectAttributes ra){
userService.removeById(id);
ra.addAttribute("pn", pn);
return "redirect:/dynamic_table"; // 删除后回到当前页
}
2
3
4
5
6
7
8
这里我们用了 RedirectAttributes
属性,它可以给重定向添加参数。当然,参数少的情况下也可以自己手动拼接,例如:
return "redirect:/dynamic_table?pn=" + pn; // 删除后回到当前页
前端也要添加一个删除超链接:
<tr class="gradeX" th:each="user,stat: ${page.records}">
<td th:text="${stat.count}">count</td>
<td th:text="${user.id}">id</td>
<td th:text="${user.name}">name</td>
<td th:text="${user.age}">age</td>
<td >[[${user.email}]]</td>
<td>
<a th:href="@{/user/delete/{id}(id=${user.id},pn=${users.current})}" class="btn btn-danger btn-sm" type="button">删除</a>
</td>
</tr>
2
3
4
5
6
7
8
9
10
同学们也可以练习下新增和修改功能,这里就不演示了
# 源码
已将本文源码上传到 Gitee (opens new window) 或 GitHub (opens new window) 的分支 demo15,读者可以通过切换分支来查看本文的示例代码