Mybatis-plus使用详解

一、初识

注:
1、此文基于springboot2.2.5版本,使用Mybatis-Plus3.0.5
2、使用该版本的原因是可以感受Mybatis-Plus的原理,再高版本由注解即可完成,不宜与学习。

1、简洁

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

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

二、使用步骤

1、创建一个springboot项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2、添加mybatis-plus依赖
<!-- 导入mybatis-plus依赖-->
<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.0.5</version>
</dependency>
3、添加配置文件配置数据源

注:
1、官网推荐使用yml配置文件,创建application.yml,添加数据源配置
2、通过源码分析springboot2.xx以上的版本默认mysql为8.xx版本,8.xx以上的版本url需要加上时区serverTimezone
在这里插入图片描述

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnincode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123456
4、application.properties配置日志

用来打印sql执行情况

#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
5、创建数据库

1、创建数据库mybtis_plus
2、根据官网给出的样例创建User表,插入数据

6、编写pojo
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private int age;
    private String email;
}
7、编写dao

1、创建UserMapper 继承BaseMapper

@Repository
public interface UserMapper extends BaseMapper<User> {
}

2、通过源码分析BaseMapper提供了一系列简化的操作,直接调用即可
在这里插入图片描述

8、启动类添加扫描dao
@SpringBootApplication
@MapperScan("com.yyrifle.springbootmp.dao")
public class SpringbootMpApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringbootMpApplication.class, args);
	}

}
9、测试
@SpringBootTest
class SpringbootMpApplicationTests {
	@Autowired
	private UserMapper userMapper;
	@Test
	void contextLoads() {
		List<User> users = userMapper.selectList(null);
		users.forEach(System.out::println);
	}

}

结果:
在这里插入图片描述
完成!!

三、插入策略

1、源码分析主键生成策列

关于id生成的一些策略(引用别人博客,点击进入)
在这里插入图片描述

2、源码刨析主键生成策列

1、源码刨析

public enum IdType { 
// 自增 (需要保证数据库是自增的,IdType设置为AUTO)
AUTO(0), 
// 手动输入 
NONE(1), 
INPUT(2), 
// 唯一id生成器 雪花算法,默认为此算法
ID_WORKER(3), 
// uuid 
UUID(4), 
// 唯一id生成器(字符串类型)  雪花算法,转为字符串
ID_WORKER_STR(5); 
}

2、默认
在这里插入图片描述
3、使用方法:添加 @TableId注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

	//默认为雪花算法
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private int age;
    private String email;
}

4、什么是雪花算法
在这里插入图片描述

四、更新策略

说明:
1、两种级别:数据库级别,代码级别
2、阿里巴巴规范中,表结构必备三个字段 id、gmt_create、gmt_update 。
在这里插入图片描述

1、数据库级别(不推荐 影响效率)

1、新增两个时间字段
在这里插入图片描述
2、更新
在这里插入图片描述
3、注:高版本的sqlyong表结构里有个“更新”列,如果有则给update_time勾选,代表更新操作的时候自动更新时间为当前时间,如果低版本的没有使用语句更新

ALTER TABLE USER MODIFY update_time TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间';
2、代码级别(建议,项目统一处理时间)

1、删除表结构默认值
在这里插入图片描述
2、编写实体类对应的注解

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private int age;
    private String email;
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date  updateTime;
}

3、编写注意的处理器

public class MyMetaObjectHandler implements MetaObjectHandler{
    //表示插入的时候自动更新字段为当前时间
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("creatTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //表示更新的时候自动更新更新时间为当前时间
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

4、执行测试
在这里插入图片描述
在这里插入图片描述

四、乐观锁

1、什么是乐观锁,悲观锁

1、乐观锁:非常乐观,无论什么操作都不加锁。(思考:分布式下如何处理冲突问题呢?)
2、悲观锁:非常悲观,无论什么操作都加索。
思考解答:
分布式下解决冲突的方式就是增加一个乐观锁字段即可(version)
目的是为了确保当要更新一条记录的时候,希望这条记录没有被其他线程更新。

2、乐观锁实现方式
  1. 查询记录时,获取当前版本(version)
  2. 更新时带上当前版本(version)
# 线程一:
# 获取当前version , select version = 1
# 被线程2插队
# 线程一:
# 获取 version select version = 1
# 更新 version update set version  = 2 wehre version = 1
# 线程一更新 version失败  update set version  = 2 wehre version = 1
  1. 执行更新时,set version = newVersion where version = oldVersion
  2. 如果version 不对 ,就更新失败
3、MP支持乐观锁

1、添加version
在这里插入图片描述
2、添加@version注解到字段上

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private int age;
    private String email;
    //乐观锁直接  必须要
    @Version
    private int version;
    private Date createTime;
    private Date updateTime;
}

3、添加乐观锁插件 ,注入别人写好的bean即可

package com.yyrifle.springbootmp.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MPconfig {

    //根据官网 注入别人写好的插件处理器即可
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return  new OptimisticLockerInterceptor();
    }
}

4、测试
成功:
在这里插入图片描述
失败:
在这里插入图片描述
在这里插入图片描述

五、查询策略

1、条件查询

//查询
	@Test
	void testSelectById() {
		User user = userMapper.selectById(1266999282910642178L);
		System.out.println(user);
	}
	@Test
	void testSelectList() {
		List<User> users = userMapper.selectList(null);
		users.forEach(System.out::println);
	}
	@Test
	void testSelectBatchIds() {
		List<User> users = userMapper.selectBatchIds(Arrays.asList(1,2,3));
		users.forEach(System.out::println);
	}
	@Test
	void testSelectCount() {
		Integer integer = userMapper.selectCount(null);
		System.out.println(integer);
	}
	@Test
	void testSelectByMap() {
		HashMap<String,Object> map = new HashMap<>();
		map.put("name","Y总");
		List<User> users = userMapper.selectByMap(map);
		users.forEach(System.out::println);
	}

2、分页查询 MP内置分页插件 需要先引入插件

@Configuration
public class MPconfig {

    //根据官网 注入别人写好的插件处理器即可
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return  new OptimisticLockerInterceptor();
    }

    //引入分页查询
    @EnableTransactionManagement
    @Configuration
    @MapperScan("com.baomidou.cloud.service.*.mapper*")
    public class MybatisPlusConfig {

        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
            return paginationInterceptor;
        }
    }
}

3、编写测试

	//分页查询   MP内置分页插件  以后做分页使用Page对象即可
	@Test
	void testSelectMapsPage() {
		Page page = new Page(0,2);
		userMapper.selectMapsPage(page, null);
		page.getRecords().forEach(System.out::println);
		System.out.println(page.getCurrent());//当前第几页
		System.out.println(page.getSize());//一页多少条
		System.out.println(page.getTotal());//总条数
		System.out.println(page.hasNext());//是否有下页
		System.out.println(page.hasPrevious());//是否有上页
	}

4、结果
在这里插入图片描述

六、删除策略

1、物理删除

在这里插入图片描述

2、逻辑删除

1、添加删除字段
在这里插入图片描述
2、实体类字段上加上@TableLogic注解

  @TableLogic
  private int deleted;

3、加入配置(如果你的默认值和mp默认的一样,该配置可无):

# 配置删除 删除为1  没有删除为0
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0

4、引入删除插件(3.1.1以上不再需要这一步)

   //逻辑删除插件
    @Bean
    public ISqlInjector iSqlInjector() {

        return new LogicSqlInjector();
    }

5、测试在这里插入图片描述

六、性能分析

1、目的:在开发的时候排除慢sql!
2、引入插件性能分析插件

    //性能分析插件
    /**
     * SQL执行效率插件
     */
    @Bean
    @Profile({"dev","test"})// 设置 dev test 环境开启
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor =  new PerformanceInterceptor();
        //设置最大sql执行时间
        performanceInterceptor.setMaxTime(200);
        //format SQL SQL是否格式化,默认false
        //performanceInterceptor.setFormat(true);
        return  performanceInterceptor;
    }

3、配置多环境,激活开发环境
在这里插入图片描述4、测试
在这里插入图片描述
5、注意!参数说明
参数:maxTime SQL 执行最大时长,超过自动停止运行,有助于发现问题。
参数:format SQL SQL是否格式化,默认false。
该插件只用于开发环境,不建议生产环境使用


版权声明:本文为qq_40765573原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。