这种场景非常常见,就是当前的查询语句是我们自定义的,想要在自己写的sql语句中通过分页插件来实现分页功能👑(比如说我需要在教师表中查询name不为空的⽤户,并且职称为讲师,年龄小于40的教师对象并将查询结果分页等等…)
还没有看过上一篇的朋友,这里是传送门:玩转MyBatis-Plus分页插件一:基本使用
如果对MybatisPlus分页插件基本使用已经非常熟练的朋友就接着往下看吧
玩自定义分页必须掌握的神器就是:条件构造器wrapper、Lambda条件构造器如果还没有学会的朋友可以去官网先学习一波
前面说到,分页它的本质就是内部封装了一个拦截器,对于满足满足条件的数据,起到一个过滤的作用🙋♀️这会和我们后续的自定义条件有关,毕竟也是同样的道理,你自定义一个条件来“筛选数据”,只展示满足条件的数据
上一篇博文我们在mapper的selectPage函数当中将wrapper设为null,则是查询全部数据。
自定义分页的核心就是:参照selectPage函数
自定义分页的重点就是:自定义函数的返回值必须为Page对象,你所定义的函数的第一个参数类型必须为Page
目标数据表t_product
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_product
-- ----------------------------
DROP TABLE IF EXISTS `t_product`;
CREATE TABLE `t_product` (
`id` int(0) NULL DEFAULT NULL,
`name` varchar(300) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`price` decimal(10, 0) NULL DEFAULT NULL,
`stock` int(0) NULL DEFAULT NULL,
`proPic` varchar(765) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`isHot` bit(1) NULL DEFAULT NULL,
`isSwiper` bit(1) NULL DEFAULT NULL,
`swiperPic` varchar(765) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '轮转图片的地址',
`swiperSort` int(0) NULL DEFAULT NULL COMMENT '排序',
`typeId` int(0) NULL DEFAULT NULL COMMENT '类别id',
`hotDateTime` datetime(0) NULL DEFAULT NULL COMMENT '设置热卖的时间',
`productIntroImgs` varchar(600) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`productParaImgs` varchar(600) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`description` varchar(600) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商品描述'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of t_product
-- ----------------------------
INSERT INTO `t_product` VALUES (1, '小米电视大师 82英寸', 10999, 3451, '21.png', b'0', b'1', '2.jpg', 3, 14, '2022-04-26 21:36:34', '\"\"', '\"\"', '\"\"');
INSERT INTO `t_product` VALUES (4, 'Xiaomi 11', 3799, 3232, '6.png', b'1', b'0', 'default.jpg', 0, 2, '2022-05-31 21:36:34', '', '', '「全版本领券立减200元,券后价3299元起;享至高24期免息;赠手机保护壳*1;【全款支付套装】赠果冻包」');
INSERT INTO `t_product` VALUES (5, 'Redmi K40 游戏增强版', 2299, 2005, '11.png', b'0', b'1', '1.jpg', 1, 39, NULL, '\"\"', '\"\"', '\"\"');
INSERT INTO `t_product` VALUES (6, 'Xiaomi 11 Pro', 4499, 2343, '1.png', b'1', b'0', 'default.jpg', 0, 2, '2021-09-12 21:36:34', '\"\"', NULL, NULL);
INSERT INTO `t_product` VALUES (7, 'Xiaomi MIX FOLD折叠屏手机', 7999, 2222, '2.png', b'1', b'0', 'default.jpg', 0, 3, '2021-10-28 21:36:34', '\"\"', NULL, NULL);
INSERT INTO `t_product` VALUES (8, 'Note 9 5G', 1199, 1111, '3.png', b'1', b'0', 'default.jpg', 0, 40, '2022-02-23 21:36:34', '\"\"', NULL, NULL);
INSERT INTO `t_product` VALUES (9, 'Xiaomi 10S', 2999, 1111, '4.png', b'1', b'0', 'default.jpg', 0, 2, '2021-12-28 21:36:34', '\"\"', NULL, NULL);
INSERT INTO `t_product` VALUES (10, 'Note 9 Pro 5G', 1399, 2222, '5.png', b'1', b'0', 'default.jpg', 0, 40, '2021-11-28 21:36:34', '\"\"', NULL, NULL);
INSERT INTO `t_product` VALUES (11, '黑鲨4', 2499, 3322, '7.png', b'1', b'0', 'default.jpg', 0, 41, '2021-11-28 21:36:34', '\"\"', NULL, NULL);
INSERT INTO `t_product` VALUES (12, 'Redmi K40 Pro 系列', 2499, 3244, '8.png', b'1', b'0', 'default.jpg', 0, 39, '2021-11-28 21:36:34', NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (14, 'Xiaomi Civi', 2599, 4444, '9.png', b'0', b'0', 'default.jpg', 0, 1, NULL, '', '', '「购机至高享24期免息;赠Redmi AirDots 2真无线蓝牙耳机;赠Keep会员7天体验卡;+110元得Air2 SE蓝牙耳机」');
INSERT INTO `t_product` VALUES (15, 'Xiaomi 11 Ultra', 5499, 4444, '10.png', b'0', b'0', 'default.jpg', 0, 2, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (16, '小米平板5', 1999, 444, '13.png', b'0', b'0', 'default.jpg', 0, 5, NULL, '', '', '11英寸大屏 2.5K超清显示 120Hz高刷新率');
INSERT INTO `t_product` VALUES (17, '小米平板5 Pro', 2499, 444, '14.png', b'0', b'0', 'default.jpg', 0, 5, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (19, 'RedmiBook Pro 15 增强版', 5299, 444, '15.png', b'0', b'0', 'default.jpg', 0, 6, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (20, 'Redmi G 2021', 6499, 1999, '16.png', b'0', b'1', '3.jpg', 2, 6, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (21, 'Redmi G 2021 锐龙版', 7499, 2000, '17.png', b'0', b'0', 'default.jpg', 0, 6, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (22, 'RedmiBook Pro 14 增强版', 4999, 777, '18.png', b'0', b'0', 'default.jpg', 0, 6, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (23, '小米笔记本 Pro 14 锐龙版', 5499, 666, '19.png', b'0', b'0', 'default.jpg', 0, 7, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (24, '小米笔记本 Pro 14 增强版', 5499, 666, '20.png', b'0', b'0', 'default.jpg', 0, 7, NULL, NULL, NULL, NULL);
INSERT INTO `t_product` VALUES (26, '1', 1, 1, 'default.jpg', b'0', b'0', 'default.jpg', 0, 6, NULL, '1', '1', NULL);
INSERT INTO `t_product` VALUES (27, '1', 2, 3, 'default.jpg', b'0', b'0', 'default.jpg', 0, 6, NULL, '5', '6', '4');
INSERT INTO `t_product` VALUES (28, '2', 3, 4, 'default.jpg', b'0', b'0', 'default.jpg', 0, 6, NULL, '6', '7', '5');
INSERT INTO `t_product` VALUES (29, '1', 1, 1, 'default.jpg', b'0', b'0', 'default.jpg', 0, 11, NULL, '1', '1', '1');
INSERT INTO `t_product` VALUES (30, '223335552', 322, 22355, 'default.jpg', b'0', b'0', 'default.jpg', 0, 6, NULL, '22333522', '22333544442', '22333511');
SET FOREIGN_KEY_CHECKS = 1;
例如:想要查询出价格大于某个值的产品并进行分页(这里为了测试sql定义了该值为1400)
共查询到18条数据
@Select("SELECT * FROM `t_product` where price>#{price}")
Page<Product> selectPageByMyself(@Param("page") Page<Product> page, @Param("price") Integer price);
@SpringBootTest
public class MybatisPageTest {
@Autowired
public ProductMapper mapper;
@Test
public void test(){
Page<Product> page = new Page<>(1,10);
mapper.selectPageByMyself(page,1400);
System.out.println(page);
}
}
我这里设置了每页10条数据
可以看到将第一页的数据全部查询出来了,修改参数即可查看第二页的数据
可以看到我这里只是简单的对price进行了筛选,如果说我现在的查询条件变得很复杂了,该怎么处理呢?这里要使用到的就是我们一直提到的条件构造器来解决这个问题
比如,我想要查询商品名称模糊查询,价格小于[前端传过来的值],isHot参数为[前端传过来的值]的商品有哪些,并进行分页
一般遇到这种指定条件的分页情况,都是通过前端传过来一个vo对象,然后根据这个vo对象进行操作解析,简单说明就是:我们不需要对product类全部字段进行操作,只需要几个重要字段就行了
以下是使用了thymeleaf来做测试
import lombok.Data;
/**
* @description: product vo对象类
* @author: xmonster_大魔王
* @create: 2022-07-28 20:00
**/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class ProductParam {
private String name;
private int price;
private Boolean ishot;
}
/**
*
* Mapper 接口
*
*
* @author xmonster_大魔王
* @since 2022-06-16
*/
@Mapper
public interface ProductMapper extends BaseMapper<Product> {
@Select("SELECT * FROM `t_product` where price>#{price}")
Page<Product> selectPageByMyself(@Param("page") Page<Product> page, @Param("price") Integer price);
@Select("SELECT * FROM `t_product` ${ew.customSqlSegment}")
Page<Product> selectPageByMyself2(@Param("page") Page<Product> page,@Param(Constants.WRAPPER) Wrapper<Product> wrapper);
}
这里主要看selectPageByMyself2方法啦,直接传wrapper即可,这里的sql语句当中使用了 ${ew.customSqlSegment},那么它具体的用法是什么呢?
${ew.customSqlSegment}
拼接where后的语句(包括where,需注意在动态SQL中不处于标签内)
我们来一起看看我们的SQL语句就明白啦
这里可以看到,我们编写了一个ProductParam的对象,并对这个对象填入我们需要查询的信息,这里我要查询商品名称中包含“x”,价格小于8000,并且ishot属性为true
@GetMapping("")
public String index(Model model){
ProductParam param = new ProductParam().builder().name("x").price(8000).ishot(true).build();
Page<Product> page = new Page<>(1,10);
LambdaQueryWrapper<Product> wrapper = Wrappers.lambdaQuery(Product.class)
.like(Product::getName, param.getName())
.lt(Product::getPrice, param.getPrice())
.eq(Product::getIshot, param.getIshot());
mapper.selectPageByMyself2(page,wrapper);
model.addAttribute("productList",page.getRecords());
return "index";
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>product分页测试title>
<link rel="stylesheet" th:href="@{/asserts/bootstrap5/css/bootstrap.min.css}" />
head>
<body>
<table class="table table-dark table-hover" style="margin:10px auto;width: 800px">
<thead>
<th>nameth>
<th>priceth>
<th>stockth>
<th>isHotth>
<th>typeIdth>
thead>
<tbody>
<tr th:each="product: ${productList}">
<td ><th:block th:text="${product.name}">th:block>td>
<td ><th:block th:text="${product.price}">th:block>td>
<td ><th:block th:text="${product.stock}">th:block>td>
<td ><th:block th:text="${product.ishot}">th:block>td>
<td ><th:block th:text="${product.typeid}">th:block>td>
tr>
tbody>
table>
<script th:src="@{/asserts/bootstrap5/js/bootstrap.bundle.min.js}">script>
<script th:src="@{/asserts/jquery/jquery.min.js}">script>
body>
html>
看到sql语句后面自动添加了where条件进行筛选,具体和${ew.customSqlSegment}有关的其他信息可以去查查资料深入一下👓👓它可是非常常用的
好啦,这就是自定义分页函数基础的内容,体验了一波之后我相信更多的朋友想要的效果当然是和前端进行交互的那种真正感受分页的快乐,这里的操作都是在后台进行输出,前台只是简单的展示,与前端进行交互的内容我会放在下一期~也会介绍很多好看的分页效果