MybatisPlus自定义SQL使用条件构造器和分页

342 阅读2分钟

1 前言

我们知道MybatisPlus对单表操作很方便,特别是其条件构造器和分页插件,避免我们书写简单重复的SQL,提高我们的效率。其实在自定义SQL中也可以使用MybatisPlus提供的条件构造器和分页插件,下面就来介绍如何自定义SQL中如何使用。

2 环境准备

  • 数据库新建studentteacher两张表

student表结构如下

idnameteacher_id
1小明1
2小红1
3小白2

teacher表结构如下

idname
1老师1
2老师2
  • 项目的创建此处就省略了。导入如下依赖
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- 测试 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
</dependency>

<!-- MybatisPlus依赖 -->
<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>mybatis-plus-boot-starter</artifactId>
   <version>3.5.3.1</version>
</dependency>

<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
</dependency>

<!-- MySQL驱动 -->
<dependency>
   <groupId>com.mysql</groupId>
   <artifactId>mysql-connector-j</artifactId>
   <scope>runtime</scope>
</dependency>
  • yml配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql:///test
    username: root
    password: root
mybatis-plus:
  # 开启MybatisPlus的日志打印
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # 如果mapper文件所在位置为resources/mapper下,此项可不配置
  mapper-locations: classpath:mapper/*.xml
  • 实体类

Student实体类

package com.example.entity;

@Data
@TableName("student")
public class Student {
   //自动递增的主键
   @TableId(value = "id", type = IdType.AUTO)
   private Integer id;
   private String name;
   private Integer teacherId;
}

Teacher实体类

package com.example.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

@Data
@TableName("teacher")
public class Teacher {
   @TableId(value = "id", type = IdType.AUTO)
   private Integer id;
   private String name;
}
  • vo
package com.example.vo;

/**
 * 用于接收查询出的数据
 */
@Data
public class StudentVo {
   private Integer id;
   private String name;
   private Teacher teacher;
}
  • 注意:在启动类上添加MapperScan注解扫描mapper接口所在包

3 实现

我们以查询出学生信息为例,如下图

Snipaste_2023-12-19_09-59-55.png

3.1 使用条件构造器

  • mapper接口如下

注意:Wrapper形参的格式与下面要相同

package com.example.mapper;

@Repository
public interface StudentMapper extends BaseMapper<Student> {
   StudentVo mySelectOne(@Param(Constants.WRAPPER) Wrapper<StudentVo> queryWrapper);
}
  • xml配置文件如下

${ew.customSqlSegment}:就是条件构造器中的条件了,不需要写WHERE

<?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.example.mapper.StudentMapper">
   <resultMap id="studentVoMap" type="com.example.vo.StudentVo">
      <result property="id" column="id" />
      <result property="name" column="name" />
      <association property="teacher" javaType="com.example.entity.Teacher">
         <result property="id" column="tid" />
         <result property="name" column="tname" />
      </association>
   </resultMap>

   <select id="mySelectOne" resultMap="studentVoMap">
      SELECT s.id, s.name, t.id tid, t.name tname
      FROM student s join teacher t on s.teacher_id = t.id
      ${ew.customSqlSegment}
   </select>
</mapper>
  • 测试
@Test
void contextLoads() {
   QueryWrapper<StudentVo> wrapper = Wrappers.<StudentVo>query()
         .eq("s.id", 1);
   StudentVo studentVo = studentMapper.mySelectOne(wrapper);
   System.out.println(studentVo);
}

执行SQL如下

Snipaste_2023-12-19_10-07-06.png

这样我们就能在自定义SQL中使用条件构造器了。

3.2 使用分页

MybatisPlus使用分页需要配置分页插件,配置如下

package com.example.config;

@Configuration
public class MybatisPlusConfig {
   @Bean
   public MybatisPlusInterceptor paginationInterceptor() {
      MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
      interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
      return interceptor;
   }
}
  • mapper接口如下
package com.example.mapper;

@Repository
public interface StudentMapper extends BaseMapper<Student> {
   Page<StudentVo> mySelectPage(Page<StudentVo> iPage, @Param(Constants.WRAPPER) Wrapper<StudentVo> queryWrapper);
}
  • xml文件如下
<?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.example.mapper.StudentMapper">
   <resultMap id="studentVoMap" type="com.example.vo.StudentVo">
      <result property="id" column="id" />
      <result property="name" column="name" />
      <association property="teacher" javaType="com.example.entity.Teacher">
         <result property="id" column="tid" />
         <result property="name" column="tname" />
      </association>
   </resultMap>

   <select id="mySelectPage" resultMap="studentVoMap">
      SELECT s.id, s.name, t.id tid, t.name tname
      FROM student s join teacher t on s.teacher_id = t.id
      ${ew.customSqlSegment}
   </select>
</mapper>
  • 测试
@Test
void contextLoads() {
   QueryWrapper<StudentVo> wrapper = Wrappers.<StudentVo>query()
         .eq("s.id", 1);
   Page<StudentVo> page = studentMapper.mySelectPage(Page.of(1, 10), wrapper);
   System.out.println(page.getRecords());
}

执行的SQL如下

Snipaste_2023-12-19_10-16-46.png 我们发现分页也起效果了。

4 总结

虽然我们能够在自定义SQL中使用MybatisPlus提供的条件构造器共和分页插件,但是还是有局限性的。

  1. 不能使用LambdaWrapper
  2. 自定义SQL使用条件构造器,只会将条件原封不动的加在SQL后。例子如下

我们要查询创建时间create_date等于2023年的

// 我们只能书写为create_date,而不能书写为createDate
QueryWrapper<StudentVo> wrapper = Wrappers.<StudentVo>query()
                                          .eq("s.id", 1)
                                          .eq("create_date", 2023)

5 写在最后

上述观点只是小白在学习过程中对接触的新东西的总结和分享,若存在不足之处,还请大佬指出。