声明:本文系原创,转载请注明出处。

注意:本程序使用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>
-- &gt;=是大于等于
<if test="minAge!=null">
AND `student`.`stuAge`&gt;= #{minAge}
</if>
-- &lt;=是小于等于
<if test="maxAge!=null">
AND `student`.`stuAge` &lt;= #{maxAge}
</if> -- 没毕业 毕业时间大于现在
<if test="isGraduate != null and isGraduate ==false">
AND `student`.`graduateDate`&gt;=NOW()
</if> -- 毕业了 毕业时间小于现在
<if test="isGraduate != null and isGraduate ==true">
AND `student`.`graduateDate`&lt;=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带多条件的多表联合、分页、排序查询的更多相关文章

  1. .net通用CMS快速开发框架——问题1:Dapper通用的多表联合分页查询怎么破?

    最近在弄一个东东,类似那种CMS的后台管理系统,方便作为其它项目的初始化框架用的. 现在遇到个问题,如标题所示:Dapper通用的多表联合分页查询怎么破? 难道只能通过拼接sql或者使用存储过程吗?我 ...

  2. SQL多表联合分页.....

    set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go /* 支持多表查询分页存储过程(事理改进)2012.3 --多表联查1 declare @Count int ...

  3. MyBatis 多表联合查询及优化 以及自定义返回结果集

    下面就来说一下 mybatis 是通过什么来实现多表联合查询的.首先看一下表关系,如图: 这 里,我已经搭好了开发的环境,用到的是 SpringMVC + Spring + MyBatis,当然,为了 ...

  4. MyBatis学习总结(三)——多表关联查询与动态SQL

    在上一章中我们学习了<MyBatis学习总结(二)——MyBatis核心配置文件与输入输出映射>,这一章主要是介绍一对一关联查询.一对多关联查询与动态SQL等内容. 一.多表关联查询 表与 ...

  5. mybatis实现多表联合查询

    本文转自:http://www.cnblogs.com/xdp-gacl/p/4264440.html#!comments 一.一对一关联 1.1.提出需求 根据班级id查询班级信息(带老师的信息) ...

  6. MySQL不带where条件的UPDATE和DELETE 限制操作说明

    本文来自 网易云社区 . 数据安全是业务的基石,但是DBA 总会遇到救火情况,业务误删除全表或者误更新错全表业务数据,导致服务不可用 sql_safe_updates参数可以限制不带where条件的u ...

  7. mybatis:开发环境搭建--增删改查--多表联合查询(多对一)

    什么是mybatisMyBatis是支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索.MyBatis使用简单的XML或 ...

  8. MyBatis Plus 实现多表分页模糊查询

    项目中使用springboot+mybatis-plus来实现. 但是之前处理的时候都是一个功能,比如分页查询,条件查询,模糊查询. 这次将这个几个功能合起来就有点头疼,写下这边博客来记录自己碰到的问 ...

  9. MyBatis之三:多表联合查询

    在这篇文章里面主要讲解如何在mybatis里面使用一对一.一对多.多表联合查询(类似视图)操作的例子. 注:阅读本文前请先大概看一下之前两篇文章. 一.表结构 班级表class,学生表student, ...

随机推荐

  1. Til the Cows Come Home ( POJ 2387) (简单最短路 Dijkstra)

    problem Bessie is out in the field and wants to get back to the barn to get as much sleep as possibl ...

  2. Js中Array常用方法小结

    说起Array的方法,不免让人皱一下眉头,下面我们从增删改查角度依次来总结. 1.增 push: 将传入的参数 ,插入数组的尾部,并返回新数组的长度.不管传入参数为一个值还是一个数组,都作为插入数组的 ...

  3. Ubuntu: Linux下查看本机显示器分辨率(xrandr)

    版权声明:转载请注明出处 https://blog.csdn.net/JNingWei/article/details/75044598   Linux下查看本机显示器分辨率: $ xrandr Sc ...

  4. vagrant系列三:vagrant搭建的php7环境

    原文:https://blog.csdn.net/hel12he/article/details/51107236 前面已经把vagrant的基础知识已经基本过了一遍 了,相信只要按着教程来,你已经搭 ...

  5. bootstrap 上下页滚动

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...

  6. Centos D-Bus connection: Operation not permitted

    解决办法: 首先要先在后台启动一个 CentOS7 容器(注意不要少参数): docker run -d -e "container=docker" --privileged=tr ...

  7. 一步一步搭建Nuget私服

    大致流程:1. 通过VS创建一个Web空项目,然后通过Nuget引入Nuget.Server(目前最新版3.2.1).2. 直接将这个Web项目发布到IIS.3. 通过nuget.exe打包*.nup ...

  8. 无法登录到Windows云服务器怎么办?

    当您的云服务器无法远程登录时,我们首先建议您使用VNC方式登录. 是否可以通过控制台远程登录 远程登录失败时,请首先尝试能否通过管理控制台,使用VNC方式登录弹性云服务器. 登录管理控制台. 选择“计 ...

  9. Python常用模块安装

    1. python操作MySQL数据库的依赖包MySQLdb ImportError: No module named MySQLdb 安装方式: yum install MySQL-python 2 ...

  10. 不要在viewWillDisappear:方法中移除通知

    都知道viewWillAppear:方法是在控制器的view将要显示的时候调用的,而viewWillDisappear:方法是在控制器的view将要隐藏的时候调用. 这看上去没什么问题,键盘的显示和隐 ...