Mybatis Plus带多条件的多表联合、分页、排序查询
声明:本文系原创,转载请注明出处。
注意:本程序使用SpringBoot+Mybatis Plus
一、现有表
student学生表:
id | stuName | stuAge | graduateDate | facultyId |
---|---|---|---|---|
1 | 卢1 | 21 | 2019-11-20 20:29:20 | 1 |
2 | 卢2 | 20 | 2019-11-27 20:29:40 | 2 |
3 | 卢3 | 22 | 2019-11-28 20:29:53 | 3 |
4 | 卢4 | 17 | 2019-11-28 20:30:20 | 2 |
5 | 卢5 | 17 | 2019-11-21 20:29:20 | 1 |
6 | 卢6 | 17 | 2025-12-11 20:29:20 | 3 |
7 | 卢7 | 20 | 2019-11-20 20:29:20 | 2 |
8 | 卢8 | 22 | 2019-11-27 20:29:40 | 3 |
9 | 卢9 | 17 | 2025-12-11 20:29:20 | 2 |
10 | 卢10 | 21 | 2019-11-28 20:30:20 | 1 |
11 | 卢11 | 17 | 2019-11-21 20:29:20 | 1 |
12 | 卢12 | 17 | 2019-11-11 20:29:20 | 3 |
13 | 卢13 | 17 | 2019-11-20 20:29:20 | 2 |
14 | 卢14 | 18 | 2025-12-11 20:29:20 | 3 |
15 | 卢15 | 22 | 2019-11-28 20:29:53 | 3 |
16 | 卢16 | 22 | 2019-11-28 20:30:20 | 1 |
17 | 卢17 | 18 | 2019-11-21 20:29:20 | 1 |
18 | 卢18 | 20 | 2025-12-11 20:29:20 | 2 |
19 | 卢19 | 21 | 2019-11-21 20:29:20 | 3 |
20 | 卢20 | 19 | 2025-12-11 20:29:20 | 3 |
21 | 卢21 | 18 | 2019-11-28 22:16:17 | 1 |
facultylist学院表:
id | facultyName |
---|---|
1 | 计算机与通信工程学院 |
2 | 数学与统计学院 |
3 | 文法学院 |
二、同时满足以下需求:
1.多表联合查询出学院名字
需求展示:学生表联合学院表隐去学院id直接展示学院名给用户:
id | stuName | stuAge | graduateDate | facultyName |
---|---|---|---|---|
1 | 卢1 | 21 | 2019-11-20 20:29:20 | 计算机与通信工程学院 |
2 | 卢2 | 20 | 2019-11-27 20:29:40 | 数学与统计学院 |
3 | 卢3 | 22 | 2019-11-28 20:29:53 | 文法学院 |
4 | 卢4 | 17 | 2019-11-28 20:30:20 | 数学与统计学院 |
5 | 卢5 | 17 | 2019-11-21 20:29:20 | 计算机与通信工程学院 |
… | … | … | … | … |
2.可以带多条件查询
学生名字模糊搜索
年龄范围搜索
搜索是否毕业
指定字段排序
3.指定页码,页数据大小进行物理分页查询
三、解决步骤
今天找了一下午资料,终于可以同时满足以上所有需求了!开干!
Spring Boot配置
重要配置已经做注释!
server.port=9999
#设置jackson的时区和输出形式
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#URL要设置数据库编码、时区、允许多语句查询(等会会讲原因)
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&serverTimezone=GMT%2b8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=6666
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#关闭字段名的映射(关闭如userName映射成user_name)
mybatis-plus.configuration.map-underscore-to-camel-case=false
#配置xml Mapper路径
mybatis-plus.mapper-locations=classpath:mapping/*Mapper.xml
MP配置
创建一个MP的配置类写入如下内容,主要是配置mapper路径
package com.looyeagee.web.util;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@Configuration
@MapperScan("com.looyeagee.web.mapper")
public class MybatisPlusConfig {
}
实体类编写
Student.java
package com.looyeagee.web.bean;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Student implements Serializable {
private Long id;
private String stuName;
private Integer stuAge;
private Date graduateDate;
private Long facultyId;
}
Select.java(把查询条件封装成类)
package com.looyeagee.web.bean;
import lombok.AllArgsConstructor;
import lombok.Data;
import java.io.Serializable;
@Data
public class Select implements Serializable {
String stuName;//模糊搜索学生名
Integer minAge;//最小年龄 用Integer不用int是因为用户可以不选择此条件(null)即没有最小年龄限制 用int默认值是0
Integer maxAge;//最大年龄
Boolean isGraduate;//是否毕业 为null就是不管毕业还是没毕业都要
Integer pageNumber;//第几页 从1开始
Integer pageSize;//每页几个数据
String orderBy;//排序字段
Boolean highToLow;//是否降序 为false和null就是升序 为true就是降序
}
Result.java(把结果也封装)
package com.looyeagee.web.bean;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)//为null的字段 不输出到前端 看以下的stuAge字段
public class Result implements Serializable {
private Long id;
private String stuName;
private Integer stuAge;//为什么要用Integer而不是int 因为int会有默认值0,而Integer默认是null,如果查到年龄为null就会显示为0岁了,这样输出到前端就是0岁,而我们不期望前端展示为null的数据
private Date graduateDate;
private String facultyName;
}
StudentMapper.xml编写
前提知识:
mysql如何通过当前页码和页数据条数分页?
mysql limit m,n是mysql分页用的语句,不过此处的m不是当前页码而是从第几条数据开始,n是取几条数据。所以假设PageNumber为第几页,PageSize为一页数据条数,则写法为limit (PageNumber-1)*PageSize,PageSize
如何用mysql limit分页查询的同时返回符合条件数据总数以确定总页数?
用上面的方法虽然能分页,但是没有查出符合条件总个数,所以就不知道数据总共有多少页数。MP内部分页的实现是先查询符合条件的个数再用limit查询,不过这样会导致两次查询浪费资源,而且要写2个条件一模一样的select查询,很不方便,这里有个解决方案可以一次性返回数据和总条数:通过SQL_CALC_FOUND_ROWS和SELECT FOUND_ROWS();来获取。
为了说的更清楚,我直接贴出测试sql:我的21个数据中名字含有字符"2"
的有4个同学,我想每页展示2条数据,并且访问第1页:根据我贴出的数据,满足条件的有4个,id分别为2,12,20,21。因为1页只展示2个数据,所以第1页应该是返回2,12这两个数据。语句
SELECT SQL_CALC_FOUND_ROWS * FROM `student` WHERE stuName LIKE '%2%' limit 0,2;SELECT FOUND_ROWS();
执行后一次性返回2个结果集(这就是前面要配置一次性可执行多个语句的原因,默认不可以一次性执行多个语句),如图:
第二个结果集就是总条数。下面介绍Mapper的配置。
2个结果集的配置:
<resultMap id="ResultMap" type="com.looyeagee.web.bean.Result"/>
<resultMap id="RecordsCount" type="integer"/>
resultMap标签是mapper的子标签用来指定结果集的id和类型。由于返回的第一个结果集的结果为我们定义的实体类Result,所以类型填写完整实体类路径;由于返回的第二个结果集的结果为一个整数,所以类型是integer。
<select id="findResultByInfo" resultMap="ResultMap,RecordsCount"
parameterType="com.looyeagee.web.bean.Select" resultType="java.util.List">
在select标签中添加resultMap
属性来指定结果集的id,由于这个select会返回2个结果集,所以resultMap属性填写2个刚刚定义的结果集id,用英文逗号隔开。parameterType
属性就是我们封装的查询实体类。返回的结果类型是List。
下面贴出完整多条件查询代码:
注意:
1.大于号小于号要用xml实体字符转义。
2.orderby字段的使用要用${},不让程序自动预编译。
3.排序多加一个通过id升序,因为mysql排序是不稳定的,可能会出现不同页数出现相同数据的情况。
4.此处传进去的pageNumber已经经过了PageNumber=(PageNumber-1)*PageSize
的处理。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.looyeagee.web.mapper.StudentMapper">
<resultMap id="ResultMap" type="com.looyeagee.web.bean.Result"/>
<resultMap id="RecordsCount" type="integer"/>
<select id="findResultByInfo" resultMap="ResultMap,RecordsCount"
parameterType="com.looyeagee.web.bean.Select" resultType="java.util.List">
SELECT SQL_CALC_FOUND_ROWS
`student`.`id` AS `id`,
`student`.`stuName` AS `stuName`,
`student`.`stuAge` AS `stuAge`,
`student`.`graduateDate` AS `graduateDate`,
`facultylist`.`facultyName` AS `facultyName`
FROM
( `facultylist` JOIN `student` )
WHERE
(
`facultylist`.`id` = `student`.`facultyId`)
-- 标题模糊搜索
<if test="stuName != null">
AND `student`.`stuName` LIKE CONCAT('%',#{stuName},'%')
</if>
-- >=是大于等于
<if test="minAge!=null">
AND `student`.`stuAge`>= #{minAge}
</if>
-- <=是小于等于
<if test="maxAge!=null">
AND `student`.`stuAge` <= #{maxAge}
</if>
-- 没毕业 毕业时间大于现在
<if test="isGraduate != null and isGraduate ==false">
AND `student`.`graduateDate`>=NOW()
</if>
-- 毕业了 毕业时间小于现在
<if test="isGraduate != null and isGraduate ==true">
AND `student`.`graduateDate`<=NOW()
</if>
<if test="orderBy!=null and orderBy!=''">
<if test="highToLow ==null or highToLow ==false">
ORDER BY ${orderBy} ASC,`student`.`id` ASC -- 加id ASC是为了保证分页结果的唯一性 mysql排序是不稳定的 https://www.jianshu.com/p/1e8a19738ae4
</if>
<if test="highToLow !=null and highToLow ==true">
ORDER BY ${orderBy} DESC,`student`.`id` ASC
</if>
</if>
-- 分页查询
LIMIT
#{pageNumber},#{pageSize};
-- 接着查询符合条件个数
SELECT FOUND_ROWS();
</select>
</mapper>
StudentMapper类编写
注意返回类型即可。
package com.looyeagee.web.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.looyeagee.web.bean.Select;
import com.looyeagee.web.bean.Student;
import java.util.List;
public interface StudentMapper extends BaseMapper<Student> {
List<List<?>> findResultByInfo(Select select);
}
测试类编写
关于总页数计算的说明:总数据条数除以每页数据条数,如果没有余数,结果就是总页数;如果有余数,则要将计算结果+1(进1法);用一句话就是(totalCount + pageSize - 1) / pageSize
package com.looyeagee.web;
import com.looyeagee.web.bean.Result;
import com.looyeagee.web.bean.Select;
import com.looyeagee.web.mapper.StudentMapper;
import com.looyeagee.web.service.impl.StudentServiceImpl;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
class WebApplicationTests {
@Autowired
StudentMapper studentMapper;
@Test
void selectTest() {
Select selectInfo = new Select();
int nowPageIndex = 1;
int pageSize = 5;
selectInfo.setPageNumber((nowPageIndex - 1) * pageSize);
selectInfo.setPageSize(pageSize);
selectInfo.setOrderBy("stuAge");
selectInfo.setHighToLow(true);
selectInfo.setIsGraduate(true);
selectInfo.setMinAge(17);
selectInfo.setMaxAge(20);
List<List<?>> findtest = studentMapper.findResultByInfo(selectInfo);
List<Result> orderinfos = (List<Result>) findtest.get(0);
int totalCount = (Integer) findtest.get(1).get(0);
System.out.println("当前页面记录数:" + orderinfos.size());
System.out.println("符合条件记录数:" + totalCount);
System.out.println("当前页数:" +nowPageIndex);
System.out.println("总页数:" + ((totalCount + pageSize - 1) / pageSize));
orderinfos.forEach(System.out::println);
}
}
以上的测试是筛选在我们的21个数据中,最小年龄17,最大年龄20,已经毕业(毕业时间小于现在时间),总共结果是有9个同学:通过年龄降序分别为2,7,17,21,4,5,11,12,13号,
选择第1页,1页5个数据,输出结果
当前页面记录数:5
符合条件记录数:9
当前页数:1
总页数:2
Result(id=2, stuName=卢2, stuAge=20, graduateDate=Wed Nov 27 20:29:40 CST 2019, facultyName=数学与统计学院)
Result(id=7, stuName=卢7, stuAge=20, graduateDate=Wed Nov 20 20:29:20 CST 2019, facultyName=数学与统计学院)
Result(id=17, stuName=卢17, stuAge=18, graduateDate=Thu Nov 21 20:29:20 CST 2019, facultyName=计算机与通信工程学院)
Result(id=21, stuName=卢21, stuAge=18, graduateDate=Thu Nov 28 22:16:17 CST 2019, facultyName=计算机与通信工程学院)
Result(id=4, stuName=卢4, stuAge=17, graduateDate=Thu Nov 28 20:30:20 CST 2019, facultyName=数学与统计学院)
将nowPageIndex
改为2,输出第二页结果(剩余4个数据):
当前页面记录数:4
符合条件记录数:9
当前页数:2
总页数:2
Result(id=5, stuName=卢5, stuAge=17, graduateDate=Thu Nov 21 20:29:20 CST 2019, facultyName=计算机与通信工程学院)
Result(id=11, stuName=卢11, stuAge=17, graduateDate=Thu Nov 21 20:29:20 CST 2019, facultyName=计算机与通信工程学院)
Result(id=12, stuName=卢12, stuAge=17, graduateDate=Mon Nov 11 20:29:20 CST 2019, facultyName=文法学院)
Result(id=13, stuName=卢13, stuAge=17, graduateDate=Wed Nov 20 20:29:20 CST 2019, facultyName=数学与统计学院)
Mybatis Plus带多条件的多表联合、分页、排序查询的更多相关文章
- .net通用CMS快速开发框架——问题1:Dapper通用的多表联合分页查询怎么破?
最近在弄一个东东,类似那种CMS的后台管理系统,方便作为其它项目的初始化框架用的. 现在遇到个问题,如标题所示:Dapper通用的多表联合分页查询怎么破? 难道只能通过拼接sql或者使用存储过程吗?我 ...
- SQL多表联合分页.....
set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go /* 支持多表查询分页存储过程(事理改进)2012.3 --多表联查1 declare @Count int ...
- MyBatis 多表联合查询及优化 以及自定义返回结果集
下面就来说一下 mybatis 是通过什么来实现多表联合查询的.首先看一下表关系,如图: 这 里,我已经搭好了开发的环境,用到的是 SpringMVC + Spring + MyBatis,当然,为了 ...
- MyBatis学习总结(三)——多表关联查询与动态SQL
在上一章中我们学习了<MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射>,这一章主要是介绍一对一关联查询.一对多关联查询与动态SQL等内容. 一.多表关联查询 表与 ...
- mybatis实现多表联合查询
本文转自:http://www.cnblogs.com/xdp-gacl/p/4264440.html#!comments 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) ...
- MySQL不带where条件的UPDATE和DELETE 限制操作说明
本文来自 网易云社区 . 数据安全是业务的基石,但是DBA 总会遇到救火情况,业务误删除全表或者误更新错全表业务数据,导致服务不可用 sql_safe_updates参数可以限制不带where条件的u ...
- mybatis:开发环境搭建--增删改查--多表联合查询(多对一)
什么是mybatisMyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或 ...
- MyBatis Plus 实现多表分页模糊查询
项目中使用springboot+mybatis-plus来实现. 但是之前处理的时候都是一个功能,比如分页查询,条件查询,模糊查询. 这次将这个几个功能合起来就有点头疼,写下这边博客来记录自己碰到的问 ...
- MyBatis之三:多表联合查询
在这篇文章里面主要讲解如何在mybatis里面使用一对一.一对多.多表联合查询(类似视图)操作的例子. 注:阅读本文前请先大概看一下之前两篇文章. 一.表结构 班级表class,学生表student, ...
随机推荐
- CSP-S 模拟测试92 题解
话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...
- 「NOI 2018」归程「Kruskal 重构树」
题解 Kruskal重构树:每次一条边连接两个集合,建一个新点,点权为该边边权:把这两个集合的根连向新点. 性质:(如果求的是最大生成树)叶子结点是图中实际结点:叶子到根路径上点权递减:两点间lca的 ...
- 第2组 Alpha冲刺(3/4)
17-材料-黄智(252342126) 22:10:46 队名:十一个憨批 组长博客 作业博客 组长黄智 过去两天完成的任务:写博客,复习C语言 GitHub签入记录 接下来的计划:构思游戏实现 还剩 ...
- 畅通工程续(HDU 1874)(简单最短路)
某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在 ...
- 2019.6.28 校内测试 T3 【音乐会】道路千万条
大眼一看最下面的题意解释的话,发现这和洛谷P1310表达式的值挺像的,大概都是给定一些运算符号,让最后的表达式为true的概率,为false的概率啥的QwQ~: 然后这个题嘛?就是在所有的运算符中提溜 ...
- masm for windows2015 下载安装
下载地址: https://sm.myapp.com/original/Office/wasm2015.rar
- Jenkins系统初始化配置
1.点击系统管理-->全局安全配置 2.设置允许用户注册,点击保存 3.配置全局工具 4.配置maven文件路径,使用文件系统中的settings文件 5.配置jdk 6.配置maven 7.我 ...
- 解决JAVA单步调试键盘输入被JDB占用的问题
解决JAVA单步调试键盘输入被JDB占用的问题 问题来源: 在完成本周任务时,编写的代码中含有Scanner类,编译及运行过程均正确,但使用JDB单步调试时,运行到输入行无法在JDB内部输入变量值. ...
- You can't specify target table 'a' for update in FROM clause
项目中有一个功能变动上线,其中有一张表ttt的字段cc,历史数据需要处理,把字段cc中为'xxx'的值替换为'yyy'. 表A结构如下: CREATE TABLE `ttt` ( `id` bigin ...
- 高性能高可用的微服务框架TarsGo的腾讯实践
conference/2.3 高性能高可用的微服务框架TarsGo的腾讯实践 - 陈明杰.pdf at master · gopherchina/conferencehttps://github.co ...