最简单的MyBatis Plus的多表联接、分页查询实现方法

一、前言

最近在加强 ITAEM 团队的一个 app 项目——学生教师学习交流平台
人员组成:安卓 + 前端 + 后台
后台 DAO 层借鉴了华工其他软件开发团队,使用了新颖强大的 MyBatisPlus 框架,里边有一个类似百度贴吧的发帖子的功能:

而如果设计表,应为

帖子表 t_post
- id
- title 标题
- content 内容
- xx
- user_id 用户外键

用户表 t_user
+ id
+ name 帖子发起者名字
+ xx

示例图中红色框中的内容为 t_user 表的字段 name
而要实现上面显示帖子,就要用到关联查询了,而且帖子很多,必须用分页查询,

那么,怎么通过 MyBatisPlus 来实现关联、分页查询呢 ?很简单,往下看。

二、需求、数据库表设计

这是个人 app 项目中 v1.0 版本的部分表。

需求:显示帖子

要帖子基本内容如时间、帖子内容等,即 t_question 表的内容全部要,

同时还要发帖子的人名字,即 t_student 的字段 name

三、代码结构

为了写这篇文章,抽取了该 app 项目中的部分代码,彼此相互关系如下图

四、代码实现

1、代码已经放到 github 上了,若对本文的代码有疑问可以去 github 上查看详情:
https://github.com/larger5/MyBatisPlus_page_tables.git

2、entity、mapper、service、controller 使用了 MyBatisPlus 的代码生成器,自动生成大部分基础的代码,操作方法见之前的文章:
在 SpringBoot 中引入 MyBatisPlus 之 常规操作

1.实体

① Question

// import 省略

@TableName("t_question")
public class Question implements Serializable {

  private static final long serialVersionUID = 1L;

  @ApiModelProperty(value = "问答主键id")
  @TableId(value = "id", type = IdType.AUTO)
  private Integer id;

  @ApiModelProperty(value = "学生外键id")
  @TableField("student_id")
  private Integer studentId;

  @ApiModelProperty(value = "问题内容")
  private String content;

  @ApiModelProperty(value = "问题发布时间,发布的时候后台自动生成")
  private Date date;

  @ApiModelProperty(value = "问题悬赏的积分")
  private Integer value;

	// getter、setter 省略
}

② Student

// import 省略

@TableName("t_student")
public class Student implements Serializable {

  private static final long serialVersionUID = 1L;

  @ApiModelProperty(value = "学生主键id")
  @TableId(value = "id", type = IdType.AUTO)
  private Integer id;

  @ApiModelProperty(value = "学生名称")
  private String name;

  @ApiModelProperty(value = "学生密码")
  private String password;

  @ApiModelProperty(value = "学生积分数")
  private Integer points;

  @ApiModelProperty(value = "学生邮件地址")
  private String email;

  @ApiModelProperty(value = "学生手机号码")
  private String phone;

  @ApiModelProperty(value = "学生学号")
  private String num;

  @ApiModelProperty(value = "学生真实姓名")
  @TableField("true_name")
  private String trueName;

	// getter、setter 省略
}

2.mapper

① StudentMapper

// import 省略
public interface StudentMapper extends BaseMapper<Student> {
}

② QuestionMapper

// import 省略
public interface QuestionMapper extends BaseMapper<Question> {
  /**
   *
   * @param page 翻页对象,可以作为 xml 参数直接使用,传递参数 Page 即自动分页
   * @return
   */
  @Select("SELECT t_question.*,t_student.`name` FROM t_question,t_student WHERE t_question.student_id=t_student.id")
  List<QuestionStudentVO> getQuestionStudent(Pagination page);

}

3、service

① StudentService

// import 省略
public interface StudentService extends IService<Student> {
}

② QuestionService

// import 省略
public interface QuestionService extends IService<Question> {

  Page<QuestionStudentVO> getQuestionStudent(Page<QuestionStudentVO> page);

}

4、serviceImpl

① StudentServiceImpl

// import 省略
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

}

② QuestionServiceImpl

// 省略 import

@Service
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements QuestionService {

  @Override
  public Page<QuestionStudentVO> getQuestionStudent(Page<QuestionStudentVO> page) {
    return page.setRecords(this.baseMapper.getQuestionStudent(page));
  }

}

5、controller

// 省略 import

@RestController
@RequestMapping("/common")
@EnableSwagger2
public class CommonController {

  @Autowired
  QuestionService questionService;

  @Autowired
  StudentService studentService;

  @GetMapping("/getAllQuestionByPage/{page}/{size}")
  public Map<String, Object> getAllQuestionByPage(@PathVariable Integer page, @PathVariable Integer size) {
    Map<String, Object> map = new HashMap<>();
    Page<Question> questionPage = questionService.selectPage(new Page<>(page, size));
    if (questionPage.getRecords().size() == 0) {
      map.put("code", 400);
    } else {
      map.put("code", 200);
      map.put("data", questionPage);
    }
    return map;
  }

  @GetMapping("/getAllQuestionWithStudentByPage/{page}/{size}")
  public Map<String, Object> getAllQuestionWithStudentByPage(@PathVariable Integer page, @PathVariable Integer size) {
    Map<String, Object> map = new HashMap<>();
    Page<QuestionStudentVO> questionStudent = questionService.getQuestionStudent(new Page<>(page, size));
    if (questionStudent.getRecords().size() == 0) {
      map.put("code", 400);
    } else {
      map.put("code", 200);
      map.put("data", questionStudent);
    }
    return map;
  }

}

6、MyBatisPlus 配置

// 省略 import

@EnableTransactionManagement
@Configuration
@MapperScan("com.cun.app.mapper")
public class MybatisPlusConfig {

  /**
   * 分页插件
   */
  @Bean
  public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
  }

  /**
   * 打印 sql
   */
  @Bean
  public PerformanceInterceptor performanceInterceptor() {
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    //格式化sql语句
    Properties properties = new Properties();
    properties.setProperty("format", "true");
    performanceInterceptor.setProperties(properties);
    return performanceInterceptor;
  }
}

7、关联查询 VO 对象

// import 省略

public class QuestionStudentVO implements Serializable {

  @ApiModelProperty(value = "问答主键id")
  @TableId(value = "id", type = IdType.AUTO)
  private Integer id;

  @ApiModelProperty(value = "学生外键id")
  @TableField("student_id")
  private Integer studentId;

  private String name;

  @ApiModelProperty(value = "问题内容")
  private String content;

  @ApiModelProperty(value = "问题发布时间,发布的时候后台自动生成")
  private Date date;

  @ApiModelProperty(value = "问题悬赏的积分")
  private Integer value;

	// getter、setter 省略

五、测试接口

1、没有关联的分页查询接口

http://localhost/common/getAllQuestionByPage/1/2

① json 输出

{
 "code": 200,
 "data": {
  "total": 10,
  "size": 2,
  "current": 1,
  "records": [
   {
    "id": 1,
    "studentId": 3,
    "content": "唐代,渝州城里,有一个性格开朗、乐观的小伙子,名叫景天。",
    "date": 1534497561000,
    "value": 5
   },
   {
    "id": 2,
    "studentId": 1,
    "content": "雪见从小父母双亡,由爷爷唐坤抚养成人。",
    "date": 1533201716000,
    "value": 20
   }
  ],
  "pages": 5
 }
}

② sql 执行

2、多表关联、分页查询接口

http://localhost/common/getAllQuestionWithStudentByPage/1/2

① json 输出

{
 "code": 200,
 "data": {
  "total": 10,
  "size": 2,
  "current": 1,
  "records": [
   {
    "id": 1,
    "studentId": 3,
    "name": "vv",
    "content": "唐代,渝州城里,有一个性格开朗、乐观的小伙子,名叫景天。",
    "date": 1534497561000,
    "value": 5
   },
   {
    "id": 2,
    "studentId": 1,
    "name": "cun",
    "content": "雪见从小父母双亡,由爷爷唐坤抚养成人。",
    "date": 1533201716000,
    "value": 20
   }
  ],
  "pages": 5
 }
}

② sql 执行

六、小结

写本文的原因:

①网上有做法不合时宜的文章(自定义page类、配置版)②官方文档使用的是配置版的,笔者采用注解版的

MyBatis 配置版 MyBatis 注解版
① 动态 sql 灵活、② xml 格式的 sql,可拓展性好 ① 少一个设置,少一个错误爆发点、② 代码清晰优雅

当然,智者见智仁者见仁

参考资料:
MyBatisPlus 官方文档:分页插件:方式一 、传参区分模式【推荐】

到此这篇关于最简单的MyBatis Plus的多表联接、分页查询实现方法的文章就介绍到这了,更多相关MyBatis Plus多表联接、分页查询内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 结合mybatis-plus实现简单不需要写sql的多表查询

    项目地址: GITHUB (本地下载) java mybatis 多表查询 简介 实现简单的实体类操作多表,  首先你的项目是使用了mybatis-plus 才可以使用 设计说明 如何关联表? 找第一张表注解为 TableId (mybatis-plus 注解)的属性名, 到每二张表找同样的属性名, 如果没找到,反过来找,如果还没找到,挨个属性找.以此类推,实现关联的前提条件是 主从表的关联例名必须一样 // user 表 @TableId private Integer userId // a

  • mybatis Plus 多表联合查询的实现示例

    本文主要介绍了mybatis Plus 多表联合查询,分享给大家,具体如下: //实体类package com.sk.skkill.entity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import java.io.Serializable; import java.util.D

  • springboot + mybatis-plus实现多表联合查询功能(注解方式)

    第一步:加入mybatis-plus依赖 第二步:配置数据源 spring: thymeleaf: cache: false encoding: utf-8 prefix: classpath:/templates/ suffix: .html enabled: true datasource: url: jdbc:mysql://192.168.1.152:3306/timo?useUnicode=true&characterEncoding=UTF-8&useSSL=false&

  • MyBatis-Plus多表联合查询并且分页(3表联合)

    这3张表的关系是模型表Model  ===> 训练表Training ===>应用表Application(大概的逻辑是:选择应用,然后训练,然后成为模型) 首先我们先建立实体Model(我使用的data注解不需要get set  @TableField(exist = false) 注解下的属性 是相关联表的属性) package cn.com.befery.dataai.po; import java.util.Date; import org.springframework.boot.j

  • MybatisPlus自定义Sql实现多表查询的示例

    前言 前段时间看同事的代码,发现他用Layui+MybatisPlus做分页查询做得很规整,认真看了下代码发现这种方式不仅适用于与Layui做分页查询,在任何时候需要多表联查的时候都可以用到.  以下以Layui分页查询作为参考,在实际应用中可以灵活使用. 分页查询VO对象 @Data @AllArgsConstructor @NoArgsConstructor public class LayuiData { private Integer code=0; private Long count

  • MyBatis Plus 实现多表分页查询功能的示例代码

    在Mybatis Plus 中,虽然IService 接口帮我们定义了很多常用的方法,但这些都是 T 对象有用,如果涉及到 多表的查询,还是需要自定义Vo 对象和自己编写sql 语句,Mybatis Plus提供了一个Page 对象,查询是需要设置其中的 size 字段 和 current 字段的值 一.分页配置 可以直接使用selectPage这样的分页,但返回的数据确实是分页后的数据,但在控制台打印的SQL语句其实并没有真正的物理分页,而是通过缓存来获得全部数据中再进行的分页,这样对于大数据

  • Mybatis-Plus 多表联查分页的实现代码

    上一节,简单讲述了 Mybatis-Plus 搭建与使用入门,这一节,简单讲一下如何使用 MP 实现多表分页. 分析 使用的工程,依旧是 spring-boot,关于分页,官网给出了一个单表的demo,其实多表分页实现原理相同,都是通过 mybatis 的拦截器 (拦截器做了什么?他会在你的 sql 执行之前,为你做一些事情,例如分页,我们使用了 MP 不用关心 limit,拦截器为我们拼接.我们也不用关心总条数,拦截器获取到我们 sql 后,拼接 select count(*) 为我们查询总条

  • 最简单的MyBatis Plus的多表联接、分页查询实现方法

    一.前言 最近在加强 ITAEM 团队的一个 app 项目--学生教师学习交流平台 人员组成:安卓 + 前端 + 后台 后台 DAO 层借鉴了华工其他软件开发团队,使用了新颖强大的 MyBatisPlus 框架,里边有一个类似百度贴吧的发帖子的功能: 而如果设计表,应为 帖子表 t_post - id - title 标题 - content 内容 - xx - user_id 用户外键 用户表 t_user + id + name 帖子发起者名字 + xx 示例图中红色框中的内容为 t_use

  • Mybatis实现增删改查及分页查询的方法

    MyBatis的前身就是iBatis.是一个数据持久层(ORM)框架. MyBatis是支持普通SQL查询,存储过程和高级映射的优秀持 久层框架.MyBatis消除了几乎所有的JDBC 代码和参数的手工 设置以及结果集的检索.MyBatis使用简单的XML或注解用于 配置和原始映射,将接口和Java 的POJOs(Plan Old Java Objects,普通的Java 对象)映射成数据库中的记录.每个 MyBatis应用程序主要都是使用SqlSessionFactory实例的,一个 SqlS

  • 基于Java 利用Mybatis实现oracle批量插入及分页查询

    目录 1.单条数据insert 2.批量数据批量insert 3.创建序列 4.oracle分页查询 前端与后端交互,分页查询 后端海量数据导出,批量查询 1.单条数据insert <!--简单SQL--> insert into userinfo (USERID, USERNAME, AGE) values(1001,'小明',20); <!--Mybatis写法1,有序列,主键是自增ID,主键是序列--> <insert id="insert" par

  • cakephp2.X多表联合查询join及使用分页查询的方法

    本文实例讲述了cakephp2.X多表联合查询join及使用分页查询的方法.分享给大家供大家参考,具体如下: 格式化参数: public function getconditions($data){ $this->loadModel("Cm.LoginHistory"); $conditions = array(); foreach ($data as $key=>$val){ if($key=='start_date'){ $conditions['LoginHistor

  • Tk.mybatis零sql语句实现动态sql查询的方法(4种)

    目录 实现方式: 方式一:使用Example实现 方式二:使用example.createCriteria实现 方式三:使用Example.builder实现 方式四:使用weekendSqls实现 有时候,查询数据需要根据条件使用动态查询,这时候需要使用动态sql,通常我们会自己写动态sql来实现,比如: <select id="findStudentByCondition" resultType="com.example.service.entity.Student

  • 利用MyBatis进行不同条件的like模糊查询的方法

    之前一直是用MyBatis进行SQL查询时,一般都是用Generator逆向生产的代码来进行查询. 现在遇到了一个业务问题,我们需要进行对不同的条件分别进行模糊查询,首先我想到的就是根据对需要进行模糊查询的字段进行判断,然后调用Example的方式进行查询条件的注入. 对于String类型的数据可以有Like查询这个方法,但是Integer或者Long这种数据类型的话就没有了,得需要自己动手写. 但是呢,我利用Generator生成的代码Example方式进行模糊查询时确无法实现,原因不太清楚,

  • JavaWeb入门教程之分页查询功能的简单实现

    一.MySql实现分页查询的SQL语句 1.分页需求: 客户端通过传递pageNo(页码),counter(每页显示的条数)两个参数去分页查询数据库表中的数据,那我们知道MySql数据库提供了分页的函数limit m,n,但是该函数的用法和我们的需求不一样,所以就需要我们根据实际情况去改写适合我们自己的分页语句,具体的分析如下: 比如: 查询第1条到第10条的数据的sql是:select * from table limit 0,10;   ->对应我们的需求就是查询第一页的数据:select

  • 史上最简单的MyBatis动态SQL入门示例代码

    假如有如下的关于书籍基本信息的表: DROP DATABASE IF EXISTS `books`; CREATE DATABASE `books`; USE books; DROP TABLE IF EXISTS `book`; CREATE TABLE `book` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(128) DEFAULT NULL, `author` varchar(64) DEFAULT NULL, `pres

  • 简单了解Mybatis如何实现SQL防注入

    这篇文章主要介绍了简单了解Mybatis如何实现SQL防注入,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Mybatis这个框架在日常开发中用的很多,比如面试中经常有一个问题:$和#的区别,它们的区别是使用#可以防止SQL注入,今天就来看一下它是如何实现SQL注入的. 什么是SQL注入 在讨论怎么实现之前,首先了解一下什么是SQL注入,我们有一个简单的查询操作:根据id查询一个用户信息.它的sql语句应该是这样:select * from u

随机推荐