mybatisplus

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

支持数据库

任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

  • MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,OceanBase,Firebird,Cubrid,Goldilocks,csiidb
  • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库

框架结构

MyBatis-Plus框架笔记 - 图1

创建spring boot工程

使用spring initalize 快速初始化一个spring boot工程

pom.xml配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.6.4</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>indi.yuluo</groupId>
  12. <artifactId>mybatisplus</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>mybatisplus</name>
  15. <description>mybatisplus</description>
  16. <!--jdk版本-->
  17. <properties>
  18. <java.version>1.8</java.version>
  19. </properties>
  20. <!--依赖项-->
  21. <dependencies>
  22. <!--spring boot的启动器-->
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter</artifactId>
  26. </dependency>
  27. <!--mybatis-plus的启动器-->
  28. <dependency>
  29. <groupId>com.baomidou</groupId>
  30. <artifactId>mybatis-plus-boot-starter</artifactId>
  31. <version>3.5.1</version>
  32. </dependency>
  33. <!--lombok的驱动包 用于简化实体类的开发-->
  34. <dependency>
  35. <groupId>org.projectlombok</groupId>
  36. <artifactId>lombok</artifactId>
  37. <optional>true</optional>
  38. </dependency>
  39. <!--mysql的连接驱动-->
  40. <dependency>
  41. <groupId>mysql</groupId>
  42. <artifactId>mysql-connector-java</artifactId>
  43. <scope>runtime</scope>
  44. </dependency>
  45. <!--数据源配置-->
  46. <!-- https://mvnrepository.com/artifact/com.zaxxer/HikariCP -->
  47. <dependency>
  48. <groupId>com.zaxxer</groupId>
  49. <artifactId>HikariCP</artifactId>
  50. <version>3.3.1</version>
  51. </dependency>
  52. <dependency>
  53. <groupId>org.springframework.boot</groupId>
  54. <artifactId>spring-boot-starter-test</artifactId>
  55. <scope>test</scope>
  56. </dependency>
  57. </dependencies>
  58. <build>
  59. <plugins>
  60. <plugin>
  61. <groupId>org.springframework.boot</groupId>
  62. <artifactId>spring-boot-maven-plugin</artifactId>
  63. </plugin>
  64. </plugins>
  65. </build>
  66. </project>

lombok插件

简化实体类的开发

使用@Data注解来完成实体类的有参和无参构造,hasCode和equals以及toStirng和getSet方法

application.yml配置

  1. spring:
  2. # 配置数据源信息
  3. datasource:
  4. # 配置数据源类型
  5. type: com.zaxxer.hikari.HikariDataSource
  6. # 配置连接数据库的各个信息
  7. driver-class-name: com.mysql.cj.jdbc.Driver
  8. url: jdbc:mysql://localhost:3306/mybatis?severTimezone=GMT%2B8&characterEncoding=utf-8&ssl=false
  9. username: root
  10. password: root

UserMapper接口

@Repository 标记为持久层组件 解决测试类中的引用报红线问题

@MapperScan 扫描到的mapper。并不是将接口交给IOC容器进行管理,而是将UserMapper动态生成的代{过}{滤}理类交由IOC容器管理,所以IDEA在编译的时候认为UserMapper无法进行自动装配。 在运行阶段的时候是没有这个错误的

  1. package indi.yuluo.mybatisplus.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import indi.yuluo.mybatisplus.pojo.User;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. public interface UserMapper extends BaseMapper<User> {
  7. }

测试

  1. package indi.yuluo.mybatisplus;
  2. import indi.yuluo.mybatisplus.mapper.UserMapper;
  3. import indi.yuluo.mybatisplus.pojo.User;
  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. /**
  9. * @author: yuluo
  10. * @createTime: 2022/3/15 22:30
  11. * @File: MyBatisPlusTest.java
  12. * @Software: IntelliJ IDEA
  13. * @Description:
  14. */
  15. @SpringBootTest
  16. public class MyBatisPlusTest {
  17. @Autowired
  18. private UserMapper userMapper;
  19. /**
  20. * 用于测试:查询集合的方法
  21. */
  22. @Test
  23. public void testSelectList() {
  24. // 通过条件构造器来查询一个list集合,若没有条件,则可以设置null为参数
  25. List<User> list = userMapper.selectList(null);
  26. list.forEach(System.out::println);
  27. }
  28. }

加入日志功能

查看生成的sql语句

  1. spring:
  2. # 配置数据源信息
  3. datasource:
  4. # 配置数据源类型
  5. type: com.zaxxer.hikari.HikariDataSource
  6. # 配置连接数据库的各个信息
  7. driver-class-name: com.mysql.cj.jdbc.Driver
  8. url: jdbc:mysql://localhost:3306/mybatis?severTimezone=GMT%2B8&characterEncoding=utf-8&ssl=false
  9. username: root
  10. password: w082916x
  11. mybatis-plus:
  12. configuration:
  13. # mybatis-plus日志配置
  14. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

mybatis-plus表的结构

mybatis-plus会先去扫描相对应的实体类,根据反射抽取出来里面的属性名,然后在分析要操作的表是谁,属性名(表中的字段)是谁,生成相对应的sql语句来交给IMC容器进行查询

BaseMapper里的新增功能

添加功能 (还可以获取生成的id)

  1. /**
  2. * 用于测试:BaseMapper里面的insert方法
  3. */
  4. @Test
  5. public void testInsert() {
  6. // 准备参数
  7. User user = new User();
  8. user.setAge(20);
  9. user.setName("yuluo");
  10. user.setEmail("yuluo829@aliyun.com");
  11. // 调用insert方法插入 返回值为受影响的行数
  12. int insert = userMapper.insert(user);
  13. System.out.println("insert = " + insert);
  14. // 获取生成的id
  15. System.out.println("id : " + user.getId());
  16. }

执行的SQL语句

  1. ==> Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
  2. ==> Parameters: 1504020449580343298(Long), yuluo(String), 20(Integer), yuluo829@aliyun.com(String)
  3. <== Updates: 1

删除方法

通过id进行删除

  1. /**
  2. * 用于测试:BaseMapper的删除方法
  3. * 加L表示long类型的数据
  4. */
  5. @Test
  6. public void test() {
  7. int i = userMapper.deleteById(1504020449580343298L);
  8. System.out.println("i = " + i);
  9. // 准备删除的条件
  10. // 根据map集合中设置的条件来删除用户信息
  11. Map<String, Object> map = new HashMap<>();
  12. map.put("name", "yuluo");
  13. map.put("age", 20);
  14. userMapper.deleteByMap(map);
  15. // 通过多个id来进行批量删除
  16. List<Long> lists = Arrays.asList(1L, 2L);
  17. userMapper.deleteBatchIds(lists);
  18. }
  • 对应的sql语句
  1. ==> Preparing: DELETE FROM user WHERE id=?
  2. ==> Parameters: 1504020449580343298(Long)
  3. <== Updates: 1
  4. ==> Preparing: DELETE FROM user WHERE name = ? AND age = ?
  5. ==> Parameters: yuluo(String), 20(Integer)
  6. <== Updates: 0
  7. ==> Preparing: DELETE FROM user WHERE id IN ( ? , ? )
  8. ==> Parameters: 1(Long), 2(Long)
  9. <== Updates: 2

修改方法

  1. /**
  2. * 用于测试:BaseMapper里面的修改方法
  3. */
  4. @Test
  5. public void testUpdate() {
  6. // 修改用户信息
  7. User user = new User();
  8. user.setId(3L);
  9. user.setName("huakai");
  10. user.setEmail("huakai@qwer.com");
  11. int i = userMapper.updateById(user);
  12. System.out.println("i = " + i);
  13. }
  • sql语句
  1. ==> Preparing: UPDATE user SET name=?, email=? WHERE id=?
  2. ==> Parameters: huakai(String), huakai@qwer.com(String), 3(Long)
  3. <== Updates: 1

查询方法

  1. /**
  2. * 用于测试:BaseMapper里的查询方法
  3. */
  4. @Test
  5. public void testSelect() {
  6. // 通过id来查询用户信息
  7. User user = userMapper.selectById(3L);
  8. System.out.println("user = " + user);
  9. // 通过id的集合来批量查询
  10. List<Long> longs = Arrays.asList(3L, 4L);
  11. List<User> list = userMapper.selectBatchIds(longs);
  12. list.forEach(System.out::println);
  13. // 根据map集合里的条件来查询用户信息
  14. Map<String, Object> map = new HashMap<>();
  15. map.put("name", "huakai");
  16. map.put("age", "28");
  17. List<User> list = userMapper.selectByMap(map);
  18. list.forEach(System.out::println);
  19. }
  • sql语句
  1. ==> Preparing: SELECT id,name,age,email FROM user WHERE id=?
  2. ==> Parameters: 3(Long)
  3. <== Columns: id, name, age, email
  4. <== Row: 3, huakai, 28, huakai@qwer.com
  5. <== Total: 1
  6. ==> Preparing: SELECT id,name,age,email FROM user WHERE id IN ( ? , ? )
  7. ==> Parameters: 3(Long), 4(Long)
  8. <== Columns: id, name, age, email
  9. <== Row: 3, huakai, 28, huakai@qwer.com
  10. <== Row: 4, Sandy, 21, test4@1234.com
  11. <== Total: 2
  12. ==> Preparing: SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
  13. ==> Parameters: huakai(String), 28(String)
  14. <== Columns: id, name, age, email
  15. <== Row: 3, huakai, 28, huakai@qwer.com
  16. <== Total: 1

自定义功能

  • mybatisplus在mubatis的基础上只做增强,不做改变,以前适用于mybatis的功能在myabayisplus里照样适用
  1. 创建mapper文件夹
  2. 创建mapper文件
  3. 在UserMapper接口中书写sql语句

MyBatis-Plus框架笔记 - 图2

UserMapper接口

  1. package indi.yuluo.mybatisplus.mapper;
  2. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  3. import indi.yuluo.mybatisplus.pojo.User;
  4. import org.springframework.stereotype.Repository;
  5. import java.util.Map;
  6. // 标记为持久层组件 解决测试类中的引用报红线问题
  7. @Repository
  8. public interface UserMapper extends BaseMapper<User> {
  9. /**
  10. * 根据id查询用户信息为map集合
  11. * @param id
  12. * @return
  13. */
  14. Map<String, Object> selectById(Long id);
  15. }

UserMapper.xml

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3. "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  4. <mapper namespace="indi.yuluo.mybatisplus.mapper.UserMapper">
  5. <select id="selectById" resultType="map">
  6. select id, name, age, email from user where id=#{id}
  7. </select>
  8. </mapper>

测试

  1. /**
  2. * 用于测试:自定义查询功能
  3. */
  4. @Test
  5. public void test() {
  6. Map<String, Object> map = userMapper.selectById(4L);
  7. System.out.println(map);
  8. }

通用service接口

说明:

  • 通用 Service CRUD 封装IService (opens new window)接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
  • 泛型 T 为任意实体对象
  • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
  • 对象 Wrapper条件构造器
  • MyBatis-Plus中有一个接口IService接口和其实现类ServiceImpl,封装了常见的业务层逻辑

关于mybstisplus提供的IService的使用

  • 建议编写自己的service,mybatiplus提供的IService不能完全适应复杂的业务场景,可以书写自己的service来继承mybatisplus的IService

UserService接口

  1. package indi.yuluo.mybatisplus.service;
  2. import com.baomidou.mybatisplus.extension.service.IService;
  3. import indi.yuluo.mybatisplus.pojo.User;
  4. public interface UserService extends IService<User> {
  5. }

UserServiceImpl

  1. package indi.yuluo.mybatisplus.service.Impl;
  2. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  3. import indi.yuluo.mybatisplus.mapper.UserMapper;
  4. import indi.yuluo.mybatisplus.pojo.User;
  5. import indi.yuluo.mybatisplus.service.UserService;
  6. import org.springframework.stereotype.Service;
  7. /**
  8. * @author: yuluo
  9. * @createTime: 2022/3/16 18:02
  10. * @File: UserServieImpl.java
  11. * @Software: IntelliJ IDEA
  12. * @Description:
  13. */
  14. @Service
  15. public class UserServieImpl extends ServiceImpl<UserMapper, User> implements UserService {
  16. }

测试

  1. package indi.yuluo.mybatisplus;
  2. import indi.yuluo.mybatisplus.mapper.UserMapper;
  3. import indi.yuluo.mybatisplus.service.UserService;
  4. import org.junit.jupiter.api.Test;
  5. import org.springframework.beans.factory.annotation.Autowired;
  6. import org.springframework.boot.test.context.SpringBootTest;
  7. /**
  8. * @author: yuluo
  9. * @createTime: 2022/3/16 18:13
  10. * @File: MyBatisPlusServiceTest.java
  11. * @Software: IntelliJ IDEA
  12. * @Description:
  13. */
  14. @SpringBootTest
  15. public class MyBatisPlusServiceTest {
  16. // 自动装配
  17. @Autowired
  18. private UserService userService;
  19. /**
  20. * 用于测试:
  21. */
  22. @Test
  23. public void testGetCount() {
  24. // 查询总记录数
  25. long count = userService.count();
  26. System.out.println("count = " + count);
  27. }
  28. }
  • SQL语句
  1. ==> Preparing: SELECT COUNT( * ) FROM user
  2. ==> Parameters:
  3. <== Columns: COUNT( * )
  4. <== Row: 3
  5. <== Total: 1

通用service的批量添加操作

测试

  1. /**
  2. * 用于测试:通用service的批量添加操作
  3. */
  4. @Test
  5. public void testInsertMore() {
  6. // 准备数据
  7. // 批量添加
  8. List<User> list = new ArrayList<>();
  9. for (int i = 0; i < 10; i++) {
  10. User user = new User();
  11. user.setName("yuluo" + i);
  12. user.setAge(20 + i);
  13. list.add(user);
  14. }
  15. boolean b = userService.saveBatch(list);
  16. System.out.println("b = " + b);
  17. }
  • SQL语句
  1. ==> Preparing: INSERT INTO user ( id, name, age ) VALUES ( ?, ?, ? )
  2. ==> Parameters: 1504040927478484993(Long), yuluo0(String), 20(Integer)
  3. ==> Parameters: 1504040927553982465(Long), yuluo1(String), 21(Integer)
  4. ==> Parameters: 1504040927553982466(Long), yuluo2(String), 22(Integer)
  5. ==> Parameters: 1504040927553982467(Long), yuluo3(String), 23(Integer)
  6. ==> Parameters: 1504040927553982468(Long), yuluo4(String), 24(Integer)
  7. ==> Parameters: 1504040927553982469(Long), yuluo5(String), 25(Integer)
  8. ==> Parameters: 1504040927553982470(Long), yuluo6(String), 26(Integer)
  9. ==> Parameters: 1504040927553982471(Long), yuluo7(String), 27(Integer)
  10. ==> Parameters: 1504040927553982472(Long), yuluo8(String), 28(Integer)
  11. ==> Parameters: 1504040927553982473(Long), yuluo9(String), 29(Integer)
  12. b = true

MyBatis-plus的常用注解

表名由BaseMapper的泛型类型决定

@TableName 注解

  • 处理数据库的表名和实体类名不一致的情况
  • 数据库中的表名为t_user
  1. package indi.yuluo.mybatisplus.pojo;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. /**
  5. * @author: yuluo
  6. * @createTime: 2022/3/15 22:19
  7. * @File: User.java
  8. * @Software: IntelliJ IDEA
  9. * @Description:
  10. */
  11. @Data
  12. @TableName("t_user")
  13. public class User {
  14. private Long id;
  15. private String name;
  16. private Integer age;
  17. private String email;
  18. }

当所有的表名前面都有一个一致的前缀的时候,可以在yml配置文件中通过配置给所有的实体类加上同一个前缀

  • 数据库中的表名为t_user
  1. mybatis-plus:
  2. configuration:
  3. # mybatis-plus日志配置
  4. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  5. # 设置MyBatis-Plus的全局配置
  6. global-config:
  7. db-config:
  8. # 设置实体类所对应的表的统一前缀
  9. table-prefix: t_

@TableId

将属性所对应的字段指定为主键

  1. package indi.yuluo.mybatisplus.pojo;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. /**
  5. * @author: yuluo
  6. * @createTime: 2022/3/15 22:19
  7. * @File: User.java
  8. * @Software: IntelliJ IDEA
  9. * @Description:
  10. */
  11. @Data
  12. @TableName("t_user")
  13. public class User {
  14. @TableId
  15. private Long id;
  16. private String name;
  17. private Integer age;
  18. private String email;
  19. }

TableId的value属性

作用:用于指定主键的字段

  • 数据库中的主键字段为uId时
  1. package indi.yuluo.mybatisplus.pojo;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. /**
  5. * @author: yuluo
  6. * @createTime: 2022/3/15 22:19
  7. * @File: User.java
  8. * @Software: IntelliJ IDEA
  9. * @Description:
  10. */
  11. @Data
  12. @TableName("t_user")
  13. public class User {
  14. // value可以省略
  15. @TableId(value="uId")
  16. private Long id;
  17. private String name;
  18. private Integer age;
  19. private String email;
  20. }

@TableId的type属性

  • 设置主键生成策略 (自动递增和雪花算法) 默认为雪花算法
  • 条件:
    • 数据库中的主键设置为自动递增,否则无效
  1. package indi.yuluo.mybatisplus.pojo;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. /**
  5. * @author: yuluo
  6. * @createTime: 2022/3/15 22:19
  7. * @File: User.java
  8. * @Software: IntelliJ IDEA
  9. * @Description:
  10. */
  11. @Data
  12. @TableName("t_user")
  13. public class User {
  14. @TableId(value = "uId", type = IdType.AUTO)
  15. private Long id;
  16. private String name;
  17. private Integer age;
  18. private String email;
  19. }

通过全局配置配置主键生成策略

  1. spring:
  2. # 配置数据源信息
  3. datasource:
  4. # 配置数据源类型
  5. type: com.zaxxer.hikari.HikariDataSource
  6. # 配置连接数据库的各个信息
  7. driver-class-name: com.mysql.cj.jdbc.Driver
  8. url: jdbc:mysql://localhost:3306/mybatis?severTimezone=GMT%2B8&characterEncoding=utf-8&ssl=false
  9. username: root
  10. password: w082916x
  11. mybatis-plus:
  12. configuration:
  13. # mybatis-plus日志配置
  14. log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  15. # 设置MyBatis-Plus的全局配置
  16. global-config:
  17. db-config:
  18. # 设置实体类所对应的表的统一前缀
  19. table-prefix: t_
  20. # 设置统一的主键生成策略
  21. id-type: auto

TableField

指定属性对应的字段名

  1. @TableField("user_name")

@TableLogic

  • 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据
  • 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”。此后在数据库中任然可以看见此条数据记录
  • 使用场景:可以进行数据恢复

逻辑删除的实现步骤:

  • 在数据库中新建一个字段,默认值设置为0,
  • 在User实体类中设置isDeleted属性,加上@TableLogic注解
  1. package indi.yuluo.mybatisplus.pojo;
  2. import com.baomidou.mybatisplus.annotation.TableLogic;
  3. import lombok.Data;
  4. /**
  5. * @author: yuluo
  6. * @createTime: 2022/3/15 22:19
  7. * @File: User.java
  8. * @Software: IntelliJ IDEA
  9. * @Description:
  10. */
  11. @Data
  12. public class User {
  13. private Long id;
  14. private String name;
  15. private Integer age;
  16. private String email;
  17. @TableLogic
  18. private Integer isDeleted;
  19. }

雪花算法(mybatis-plus自动生成主键的默认策略)

背景

需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量

数据库的扩展方式主要包括:业务分库,主从复制,数据库分表

数据库分表

将不同业务数据分撒存储到不同的数据库服务器,能够支撑百万甚至千万用户规模的业务,但如果业务继续发展,同一业务的单表数据也会达到单台数据库服务器的处理瓶颈

  • 单表数据拆分的形式有两种:
    • 垂直分表:将表中某些不常用且占了大量空间的列拆分出去
    • 水平分表:适合表行数特别大的表

介绍

雪花算法是由Twitier公布的分布式主键生成算法,能够保证不同表的主键的不重复性,以及相同表的主键的有序性

  • 核心思想
    • 长度共64bit(一个long型)
    • 41bit时间戳(毫秒级)存储的是时间戳的差值(当前时间戳 - 开始时间戳)结果约等于69.73年
    • 10bit作为机器的id,(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)
    • 12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生4096个ID)
  • 优点:
    • 整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高

条件构造器简介(wapper介绍)

  • Wrapper条件构造器,最顶端父类
    • AbstractWrapper:用于查询条件封装,生成sql的where条件
    • QueryWrapper:查询条件封装
    • UpdateWrapper:Update条件封装
    • AbstractLambdaWrapper:使用lambda语法
      • LambdaQueryWrapper: 用于Lambda语法使用额查询Wrapper
      • LambdaUpdateWrapper:Lambda更新封装Wrapper

组装查询条件

  1. /**
  2. * 用于测试:wrapper条件构造器
  3. */
  4. @Test
  5. public void test1() {
  6. // 查询条件: 用户名包含a,年两在20到30之间并且邮箱不为空的用户信息
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.like("name", "a")
  9. .between("age", 20, 30)
  10. .isNotNull("email");
  11. List<User> list = userMapper.selectList(queryWrapper);
  12. list.forEach(System.out::print);
  13. }
  • sql语句
  1. ==> Preparing: SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (name LIKE ? AND age BETWEEN ? AND ? AND email IS NOT NULL)
  2. ==> Parameters: %a%(String), 20(Integer), 30(Integer)
  3. <== Columns: id, name, age, email, is_deleted
  4. <== Row: 3, huakai, 28, huakai@qwer.com, 0
  5. <== Row: 4, Sandy, 21, test4@1234.com, 0
  6. <== Total: 2

组装排序条件

  1. /**
  2. * 用于测试:wrapper条件构造器组装排序条件
  3. */
  4. @Test
  5. public void test2() {
  6. // 查询用户信息,按照年龄的降序排序,若年龄相同,则按照id升序排序
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.orderByDesc("age")
  9. .orderByAsc("id");
  10. List<User> list = userMapper.selectList(queryWrapper);
  11. list.forEach(System.out::print);
  12. }
  • sql语句
  1. ==> Preparing: SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 ORDER BY age DESC,id ASC
  2. ==> Parameters:
  3. <== Columns: id, name, age, email, is_deleted
  4. <== Row: 1504040927553982473, yuluo9, 29, null, 0
  5. <== Row: 3, huakai, 28, huakai@qwer.com, 0
  6. <== Row: 1504040927553982472, yuluo8, 28, null, 0
  7. <== Row: 1504040927553982471, yuluo7, 27, null, 0
  8. <== Row: 1504040927553982470, yuluo6, 26, null, 0
  9. <== Row: 1504040927553982469, yuluo5, 25, null, 0
  10. <== Row: 5, Biilie, 24, test5@1234.com, 0
  11. <== Row: 1504040927553982468, yuluo4, 24, null, 0
  12. <== Row: 1504040927553982467, yuluo3, 23, null, 0
  13. <== Row: 1504040927553982466, yuluo2, 22, null, 0
  14. <== Row: 4, Sandy, 21, test4@1234.com, 0
  15. <== Row: 1504040927553982465, yuluo1, 21, null, 0
  16. <== Row: 1504040927478484993, yuluo0, 20, null, 0
  17. <== Total: 13

组装删除条件

  1. /**
  2. * 用于测试:wrapper条件构造器组装删除条件
  3. */
  4. @Test
  5. public void test3() {
  6. // 删除所有邮箱为null的用户信息
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.isNull("email");
  9. int delete = userMapper.delete(queryWrapper);
  10. // 输出受影响的行数
  11. System.out.println("delete = " + delete);
  12. }
  • 因为加入了逻辑删除字段,所以删除时只是将is_deleted更改为了1
  • sql语句
  1. ==> Preparing: UPDATE user SET is_deleted=1 WHERE is_deleted=0 AND (email IS NULL)
  2. ==> Parameters:
  3. <== Updates: 10

实现修改功能

  1. /**
  2. * 用于测试:wrapper条件构造器组装修改条件
  3. */
  4. @Test
  5. public void test() {
  6. // 将(年龄大于20并且用户名中包含a)或邮箱为nul来的用户信息修改
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. // 当条件是and关系是不需要写出and 默认给出and
  9. // 当条件之间是or关系时,需要用or()来连接
  10. queryWrapper.gt("age", 20)
  11. .like("name", "a")
  12. . or()
  13. .isNull("email");
  14. // 设置修改的属性
  15. User user = new User();
  16. user.setName("huakai");
  17. user.setEmail("780879337@qq.com");
  18. // update()两个参数一个设置的是修改的内容,一个是wrapper条件
  19. int update = userMapper.update(user, queryWrapper);
  20. System.out.println("update = " + update);
  21. }
  • sql语句
  1. ==> Preparing: UPDATE user SET name=?, email=? WHERE is_deleted=0 AND (age > ? AND name LIKE ? OR email IS NULL)
  2. ==> Parameters: huakai(String), 780879337@qq.com(String), 20(Integer), %a%(String)
  3. <== Updates: 2

条件的优先级

确保条件优先执行的时候可以执行and方法

lambda中的条件优先执行

  1. /**
  2. * 用于测试:wrapper条件构造器的条件优先级
  3. */
  4. @Test
  5. public void test5() {
  6. // 将用户名中包含有a并且(年龄大于10或者邮箱为null)的用户信息修改
  7. // lambda中的条件优先执行
  8. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  9. queryWrapper.like("name", "a")
  10. .and(i -> i.gt("age", 10).or().isNull("email"));
  11. // 设置修改的属性
  12. User user = new User();
  13. user.setName("huakai love yuluo");
  14. user.setEmail("780879337@qq.com");
  15. int update = userMapper.update(user, queryWrapper);
  16. System.out.println("update = " + update);
  17. }
  • sql语句
  1. ==> Preparing: UPDATE user SET name=?, email=? WHERE is_deleted=0 AND (name LIKE ? AND (age > ? OR email IS NULL))
  2. ==> Parameters: huakai love yuluo(String), 780879337@qq.com(String), %a%(String), 10(Integer)
  3. <== Updates: 2

组装select子句

  1. /**
  2. * 用于测试:组装select子句
  3. */
  4. @Test
  5. public void test6() {
  6. // 查询用户的用户名、年龄、邮箱信息
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.select("name", "age", "email");
  9. List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
  10. maps.forEach(System.out::println);
  11. }
  • sql语句
  1. ==> Preparing: SELECT name,age,email FROM user WHERE is_deleted=0
  2. ==> Parameters:
  3. <== Columns: name, age, email
  4. <== Row: huakai love yuluo, 28, 780879337@qq.com
  5. <== Row: huakai love yuluo, 21, 780879337@qq.com
  6. <== Row: Biilie, 24, test5@1234.com
  7. <== Total: 3
  8. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4cb40e3b]
  9. // 查询结果
  10. {name=huakai love yuluo, age=28, email=780879337@qq.com}
  11. {name=huakai love yuluo, age=21, email=780879337@qq.com}
  12. {name=Biilie, age=24, email=test5@1234.com}

组装子查询

  1. /**
  2. * 用于测试:组装子查询
  3. */
  4. @Test
  5. public void test7() {
  6. // 查询id小于等于100的用户信息
  7. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.lt("id", 100);
  9. List<User> list = userMapper.selectList(queryWrapper);
  10. list.forEach(System.out::println);
  11. }
  • sql语句
  1. ==> Preparing: SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id < ?)
  2. ==> Parameters: 100(Integer)
  3. <== Columns: id, name, age, email, is_deleted
  4. <== Row: 3, huakai love yuluo, 28, 780879337@qq.com, 0
  5. <== Row: 4, huakai love yuluo, 21, 780879337@qq.com, 0
  6. <== Row: 5, Biilie, 24, test5@1234.com, 0
  7. <== Total: 3
  8. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6cd56321]
  9. //
  10. User(id=3, name=huakai love yuluo, age=28, email=780879337@qq.com, isDeleted=0)
  11. User(id=4, name=huakai love yuluo, age=21, email=780879337@qq.com, isDeleted=0)
  12. User(id=5, name=Biilie, age=24, email=test5@1234.com, isDeleted=0)

子查询SQL语句

select * from user where id in (select id from user where id <= 100);

  1. /**
  2. * 用于测试:组装子查询
  3. */
  4. @Test
  5. public void test7() {
  6. // 查询id小于等于100的用户信息
  7. /*QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  8. queryWrapper.lt("id", 100);
  9. List<User> list = userMapper.selectList(queryWrapper);
  10. list.forEach(System.out::println);*/
  11. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  12. queryWrapper.inSql("id", "select id from user where id <= 100");
  13. List<User> list = userMapper.selectList(queryWrapper);
  14. list.forEach(System.out::println);
  15. }
  • sql语句
  1. ELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (id IN (select id from user where id <= 100))
  2. ==> Parameters:
  3. <== Columns: id, name, age, email, is_deleted
  4. <== Row: 3, huakai love yuluo, 28, 780879337@qq.com, 0
  5. <== Row: 4, huakai love yuluo, 21, 780879337@qq.com, 0
  6. <== Row: 5, Biilie, 24, test5@1234.com, 0
  7. <== Total: 3
  8. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@19382338]
  9. User(id=3, name=huakai love yuluo, age=28, email=780879337@qq.com, isDeleted=0)
  10. User(id=4, name=huakai love yuluo, age=21, email=780879337@qq.com, isDeleted=0)
  11. User(id=5, name=Biilie, age=24, email=test5@1234.com, isDeleted=0)

使用updateWrapper实现修改功能

  1. /**
  2. * 用于测试:updateWrapper实现修改功能
  3. */
  4. @Test
  5. public void test8() {
  6. // 将用户名中包含有a并且(年龄大于20或者邮箱为null)的用户信息修改
  7. UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
  8. updateWrapper.like("user_name", "a")
  9. .and(i -> i.gt("age", 20).or().isNull("email"));
  10. // 设置修改内容
  11. updateWrapper.set("name", "yuluo").set("email", "yuluo@qq.com");
  12. int update = userMapper.update(null, updateWrapper);
  13. System.out.println("update = " + update);
  14. }
  • sql语句
  1. ==> Preparing: UPDATE user SET name=?,email=? WHERE is_deleted=0 AND (name LIKE ? AND (age > ? OR email IS NULL))
  2. ==> Parameters: yuluo(String), yuluo@qq.com(String), %a%(String), 20(Integer)
  3. <== Updates: 2
  4. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6c15e8c7]
  5. update = 2

模拟开发中组装条件的情况

第一种方法(较复杂)

  1. /**
  2. * 用于测试:模拟实际开发中的场景
  3. */
  4. @Test
  5. public void test9() {
  6. String name = "";
  7. Integer ageBegin = 20;
  8. Integer ageEnd = 30;
  9. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  10. // 组装条件
  11. if (StringUtils.isNotBlank(name)) {
  12. // isNotBlank判断某个字符串是否不为空字符串,不为null,不为空白符
  13. queryWrapper.like("name", name);
  14. }
  15. if (ageBegin != null) {
  16. queryWrapper.ge("age", ageBegin);
  17. }
  18. if (ageEnd != null) {
  19. queryWrapper.lt("age", ageEnd);
  20. }
  21. List<User> list = userMapper.selectList(queryWrapper);
  22. list.forEach(System.out::println);
  23. }
  • sql语句
  1. ==> Preparing: SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 AND (age >= ? AND age < ?)
  2. ==> Parameters: 20(Integer), 30(Integer)
  3. <== Columns: id, name, age, email, is_deleted
  4. <== Row: 3, yuluo, 28, yuluo@qq.com, 0
  5. <== Row: 4, yuluo, 21, yuluo@qq.com, 0
  6. <== Row: 5, Biilie, 24, test5@1234.com, 0
  7. <== Total: 3
  8. Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5707f613]
  9. User(id=3, name=yuluo, age=28, email=yuluo@qq.com, isDeleted=0)
  10. User(id=4, name=yuluo, age=21, email=yuluo@qq.com, isDeleted=0)
  11. User(id=5, name=Biilie, age=24, email=test5@1234.com, isDeleted=0)

简便写法

  1. /**
  2. * 用于测试:模拟实际开发中的场景 简便方法
  3. */
  4. @Test
  5. public void test10() {
  6. String name = "a";
  7. Integer ageBegin = 20;
  8. Integer ageEnd = 30;
  9. QueryWrapper<User> queryWrapper = new QueryWrapper<>();
  10. queryWrapper.like(StringUtils.isNotBlank(name), "name", name)
  11. .ge(ageBegin != null, "age", ageBegin)
  12. .le(ageEnd != null, "age", ageEnd);
  13. List<User> list = userMapper.selectList(queryWrapper);
  14. list.forEach(System.out::println);
  15. }

LambdaQueryWrapper

  1. /**
  2. * 用于测试:测试LambdaQueryWrapper 同test10
  3. */
  4. @Test
  5. public void test11() {
  6. String name = "a";
  7. Integer ageBegin = 20;
  8. Integer ageEnd = 30;
  9. LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
  10. // 使用钻石表达式来代替数据库字段名,防止写错
  11. lambdaQueryWrapper.like(StringUtils.isNotBlank(name), User::getName, name)
  12. .ge(ageBegin != null, User::getAge, ageBegin)
  13. .le(ageEnd != null, User::getAge, ageEnd);
  14. List<User> list = userMapper.selectList(lambdaQueryWrapper);
  15. list.forEach(System.out::println);
  16. }

LambdaUpdateWrapper

  1. /**
  2. * 用于测试:updateWrapper实现修改功能
  3. */
  4. @Test
  5. public void test8() {
  6. // 将用户名中包含有a并且(年龄大于20或者邮箱为null)的用户信息修改
  7. LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
  8. updateWrapper.like(User::getName, "a")
  9. .and(i -> i.gt(User::getAge, 20).or().isNull(User::getEmail));
  10. // 设置修改内容
  11. updateWrapper.set(User::getName, "yuluo").set(User::getEmail, "yuluo@qq.com");
  12. int update = userMapper.update(null, updateWrapper);
  13. System.out.println("update = " + update);
  14. }

插件功能

分页插件

  • 编写配置类

有了配置类之后,建议MapperScan注解从启动类移动到配置类上

  1. package indi.yuluo.mybatisplus.config;
  2. import com.baomidou.mybatisplus.annotation.DbType;
  3. import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
  4. import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
  5. import org.mybatis.spring.annotation.MapperScan;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. /**
  9. * @author: yuluo
  10. * @createTime: 2022/3/17 17:18
  11. * @File: MyBatisPlusConfig.java
  12. * @Software: IntelliJ IDEA
  13. * @Description:
  14. */
  15. @Configuration
  16. // 扫描mapper接口所在的包
  17. @MapperScan("indi.yuluo.mybatisplus.mapper")
  18. public class MyBatisPlusConfig {
  19. @Bean
  20. public MybatisPlusInterceptor mybatisPlusInterceptor() {
  21. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  22. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  23. return interceptor;
  24. }
  25. }

测试类

  1. /**
  2. * 用于测试:
  3. */
  4. @Test
  5. public void testPage() {
  6. // mysql数据库使用的是limit关键字来进行分页操作
  7. // limit后面的两个参数是页码和展示的记录条数
  8. Page<User> page = new Page<User>(1, 3);
  9. userMapper.selectPage(page, null);
  10. System.out.println(page);
  11. }
  • sql语句
  1. ==> Preparing: SELECT COUNT(*) AS total FROM user WHERE is_deleted = 0
  2. ==> Parameters:
  3. <== Columns: total
  4. <== Row: 3
  5. <== Total: 1
  6. ==> Preparing: SELECT id,name,age,email,is_deleted FROM user WHERE is_deleted=0 LIMIT ?
  7. ==> Parameters: 3(Long)
  8. <== Columns: id, name, age, email, is_deleted
  9. <== Row: 3, yuluo, 28, yuluo@qq.com, 0
  10. <== Row: 4, yuluo, 21, yuluo@qq.com, 0
  11. <== Row: 5, Biilie, 24, test5@1234.com, 0
  12. <== Total: 3

分页相关数据获取

  1. getPages(); 获取当前页的页码
  2. getRecords(); 获取当前页的记录
  3. getTotal(); 获取总记录数
  4. hasNext(); 判断有没有下一页
  5. hasPrevious(); 判断有没有上一页

自定义分页功能

UserMapper接口

  1. /**
  2. * 通过年龄查询用户信息并分页
  3. * @param page MyBatis-Plus提供的分页插件,必须位于第一个参数的位置
  4. * @param age
  5. * @return
  6. */
  7. Page<User> selectPageVo(@Param("page")Page<User> page,
  8. @Param("age") Integer age);

userMapper.xml

  1. <select id="selectPageVo" resultType="User">
  2. select id, name, age, email from user where age > #{age}
  3. </select>

配置文件

  1. # 配置类型别名所对应的包
  2. type-aliases-package: indi.yuluo.mybatisplus.pojo

测试方法

  1. /**
  2. * 用于测试:自定义的分页功能
  3. */
  4. @Test
  5. public void testPageVo() {
  6. Page<User> page = new Page<User>(1, 3);
  7. userMapper.selectPageVo(page, 20);
  8. System.out.println(page);
  9. }

乐观锁和悲观锁

乐观锁

乐观锁是相对悲观锁而言的,乐观锁假设数据一般情况不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果冲突,则返回给用户异常信息,让用户决定如何去做。乐观锁适用于读多写少的场景,这样可以提高程序的吞吐量

乐观锁通过 版本号 来实现

悲观锁

当要对数据库中的一条数据进行修改的时候,为了避免同时被其他人修改,最好的办法就是直接对该数据进行加锁以防止并发。这种借助数据库锁机制,在修改数据之前先锁定,再修改的方式被称之为悲观并发控制【Pessimistic Concurrency Control,缩写“PCC”,又名“悲观锁”】

模拟修改冲突

  1. package indi.yuluo.mybatisplus;
  2. import indi.yuluo.mybatisplus.mapper.ProductMapper;
  3. import indi.yuluo.mybatisplus.pojo.Product;
  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. /**
  9. * @author: yuluo
  10. * @createTime: 2022/3/17 19:51
  11. * @File: ProductTest.java
  12. * @Software: IntelliJ IDEA
  13. * @Description:
  14. */
  15. @SpringBootTest
  16. public class ProductTest {
  17. @Autowired
  18. private ProductMapper productMapper;
  19. /**
  20. * 用于测试:product表的测试类
  21. */
  22. @Test
  23. public void testProduct01() {
  24. // 小李查询商品价格
  25. Product productLi = productMapper.selectById(1);
  26. System.out.println("小李查询到的商品价格:" + productLi.getPrice());
  27. // 小明查询商品价格
  28. Product productWang = productMapper.selectById(1);
  29. System.out.println("小王查询到的商品价格:" + productWang.getPrice());
  30. // 小李将商品价格提高50
  31. productLi.setPrice(productLi.getPrice() + 50);
  32. productMapper.updateById(productLi);
  33. // 小王将商品的价格减去30
  34. productWang.setPrice(productWang.getPrice() - 10);
  35. productMapper.updateById(productWang);
  36. // 老板查询商品价格
  37. Product productLaoban = productMapper.selectById(1);
  38. System.out.println("老板查询到的商品价格:" + productLaoban.getPrice());
  39. }
  40. }
  • 小王查询到的商品价格:100
  • 小李查询到的商品价格:100
  • 老板查询到的商品价格:70

使用MyBaatis-Plus提供的乐观锁插件来优化问题

  • 在实体类中版本号属性上添加@Version // 标识乐观锁版本号字段注解
  • 在配置Bean中添加插件
    ```

// 添加乐观锁插件 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

  1. - 结果:
  2. - ![](https://www.52pojie.cn/images/image-20220317201837848-16475195286431.png#id=urjuG&originalType=binary&ratio=1&status=done&style=none)
  3. - 因为小李在修改了商品的价格之后,商品的版本号发生了变化,所以小王修改失败了
  4. - 优化修改流程
  5. -

// 小李将商品价格提高50 productLi.setPrice(productLi.getPrice() + 50); productMapper.updateById(productLi);

// 小王将商品的价格减去30 productWang.setPrice(productWang.getPrice() - 10); int i = productMapper.updateById(productWang); // 版本号发生了变化之后再次进行修改操作 if (i == 0) { Product productNew = productMapper.selectById(1); productNew.setPrice(productNew.getPrice() - 30); productMapper.updateById(productNew); }

// 老板查询商品价格 Product productLaoban = productMapper.selectById(1); System.out.println(“老板查询到的商品价格:” + productLaoban.getPrice());

  1. - 老板查询到的商品价格:120
  2. - 最终的结果:
  3. ![](https://www.52pojie.cn/images/image-20220317202549832-16475199510892.png#id=I5AFO&originalType=binary&ratio=1&status=done&style=none)
  4. <a name="ef2a9020"></a>
  5. ## 通用枚举
  6. - 枚举类的写法

package indi.yuluo.mybatisplus.enums;

import com.baomidou.mybatisplus.annotation.EnumValue; import lombok.Getter;

/**

  • @author: yuluo
  • @createTime: 2022/3/17 20:28
  • @File: SexEnum.java
  • @Software: IntelliJ IDEA
  • @Description: */

@Getter public enum SexEnum { MALE(1, “男”), FEMALE(2, “女”);

  1. // 注解的作用是将标识的属性的值存放到数据库中
  2. @EnumValue
  3. private Integer sex;
  4. private String sexName;
  5. SexEnum(Integer sex, String sexName) {
  6. this.sex = sex;
  7. this.sexName = sexName;
  8. }

}

  1. - 测试类

package indi.yuluo.mybatisplus;

import indi.yuluo.mybatisplus.enums.SexEnum; import indi.yuluo.mybatisplus.mapper.UserMapper; import indi.yuluo.mybatisplus.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;

/**

  • @author: yuluo
  • @createTime: 2022/3/17 21:24
  • @File: MyBatisPlusEnumTest.java
  • @Software: IntelliJ IDEA
  • @Description: */

@SpringBootTest public class MyBatisPlusEnumTest {

  1. @Autowired
  2. private UserMapper userMapper;
  3. /**
  4. * 用于测试:
  5. */
  6. @Test
  7. public void test() {
  8. User user = new User();
  9. user.setAge(20);
  10. user.setEmail("huakai@qq.com");
  11. user.setName("huakai");
  12. user.setSex(SexEnum.FEMALE);
  13. int insert = userMapper.insert(user);
  14. System.out.println("insert = " + insert);
  15. }

}

  1. - 配置文件

扫描通用枚举的包

type-enums-package: indi.yuluo.mybatisplus.enums

  1. <a name="8b8ca150"></a>
  2. ## 代码生成器
  3. - 添加依赖
com.baomidou mybatis-plus-generator 3.5.1

org.freemarker freemarker 2.3.31

  1. - 将如下代码粘贴到测试方法中

package indi.yuluo.mybatisplus;

import com.baomidou.mybatisplus.generator.FastAutoGenerator; import com.baomidou.mybatisplus.generator.config.OutputFile; import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine; import org.springframework.boot.test.context.SpringBootTest;

import java.util.Collections;

/**

  • @author: yuluo
  • @createTime: 2022/3/17 21:39
  • @File: MyBatisPlusFastAutoGeneratorTest.java
  • @Software: IntelliJ IDEA
  • @Description: */

@SpringBootTest public class MyBatisPlusFastAutoGeneratorTest {

  1. public static void main(String[] args) {
  2. FastAutoGenerator.create("jdbc:mysql://127.0.0.1:3306/mybatis?characterEncoding=utf-8&userSSL=false", "root", "w082916x")
  3. // 全局配置
  4. .globalConfig(builder -> {
  5. builder.author("yuluo") // 设置作者
  6. // .enableSwagger() // 开启 swagger 模式
  7. .fileOverride() // 覆盖已生成文件
  8. .outputDir("F://mybatis-plus"); // 指定输出目录
  9. })
  10. // 包配置
  11. .packageConfig(builder -> {
  12. builder.parent("indi.yuluo") // 设置父包名
  13. .moduleName("mybatisplus") // 设置父包模块名
  14. .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "F://mybatis-plus")); // 设置mapperXml生成路径
  15. })
  16. // 策略配置
  17. .strategyConfig(builder -> {
  18. builder.addInclude("user") // 设置需要生成的表名
  19. .addTablePrefix("t_", "c_"); // 设置过滤表前缀
  20. })
  21. .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
  22. .execute();
  23. }

} ```