MyBatis-Plus
简介
MyBatis-Plus(简称 MP)是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
 
- 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
 
基于SpringBoot使用MyBatisPlus
数据库设计

新建项目




导入依赖

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
   | <dependencies>     <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>     <dependency>         <groupId>mysql</groupId>         <artifactId>mysql-connector-java</artifactId>         <scope>runtime</scope>     </dependency>     <dependency>         <groupId>com.alibaba</groupId>         <artifactId>druid</artifactId>         <version>1.2.11</version>     </dependency>     <dependency>         <groupId>com.baomidou</groupId>         <artifactId>mybatis-plus-boot-starter</artifactId>         <version>3.4.1</version>     </dependency>     <dependency>         <groupId>org.projectlombok</groupId>         <artifactId>lombok</artifactId>     </dependency> </dependencies>
   | 
 
编辑配置

1 2 3 4 5 6 7
   | spring:   datasource:     type: com.alibaba.druid.pool.DruidDataSource     driver-class-name: com.mysql.cj.jdbc.Driver     url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC     username: root     password: 13851176590++
   | 
 
添加启动类

1 2 3 4 5 6
   | @SpringBootApplication public class MyBatisPlusApplication {     public static void main(String[] args) {         SpringApplication.run(MyBatisPlusApplication.class, args);     } }
   | 
 
创建实体类

1 2 3 4 5 6 7 8
   | @Data public class User {     private Long id;     private String name;     private String password;     private Integer age;     private String tel; }
   | 
 
创建Dao接口

1 2 3 4
   | @Mapper public interface UserMapper extends BaseMapper<User> {
  }
   | 
 
创建测试类

1 2 3 4 5 6 7 8 9 10 11 12
   | @SpringBootTest public class MyBatisPlusApplicationTest {     @Resource     private UserMapper userMapper;     private static final Logger logger = LoggerFactory.getLogger(MyBatisPlusApplicationTest.class);          @Test     void getAll(){         List<User> users = userMapper.selectList(null);         logger.info("用户列表:" + users);     } }
   | 
 
简化日志输出
新建logback.xml配置文件

编辑配置

1 2 3
   | <?xml version="1.0" encoding="UTF-8"?> <configuration> </configuration>
   | 
 
关闭Banner

启动测试

标准数据层开发

新增操作

1 2 3 4 5
   | @Test void saveUser() {     User user = new User().setName("xiaohong").setAge(21).setPassword("123456").setTel("123456");     Integer count = userMapper.insert(user); }
   | 
 

删除操作


修改操作

1 2 3 4 5
   | @Test void updateUser() {     User user = new User().setId(1L).setAge(50);     userMapper.updateById(user); }
   | 
 

分页查询
配置分页拦截器

编辑测试类


添加日志输出


DQL
条件查询
查看Wrapper抽象类


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
   |               @Test     void getByQueryWrapper() {         QueryWrapper<User> queryWrapper = new QueryWrapper<User>();         queryWrapper.gt("age", 20).lt("age", 40);         List<User> users = userMapper.selectList(queryWrapper);         users.forEach(user -> logger.info("用户:" + user));     }          @Test     void getByQueryWrapperForLambda() {         QueryWrapper<User> queryWrapper = new QueryWrapper<User>();         queryWrapper.lambda().gt(User::getAge, 20).lt(User::getAge, 40);         List<User> users = userMapper.selectList(queryWrapper);         users.forEach(user -> logger.info("用户:" + user));     }          @Test     void getByLambdaQueryWrapper() {         LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();                  lambdaQueryWrapper.gt(User::getAge, 20).lt(User::getAge, 40);         
          List<User> users = userMapper.selectList(lambdaQueryWrapper);         users.forEach(user -> logger.info("用户:" + user));     }
   | 
 

空值判定
新建用户查询条件类

空值测试


空值判定方法
方法一:if条件语句控制

1 2 3 4 5 6 7 8 9 10 11 12 13 14
   |     @Test     void getByIfNull() {         UserQuery userQuery = new UserQuery();         userQuery.setLowerAge(20).setUpperAge(40);         LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();         if (userQuery.getLowerAge() != null) {             lambdaQueryWrapper.gt(User::getAge, userQuery.getLowerAge());         }         if (userQuery.getUpperAge() != null) {             lambdaQueryWrapper.lt(User::getAge, userQuery.getUpperAge());         }         List<User> users = userMapper.selectList(lambdaQueryWrapper);         users.forEach(user -> logger.info("用户:" + user));     }
   | 
 
方法二:条件参数控制

1 2 3 4 5 6 7 8 9 10
   | @Test void getByCondition() {     UserQuery userQuery = new UserQuery();     userQuery.setLowerAge(20).setUpperAge(40);     LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();     lambdaQueryWrapper.gt(userQuery.getLowerAge() !=null, User::getAge, userQuery.getLowerAge())             .lt(userQuery.getUpperAge() != null, User::getAge, userQuery.getUpperAge());     List<User> users = userMapper.selectList(lambdaQueryWrapper);     users.forEach(user -> logger.info("用户:" + user)); }
   | 
 
查询投影
情况一:LambdaQueryWrapper

情况二:QueryWrapper

测试


1 2 3 4 5 6 7 8 9 10 11
   |  @Test void getTotal(){     QueryWrapper<User> queryWrapper = new QueryWrapper<User>();          queryWrapper.select("count(*) as total", "age");          queryWrapper.groupBy("age");     List<Map<String, Object>> map = userMapper.selectMaps(queryWrapper);     System.out.println(map); }
 
  | 
 

查询条件设置
API查询地址:https://baomidou.com/pages/10c804/#nested
等值查询

1 2 3 4 5 6 7 8 9
   |  @Test void login() {          LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();     lambdaQueryWrapper.eq(User::getName, "xiaomi").eq(User::getPassword, "123456");     User user = userMapper.selectOne(lambdaQueryWrapper);     System.out.println(user); }
 
  | 
 

范围查询

1 2 3 4 5 6 7 8 9 10
   |  @Test void between() {     LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();     lambdaQueryWrapper.between(User::getAge, 20, 40);     List<User> users = userMapper.selectList(lambdaQueryWrapper);     users.forEach(user -> {         System.out.println(user);     }); }
 
  | 
 

模糊匹配

1 2 3 4 5 6 7 8
   | // 模糊匹配 @Test void like() {     LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();     lambdaQueryWrapper.like(User::getName, "xiao");     List<User> users = userMapper.selectList(lambdaQueryWrapper);     users.forEach(System.out::println); }
   | 
 

映射匹配
数据库

实体类映射

测试

DML
Insert
id生成策略控制
场景分析


@TableId()注释

测试

全局配置

1 2 3 4 5 6 7 8
   | mybatis-plus:   configuration:     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl    global-config:     banner: false       db-config:       id-type: assign_id        table-prefix: ums_ 
   | 
 

Delete
批量删除

1 2 3 4 5 6 7
   | @Test void batchDelete() {          List<Long> ids = Arrays.asList(new Long[]{1544234982638149633L, 1544235553495506945L});          Integer count = userMapper.deleteBatchIds(ids); }
   | 
 

逻辑删除
数据库添加逻辑删除字段

实体类添加字段并设定逻辑删除标记字段

测试

1 2 3 4 5
   |  @Test void deleteByLogic() {     Integer count = userMapper.deleteById(1L); }
 
  | 
 




全局配置

Update
乐观锁
当更新一条记录时,希望这条记录没有被别人更新
乐观锁的实现方式:
- 取出记录时,获取当前version
 
- 更新时,带上这个version
 
- 执行更新时,set version = newVersion where version = oldVersion 
 
- 如果version不对,更新失败
 
数据库添加字段

实体类添加字段

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | @Data @AllArgsConstructor @NoArgsConstructor @Builder @Accessors(chain = true) @EqualsAndHashCode(callSuper = false)
  public class User {
      private Long id;     private String name;     @TableField(value = "pwd", select = false)     private String password;     private Integer age;     private String tel;     @TableField(exist = false)     private Integer online;     @TableField(value = "is_delete")     @TableLogic(value = "0", delval = "1")     private Integer deleted;     @Version     private Integer version; }
   | 
 
添加配置

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | 
 
 
  @Configuration public class MyBatisPlusConfig {     @Bean     public MybatisPlusInterceptor mybatisPlusInterceptor() {                  MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();                  mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());                  mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());         return mybatisPlusInterceptor;     } }
 
 
  | 
 
测试

1 2 3 4 5 6 7
   |  @Test void update() {     User user = new User().setId(3L).setName("aa")             .setVersion(1);      Integer count = userMapper.updateById(user); }
 
  | 
 

并发测试

1 2 3 4 5 6 7 8 9 10
   |  @Test void updateByConcurrency() {     User user1 = userMapper.selectById(3L);     User user2 = userMapper.selectById(3L);     user1.setName("aa");     Integer count1 = userMapper.updateById(user1);     user2.setName("bb");     Integer count2 = userMapper.updateById(user2); }
 
  | 
 


代码生成器
导入依赖

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
   | <dependencies>     <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>     <dependency>         <groupId>mysql</groupId>         <artifactId>mysql-connector-java</artifactId>         <scope>runtime</scope>     </dependency>     <dependency>         <groupId>com.alibaba</groupId>         <artifactId>druid</artifactId>         <version>1.2.11</version>     </dependency>     <dependency>         <groupId>com.baomidou</groupId>         <artifactId>mybatis-plus-boot-starter</artifactId>         <version>3.4.1</version>     </dependency>     <dependency>         <groupId>org.projectlombok</groupId>         <artifactId>lombok</artifactId>     </dependency>     <dependency>         <groupId>org.slf4j</groupId>         <artifactId>slf4j-api</artifactId>     </dependency>          <dependency>         <groupId>com.baomidou</groupId>         <artifactId>mybatis-plus-generator</artifactId>         <version>3.4.1</version>     </dependency>          <dependency>         <groupId>org.apache.velocity</groupId>         <artifactId>velocity-engine-core</artifactId>         <version>2.3</version>     </dependency> </dependencies>
   | 
 
添加代码自动生成器类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
   | 
 
 
  public class Generator {     public static void main(String[] args) {                  AutoGenerator autoGenerator = new AutoGenerator();                  DataSourceConfig dataSourceConfig = new DataSourceConfig();         dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver");         dataSourceConfig.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");         dataSourceConfig.setUsername("root");         dataSourceConfig.setPassword("13851176590++");         autoGenerator.setDataSource(dataSourceConfig);                  GlobalConfig globalConfig = new GlobalConfig();         globalConfig.setOutputDir("D:\\Users\\YuanJW\\Desktop\\Java Learn\\MyBatis-Plus\\MyBatisPlusGenerator\\src\\main\\java")                   .setOpen(false)                 .setAuthor("xiaoyuanjw")                 .setFileOverride(true)                 .setMapperName("%sMapper")                 .setIdType(IdType.ASSIGN_ID);         autoGenerator.setGlobalConfig(globalConfig);                  PackageConfig packageConfig = new PackageConfig();         packageConfig.setParent("com.example.demo")                 .setEntity("domain")                 .setMapper("dao");         autoGenerator.setPackageInfo(packageConfig);                  StrategyConfig strategyConfig = new StrategyConfig();         strategyConfig.setInclude("ums_user")                 .setTablePrefix("ums_")                 .setRestControllerStyle(true)                 .setVersionFieldName("version")                 .setLogicDeleteFieldName("deleted")                 .setEntityLombokModel(true);         autoGenerator.setStrategy(strategyConfig);                  autoGenerator.execute();     } }
 
  | 
 
生成结构
