mybatis-plus学习

概述

MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。

快速入门

构建springboot项目

1.引入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>org.springframework.boot</groupId>
  8. <artifactId>spring-boot-starter-test</artifactId>
  9. <scope>test</scope>
  10. </dependency>
  11. <dependency>
  12. <groupId>com.baomidou</groupId>
  13. <artifactId>mybatis-plus-boot-starter</artifactId>
  14. <version>3.5.0</version>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-starter-web</artifactId>
  19. </dependency>
  20. <dependency>
  21. <groupId>mysql</groupId>
  22. <artifactId>mysql-connector-java</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.projectlombok</groupId>
  26. <artifactId>lombok</artifactId>
  27. <optional>true</optional>
  28. </dependency>
  29. </dependencies>
  30. <build>
  31. <plugins>
  32. <plugin>
  33. <groupId>org.springframework.boot</groupId>
  34. <artifactId>spring-boot-maven-plugin</artifactId>
  35. </plugin>
  36. <!--添加配置跳过测试-->
  37. <plugin>
  38. <groupId>org.apache.maven.plugins</groupId>
  39. <artifactId>maven-surefire-plugin</artifactId>
  40. <version>2.22.1</version>
  41. <configuration>
  42. <skipTests>true</skipTests>
  43. </configuration>
  44. </plugin>
  45. <!--添加配置跳过测试-->
  46. </plugins>
  47. </build>

2.配置application.yaml

  1. server:
  2. port: 8080
  3. spring:
  4. datasource:
  5. url: jdbc:mysql://localhost:3306/mybatisplus?characterEncoding=utf-8&serverTimezone=UTC
  6. username: root
  7. password: 5247
  8. driver-class-name: com.mysql.cj.jdbc.Driver

3.创建mybatisplus数据库

  1. /*
  2. Navicat Premium Data Transfer
  3. Source Server : jf
  4. Source Server Type : MySQL
  5. Source Server Version : 80013
  6. Source Host : localhost:3306
  7. Source Schema : mybatisplus
  8. Target Server Type : MySQL
  9. Target Server Version : 80013
  10. File Encoding : 65001
  11. Date: 21/06/2022 19:59:27
  12. */
  13. SET NAMES utf8mb4;
  14. SET FOREIGN_KEY_CHECKS = 0;
  15. -- ----------------------------
  16. -- Table structure for student
  17. -- ----------------------------
  18. DROP TABLE IF EXISTS `student`;
  19. CREATE TABLE `student` (
  20. `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '学生id主键',
  21. `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '学生姓名',
  22. `age` int(10) NULL DEFAULT NULL COMMENT '姓名',
  23. `sex` int(2) NULL DEFAULT NULL COMMENT '性别,1为男,2为女',
  24. `address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '住址',
  25. `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
  26. PRIMARY KEY (`id`) USING BTREE
  27. ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
  28. SET FOREIGN_KEY_CHECKS = 1;

4.创建Student对象

  1. package gdut.domain;
  2. import lombok.AllArgsConstructor;
  3. import lombok.Data;
  4. import lombok.NoArgsConstructor;
  5. import java.util.Date;
  6. @Data
  7. @NoArgsConstructor
  8. @AllArgsConstructor
  9. public class Student {
  10. private Long id;
  11. private String name;
  12. private Integer age;
  13. private boolean sex;
  14. private String address;
  15. private Date createTime;
  16. }

5.创建SutdentMapper

  1. package gdut.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import gdut.domain.Student;
  4. public interface StudentMapper extends BaseMapper<Student> {
  5. }

6.创建MyApplication启动类

  1. package gdut.edu;
  2. import org.mybatis.spring.annotation.MapperScan;
  3. import org.springframework.boot.SpringApplication;
  4. import org.springframework.boot.autoconfigure.SpringBootApplication;
  5. @SpringBootApplication
  6. @MapperScan("gdut.mapper")
  7. public class MyApplication {
  8. public static void main(String[] args) {
  9. SpringApplication.run(MyApplication.class,args);
  10. }
  11. }

7.测试(先向数据库插入几条数据)

  1. package gdut.edu;
  2. import gdut.domain.Student;
  3. import gdut.mapper.StudentMapper;
  4. import org.junit.jupiter.api.Test;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. import java.util.List;
  8. @SpringBootTest
  9. public class Test01 {
  10. @Autowired
  11. private StudentMapper studentMapper;
  12. @Test
  13. public void test01() {
  14. List<Student> students = studentMapper.selectList(null);
  15. System.out.println(students);
  16. }
  17. }

常用设置

设置表映射规则

默认情况下,MP操作的表名就是实体类的类名,如果实体类类名和数据库对应的表名不一致,需要我们自行设置映射规则

单独设置

在实体类类名上加@TableName注解标识,如果表名时tb_student,而实体类类名是Student,使用如下写法

  1. package gdut.domain;
  2. import com.baomidou.mybatisplus.annotation.TableName;
  3. import lombok.AllArgsConstructor;
  4. import lombok.Data;
  5. import lombok.NoArgsConstructor;
  6. import java.util.Date;
  7. @Data
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. @TableName("tb_student")
  11. public class Student {
  12. private Long id;
  13. private String name;
  14. private Integer age;
  15. private boolean sex;
  16. private String address;
  17. private Date createTime;
  18. }

全局设置表名前缀

如果我们很多表名和实体类类名不对应,但是表名都只是在类名的基础上在其前面加了个前缀,比如tb_,实体类为User,表名为tb_user,这样的情况下我们可以全局设置表名前缀

  1. mybatis-plus:
  2. global-config:
  3. db-config:
  4. # 表名前缀
  5. table-prefix: tb_

主键生成策略

单独设置

使用MP插入数据时,如果在我们没有设置主键生成策略的情况下默认的策略是基于雪花算法的自增id。如果我们需要使用别的策略可以在定义实体类时,在代表主键的字段上加上@TableId注解,使用其type属性指定主键生成策略。

  1. package gdut.domain;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableId;
  4. import com.baomidou.mybatisplus.annotation.TableName;
  5. import lombok.AllArgsConstructor;
  6. import lombok.Data;
  7. import lombok.NoArgsConstructor;
  8. import java.util.Date;
  9. @Data
  10. @NoArgsConstructor
  11. @AllArgsConstructor
  12. //@TableName("tb_student")
  13. public class Student {
  14. @TableId(type = IdType.AUTO)
  15. private Long id;
  16. private String name;
  17. private Integer age;
  18. private boolean sex;
  19. private String address;
  20. private Date createTime;
  21. }

全局设置

  1. mybatis-plus:
  2. global-config:
  3. db-config:
  4. # id生成策略,auto为数据库自增
  5. id-type: auto

IdType

描述
AUTO 数据库 ID 自增
NONE 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUT insert 前自行 set 主键值
ASSIGN_ID 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator
的方法nextId
(默认实现类为DefaultIdentifierGenerator
雪花算法)
ASSIGN_UUID 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator
的方法nextUUID
(默认 default 方法)
ID_WORKER 分布式全局唯一 ID 长整型类型(please use ASSIGN_ID
)
UUID 32 位 UUID 字符串(please use ASSIGN_UUID
)
ID_WORKER_STR 分布式全局唯一 ID 字符串类型(please use ASSIGN_ID
)

驼峰命名

是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名 A_COLUMN(下划线命名) 到经典 Java 属性名 aColumn(驼峰命名) 的类似映射。

  1. mybatis-plus:
  2. configuration:
  3. # 默认值为true
  4. map-underscore-to-camel-case: true
  5. global-config:
  6. db-config:
  7. # 表名前缀
  8. table-prefix: tb_
  9. # id-type: auto

@TableField

  • 描述:字段注解(非主键)
  1. package gdut.domain;
  2. import com.baomidou.mybatisplus.annotation.IdType;
  3. import com.baomidou.mybatisplus.annotation.TableField;
  4. import com.baomidou.mybatisplus.annotation.TableId;
  5. import com.baomidou.mybatisplus.annotation.TableName;
  6. import lombok.AllArgsConstructor;
  7. import lombok.Data;
  8. import lombok.NoArgsConstructor;
  9. import java.util.Date;
  10. @Data
  11. @NoArgsConstructor
  12. @AllArgsConstructor
  13. //@TableName("tb_student")
  14. public class Student {
  15. @TableId(type = IdType.AUTO)
  16. private Long id;
  17. @TableField("nickname")
  18. private String name;
  19. private Integer age;
  20. private boolean sex;
  21. private String address;
  22. private Date createTime;
  23. }

启动mybatis本身的log日志

  1. mybatis-plus:
  2. configuration:
  3. # 默认值为true
  4. map-underscore-to-camel-case: true
  5. # 启动mybatis本身的log日志
  6. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  7. global-config:
  8. db-config:
  9. # 表名前缀
  10. table-prefix: tb_
  11. # id-type: auto

自动填充功能

原理:

  • 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
  • 注解填充字段 @TableField(.. fill = FieldFill.INSERT) 生成器策略部分也可以配置!
  1. public class User {
  2. // 注意!这里需要标记为填充字段
  3. @TableField(.. fill = FieldFill.INSERT)
  4. private String fillField;
  5. ....
  6. }
  • 自定义实现类 MyMetaObjectHandler
  1. @Slf4j
  2. @Component
  3. public class MyMetaObjectHandler implements MetaObjectHandler {
  4. @Override
  5. public void insertFill(MetaObject metaObject) {
  6. log.info("start insert fill ....");
  7. this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
  8. // 或者
  9. this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
  10. // 或者
  11. this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
  12. }
  13. @Override
  14. public void updateFill(MetaObject metaObject) {
  15. log.info("start update fill ....");
  16. this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
  17. // 或者
  18. this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
  19. // 或者
  20. this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
  21. }
  22. }

分页

有bug

基本操作

插入数据

  • 使用insert方法来进行数据插入
  1. @Test
  2. public void insertTest(){
  3. Student student = new Student();
  4. student.setName("张三");
  5. student.setAge(22);
  6. int res = studentMapper.insert(student);
  7. System.out.println(res);
  8. }

删除数据

  • deleteById
  1. @Test
  2. public void deleteByIdTest(){
  3. int res = studentMapper.deleteById(17);
  4. System.out.println(res);
  5. }
  • deleteBatchIds
  1. @Test
  2. public void deleteBacthIdsTest(){
  3. ArrayList<Integer> idList = new ArrayList<>();
  4. idList.add(15);
  5. idList.add(16);
  6. idList.add(14);
  7. int res = studentMapper.deleteBatchIds(idList);
  8. System.out.println(res);
  9. }
  • deleteByMap
  1. @Test
  2. public void deleteByMapTest(){
  3. HashMap<String, Object> map = new HashMap<>();
  4. map.put("name","张三");
  5. map.put("age",22);
  6. int res = studentMapper.deleteByMap(map);
  7. System.out.println(res);
  8. }

更新操作

  • update
  1. @Test
  2. public void updateTest(){
  3. Student student = new Student();
  4. student.setId(19L);
  5. student.setAge(33);
  6. int res = studentMapper.updateById(student);
  7. System.out.println(res);
  8. }

条件构造器wrapper

AbstractWrapper

说明:

QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

常用AbstractWrapper方法

  • eq 等于=
  • ne 不等于<>
  • gt 大于>
  • ge 大于等于>=
  • lt 小于<
  • le 小于等于<=
  • between between 值1 and 值2
  • notBetween not between 值2 and 值2
  • like like”%值%”
  • notLike not like “%值%”
  • likeLeft like”%值”likeRight like”值%”
  • likeRight like”值%”
  • isNull 字段 is null
  • isNotNull 字段 is not null
  • in 字段 in (value1,value2…)
  • notIN 字段 not in (value1,value2…)
  • groupBy 分组group by 字段

等等…具体查阅官网

示例
  1. @Test
  2. public void queryWrapperTest01(){
  3. QueryWrapper<Student> wrapper = new QueryWrapper<>();
  4. wrapper.eq("name","张三");
  5. wrapper.gt("age",20);
  6. List<Student> students = studentMapper.selectList(wrapper);
  7. System.out.println(students);
  8. }
  9. @Test
  10. public void queryWrapperTest02(){
  11. QueryWrapper<Student> wrapper = new QueryWrapper<>();
  12. wrapper.like("name","三");
  13. wrapper.between("age",10,33);
  14. List<Student> students = studentMapper.selectList(wrapper);
  15. System.out.println(students);
  16. }
  17. @Test
  18. public void queryWrapperTest03(){
  19. QueryWrapper<Student> wrapper = new QueryWrapper<>();
  20. wrapper.eq("sex",true);
  21. wrapper.gt("id",10);
  22. wrapper.orderByDesc("age");
  23. List<Student> students = studentMapper.selectList(wrapper);
  24. System.out.println(students);
  25. }

常用queryWrapper方法

示例
  1. @Test
  2. public void selectQueryWrapperTest01(){
  3. QueryWrapper<Student> wrapper = new QueryWrapper<>();
  4. wrapper.select("id","name","age");
  5. List<Student> students = studentMapper.selectList(wrapper);
  6. System.out.println(students);
  7. }
  8. @Test
  9. public void selectQueryWrapperTest02(){
  10. QueryWrapper<Student> wrapper = new QueryWrapper<>();
  11. wrapper.select(Student.class, new Predicate<TableFieldInfo>() {
  12. @Override
  13. public boolean test(TableFieldInfo tableFieldInfo) {
  14. return "name".equals(tableFieldInfo.getColumn());
  15. }
  16. });
  17. List<Student> students = studentMapper.selectList(wrapper);
  18. System.out.println(students);
  19. }

常用updateWrapper方法

示例
  1. @Test
  2. public void updateWrapperTest01(){
  3. UpdateWrapper<Student> updateWrapper = new UpdateWrapper<>();
  4. updateWrapper.gt("id",11);
  5. updateWrapper.set("age",99);
  6. int res = studentMapper.update(null, updateWrapper);
  7. System.out.println(res);
  8. }
  9. @Test
  10. public void updateWrapperTest02(){
  11. UpdateWrapper<Student> updateWrapper = new UpdateWrapper<>();
  12. updateWrapper.gt("id",11);
  13. updateWrapper.set("age",88);
  14. int res = studentMapper.update(new Student(), updateWrapper);
  15. System.out.println(res);
  16. }

LamdaQueryWrapper用法

示例
  1. @Test
  2. public void lamdaQueryWrapperTest01() {
  3. LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
  4. queryWrapper.eq(Student::getName, "张三");
  5. queryWrapper.gt(Student::getAge, 22);
  6. List<Student> students = studentMapper.selectList(queryWrapper);
  7. System.out.println(students);
  8. }

Service层接口

  • 接口
  1. package gdut.service;
  2. import com.baomidou.mybatisplus.extension.service.IService;
  3. import gdut.domain.Student;
  4. public interface StudentService extends IService<Student> {
  5. }
  • 实现类
  1. package gdut.service.impl;
  2. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  3. import gdut.domain.Student;
  4. import gdut.mapper.StudentMapper;
  5. import gdut.service.StudentService;
  6. import org.springframework.stereotype.Service;
  7. @Service
  8. public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
  9. }
  • 测试
  1. @Autowired
  2. private StudentService studentService;
  3. @Test
  4. public void testService(){
  5. System.out.println(studentService);
  6. LambdaQueryWrapper<Student> queryWrapper = new LambdaQueryWrapper<>();
  7. queryWrapper.eq(Student::getAge,88);
  8. queryWrapper.gt(Student::getId,12);
  9. List<Student> studentList = studentService.list(queryWrapper);
  10. Iterator<Student> iterator = studentList.iterator();
  11. while (iterator.hasNext()) {
  12. System.out.println(iterator.next());
  13. }
  14. }