史上最全的MybatisPlus学习教程从入门到精通

2024-09-01 00:28

本文主要是介绍史上最全的MybatisPlus学习教程从入门到精通,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、MybatisPlus是什么

1.1 MyBatis-Plus简介

MyBatis-Plus(简称MP)是一个MyBatis的增强工具,它在MyBatis的基础上进行了增强,但并没有改变原有的MyBatis框架。MyBatis-Plus的主要目标是简化开发和提高开发效率。它提供了诸如分页插件、代码生成器、注解支持等丰富的功能特性,使得开发者在使用MyBatis时能够更加便捷和高效。MyBatis-Plus的设计理念是“无侵入”,即引入它不会对现有工程产生影响,同时它还具备损耗小、CRUD操作强大、支持Lambda表达式调用等优点。

1.2 为什么会出现MyBatis-Plus

MyBatis-Plus框架的出现主要是为了解决MyBatis在使用过程中存在的一些不足。尽管MyBatis是一个非常优秀的持久层框架,它支持自定义SQL、存储过程以及高级映射,但它在一些简单的单表操作上并没有提供一套现成的通用增删改查(CRUD)操作,这就需要开发者自己去编写,这样不仅繁琐而且浪费时间。此外,MyBatis自身的功能不够丰富,例如它没有自带分页插件、没有分布式ID支持等。因此,MyBatis-Plus应运而生,它旨在提供更加丰富的功能特性,简化开发流程,提高开发效率。

1.3 MyBatis-Plus的特点

以下特点引用自MP官网:简介 | MyBatis-Plus (baomidou.com)

特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

二、MybatisPlus快速入门

2.1 创建mp_test数据库

2.2 新建user表

CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
);

2.3 初始化user表

INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');

2.4 初始化项目

初始化一个新的springboot项目

2.5 添加mybatisplus依赖

修改pom.xml文件,添加如下依赖

        <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency>

2.6 修改配置文件

修改application.yml文件,当然在初始化的情况下是叫做application.propertis

# DataSource Config
spring:datasource:# 密码和用户名需要修改为自己的username: rootpassword: rooturl: jdbc:mysql://localhost:3306/mp_test?userUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.cj.jdbc.Driver

2.7 编码

1.创建实体类User

package com.ltx.mybatisplus_test.demos;import lombok.Data;/*** @author 罗添煦*/
@Data
public class User {private Long id;private String name;private Integer age;private String email;
}

2.创建UserMapper接口

在这个接口中你就可以看见mybaitsplus的魔力了,只需要extends接口就可以完成所有的crud操作。

package com.ltx.mybatisplus_test.demos.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ltx.mybatisplus_test.demos.User;
import org.apache.ibatis.annotations.Mapper;//再对应的mapper上面实现基本的接口 BaseMapper
@Mapper
public interface UserMapper extends BaseMapper<User> {//所有的CRUD都已经完成//不需要像以前一样配置一大堆文件:pojo-dao(连接mybatis,配置mapper.xml文件)==>service-controller
}

 3.扫描Mapper

package com.ltx.mybatisplus_test;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
@MapperScan("com.ltx.mybatisplus_test.demos.mapper")
public class MybatisPlusTestApplication {public static void main(String[] args) {SpringApplication.run(MybatisPlusTestApplication.class, args);}}

有了MapperScan注解就可以不是用mapper去扫描接口但是还是建议养成在每个mapper上加上@Mapper的注解。 

2.8 测试使用

package com.ltx.mybatisplus_test;import com.ltx.mybatisplus_test.demos.User;
import com.ltx.mybatisplus_test.demos.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;@SpringBootTest
class MybatisPlusTestApplicationTests {@Autowiredprivate UserMapper userMapper;@Testvoid TestSelect() {List<User> users = userMapper.selectList(null);users.forEach(System.out::println);System.out.println("我修改咯");}}

结果如下所示就代表你已经成功的入门了mybatisplus了

三、配置日志

所有的SQL都是不可见的,所以在后台是希望看到SQL是怎么执行的,就必须要配置日志。

在.yml配置文件中配置日志:

#配置日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

输出sql日志如下所示: 

四、增删改查操作

4.1 新增操作

    @Testvoid TestInsert() {User user = new User();user.setName("ltx");user.setAge(666);user.setEmail("1429189960@gmail.com");int result = userMapper.insert(user);System.out.println("result:" + result);System.out.println("user:" + user);}

 结果如下所示:

对于上面的结果我们可以看到,我们其实没有指定id的值,但是为什么在插入的时候自动的帮我们加上了id呢。

4.2 自定义id生成器

在复杂分布式系统中,往往需要大量的数据和消息进行唯一标识。比如支付宝每一个账号在数据库分表后都需要有一个唯一ID做标识。此时一个能够生成全局唯一ID的系统是非常必要的。

所以全局唯一ID需要有如下特征:

  1. 全局唯一性:确保生成的ID在整个系统中是独一无二的,避免任何重复或冲突。
  2. 趋势有序性:某些场景下,ID需要大体按照时间顺序生成,这样可以在物理存储上以这个字段排序,提高查询效率。
  3. 单调递增:在某些特殊需求下,如事务版本号、消息队列等,需要保证ID的递增性。
  4. 高可用性:ID生成系统需要保证在任何时候都能稳定地生成ID,不能有单点故障

我们可以通过@TableId注解来查看有哪些主键的自动生成策略

package com.ltx.mybatisplus_test.demos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;/*** @author 罗添煦*/
@Data
public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;
}

我们点入IdType查看自动生成策略

@Getter
public enum IdType {/*** 数据库ID自增* <p>该类型请确保数据库设置了 ID自增 否则无效</p>*/AUTO(0),/*** 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)*/NONE(1),/*** 用户输入ID* <p>该类型可以通过自己注册自动填充插件进行填充</p>*/INPUT(2),
​/* 以下3种类型、只有当插入对象ID 为空,才自动填充。 *//*** 分配ID (主键类型为number或string),* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(雪花算法)** @since 3.3.0*/ASSIGN_ID(3),/*** 分配UUID (主键类型为 string)* 默认实现类 {@link com.baomidou.mybatisplus.core.incrementer.DefaultIdentifierGenerator}(UUID.replace("-",""))*/ASSIGN_UUID(4);
​private final int key;
​IdType(int key) {this.key = key;}
}   

MyBatis-Plus 提供了灵活的自定义ID生成器功能,允许开发者根据业务需求定制ID生成策略。从3.3.0版本开始,默认使用雪花算法结合不含中划线的UUID作为ID生成方式。

下面我具体说一下UUID和雪花算法的实现原理

4.2.1 UUID

UUID(Universally Unique Identifier,通用唯一识别码)是一种标准化的唯一性标识符,用于在分布式系统中无需中央协调就能保证唯一性。UUID通常表示为一个32位的16进制数字,按照8-4-4-4-12的格式分为五部分,形成一个36个字符长度的字符串。

uuid有多个版本的生成

  • 版本1:基于时间的UUID,结合时间戳和机器的MAC地址。
  • 版本2:基于分布式系统的安全UUID,使用POSIX UID/GID。
  • 版本3和版本5:基于名字空间的UUID,通过散列算法生成。
  • 版本4:基于随机数的UUID。

优点:

  1. 全局唯一性:UUID的设计确保了在全局范围内的唯一性,减少了ID冲突的可能性。
  2. 去中心化生成:不需要中央服务器或服务来生成ID,适合分布式系统。
  3. 高性能:本地生成,没有网络请求的开销,可以快速生成。
  4. 简单易用:大多数编程语言提供了生成UUID的库或函数,易于集成到应用程序中。
  5. 安全性:某些UUID版本(如版本4)不包含任何可识别的信息,增加了隐私性。
  6. 时间戳基础:某些UUID版本(如版本1)包含时间戳,可以间接反映生成时间。

缺点:

  1. 存储空间:UUID通常由36个字符组成,相比于其他类型的ID(如自增ID),占用更多的存储空间。
  2. 性能问题:由于UUID的无序性,作为数据库主键时可能影响索引性能,特别是在写入密集型的应用中。
  3. 传输效率:较长的字符串长度可能导致在网络传输时效率较低。
  4. 可读性差:UUID是随机的16进制数字符串,不具备可读性,不便于人工解读和记录。
  5. 信息泄露:某些UUID版本可能会暴露生成它的机器的某些信息,如版本1的MAC地址。
  6. 单调性问题:UUID不保证生成顺序,对于需要ID单调递增的场景(如某些数据库的自增主键)不适用。
  7. 版本依赖:UUID有多个版本,不同版本有不同的生成规则和特性,选择合适的版本可能需要额外考虑。

4.2.2 雪花算法

这种方案大致来说是一种以划分命名空间(UUID也算,由于比较常见,所以单独分析)来生成ID的一种算法,这种方案把64-bit分别划分成多段,分开来标示机器、时间等,比如在snowflake中的64-bit分别表示如下图(图片来自网络)所示:

41-bit的时间可以表示(1L<<41)/(1000L360024*365)=69年的时间,10-bit机器可以分别表示1024台机器。如果我们对IDC划分有需求,还可以将10-bit分5-bit给IDC,分5-bit给工作机器。这样就可以表示32个IDC,每个IDC下可以有32台机器,可以根据自身需求定义。12个自增序列号可以表示2^12个ID,理论上snowflake方案的QPS约为409.6w/s,这种分配方式可以保证在任何一个IDC的任何一台机器在任意毫秒内生成的ID都是不同的。

4.2 删除操作

4.2.1 删除单条数据

    @Testvoid TestDelete() {User user = new User();user.setId(1L);userMapper.deleteById(user);}

结果如下所示:

 这个地方我们需要注意到的是我们需要传入的是一个User对象,而不是传入一个Id

 4.2.2 批量删除

    /*** 批量删除*/@Testvoid TestDeleteList(){userMapper.deleteBatchIds(Arrays.asList(4L,5L));}

结果如下所示:

4.2.3 条件删除

    /*** 根据map删除*/@Testvoid TestDeleteMap(){Map<String, Object> map = new HashMap<>();map.put("name","ltx");userMapper.deleteByMap(map);}

结果如下所示:

 所以我们可以通过map进行不是id外的参数进行删除,也可以在map中指定多个参数进行删除。

4.2.4 逻辑删除

在很多的情况下用户删除数据不可以被删除,比如博客被删除就是作为逻辑删除不会被真的删除可能用户会要恢复数据的情况出现。

物理删除:从数据库中直接删除

逻辑删除:在数据库中没有被删除,而是通过一个变量来让它失效。 deleted=0 ==》deleted=1

 1.在数据库中新增逻辑删除字段

2.实体类修改,并加上@TableLogic注解

package com.ltx.mybatisplus_test.demos;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;/*** @author 罗添煦*/
@Data
public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;@TableLogicprivate Integer delete;
}

3.修改yml文件

#配置日志
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

 4.测试逻辑删除

结果如下所示:

通过结果我们可以看到逻辑删除实质上就是update(修改)语句,将deleted字段从1修改为0。

然后我们可以进行一个查询操作看看mp是怎么做到的逻辑删除

我们可以看到在查询的时候mp自动帮我们拼接上了deleted=0,所以也就没有抽查到数据。

4.3 修改操作

    /*** 更新*/@Testvoid TestUpdate(){User user = new User();user.setId(1829036034502017025L);user.setName("ltx");userMapper.updateById(user);}

结果如下所示:

4.4 查询操作

当然在查询操作之前你需要知道的是很有可能查询操作你会有和我不一样的id数据这个时候你可以自己加上或者改成自己的数据都是可以的。

4.4.1 通过ID查询

    /***通过id查询*/@Testvoid TestSelectById(){User user = userMapper.selectById(1829036034502017025L);System.out.println(user);}

结果如下所示

4.4.2 批量查询

/*** 批量查询*/@Testvoid TestSelectList(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1L,2L));users.forEach(System.out::println);}

结果如下所示: 

4.4.3 条件查询

    /*** 条件查询*/@Testvoid TestSelectMap(){Map<String, Object> map = new HashMap<>();map.put("name","ltx");map.put("age",666);userMapper.selectByMap(map);}

条件查询和我们前面介绍到的条件删除是一样的逻辑就不再这个地方过多的介绍了。

结果如下所示:

4.4.4 分页查询

mysql原生使用Limit进行分页查询

LIMIT offset, count
  • offset:这是从结果集的哪一条记录开始返回。它是一个整数,表示从查询结果的第一条记录开始计数的偏移量。如果设置为 0,则从第一条记录开始返回。如果设置为 10,则从第 11 条记录开始返回,因为 SQL 计数通常是从 0 开始的。
  • count:这是返回记录的最大数量。它也是一个整数,表示从 offset 指定的位置开始,最多返回多少条记录。。

MyBatis-Plus 的分页插件 PaginationInnerInterceptor 提供了强大的分页功能,支持多种数据库,使得分页查询变得简单高效。

配置方法

在 Spring Boot 项目中,你可以通过 Java 配置来添加分页插件:

@Configuration
public class MybatisPlusConfig {/*** 添加分页插件*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加// 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbTypereturn interceptor;}
}

测试分页组件

    /*** 分页查询*/@Testvoid TestSelectPage(){// 两个参数:current的值默认是1,从1开始,不是0。size是每一页的条数。Page<User> page = new Page<>(1, 4);userMapper.selectPage(page,null);page.getRecords().forEach(System.out::println);}

 结果如下所示:

其实分页查询插件在底层还是使用的是limit进行查询 

Page中的其他方法

//page的其他方法
System.out.println("当前页:" + page.getCurrent());
System.out.println("总页数:" + page.getPages());
System.out.println("记录数:" + page.getTotal());
System.out.println("是否有上一页:" + page.hasPrevious());
System.out.println("是否有下一页:" + page.hasNext());

五、自动填充

在常用业务中有些属性需要配置一些默认值,MyBatis-Plus提供了实现此功能的插件,也就是自动填充功能。比如创建时间、修改时间这些操作一般都是自动化完成的,是不用去手动更新的。

5.1 数据库层面

1.添加字段

在数据库中添加create_time和update_time字段并且设置默认值        

2.实体类同步

    private Date createTime;private Date updateTime;

3.代码测试

sql语句中并没有把create_time和update_time插入到数据库中,我们可以查看数据库中的数据。

4.数据库查看

我们可以看到插入的数据自动的帮我们把create_time和uadate_time给我们赋值了

5.2 代码层面

1.修改数据库,删除默认值

2.注解填充字段 @TableField(.. fill = FieldFill.INSERT) 

    @TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;

3.自定义实现类 MyMetaObjectHandler 处理这个注解

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("开始插入填充...");this.strictInsertFill(metaObject, "create_time", LocalDateTime.class, LocalDateTime.now());}@Overridepublic void updateFill(MetaObject metaObject) {log.info("开始更新填充...");this.strictUpdateFill(metaObject, "update_time", LocalDateTime.class, LocalDateTime.now());}
}

六、条件构造器

MyBatis-Plus 提供了一套强大的条件构造器(Wrapper),用于构建复杂的数据库查询条件。Wrapper 类允许开发者以链式调用的方式构造查询条件,无需编写繁琐的 SQL 语句,从而提高开发效率并减少 SQL 注入的风险。

下面我举例几个简单的test,大家如果有兴趣的话可以去官网看更多的使用:

1、查询name、邮箱不为空且年龄大于等于20的用户

@Test
void WrapperTest(){//查询name、邮箱不为空且年龄大于等于20的用户QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name").isNotNull("email").ge("age",12);userMapper.selectList(wrapper).forEach(System.out::println);
}

结果如下所示:

2、查询姓名为小罗的用户

    @Testvoid WrapperTest2(){//查询姓名叫做“小罗”用户QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name","小罗");System.out.println(userMapper.selectOne(wrapper));}

结果如下所示:

 

3、查询年龄在19-28之间的用户

    @Testvoid WrapperTest3(){//查询年龄在19-28之间的用户QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.between("age",19,28);Long count = userMapper.selectCount(wrapper);//查询结果数System.out.println(count);}

结果如下所示: 

4、模糊查询

    @Testvoid WrapperTest4(){QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.notLike("name","l")    //查询姓名中不包含a的用户.likeRight("email","1");   //左和右是代表%的位置 两边都要匹配则为%e%,这里是email以t开头的 t%List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);maps.forEach(System.out::println);}

结果如下所示: 

5、通过ID进行排序

@Test
void WrapperTest5(){//通过ID进行排序QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.orderByAsc("id");   //通过id升序List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);
}

结果如下所示:

七、乐观锁和悲观锁

7.1 什么是乐观锁和悲观锁

乐观锁:十分乐观,认为不会出现问题,无论干什么都不会去上锁,如果出现问题,就再次更新测试值

乐观锁是对于数据冲突保持一种乐观态度,操作数据时不会对操作的数据进行加锁(这使得多个任务可以并行的对数据进行操作),只有到数据提交的时候才通过一种机制来验证数据是否存在冲突(一般实现方式是通过加版本号然后进行版本号的对比方式实现);

特点:乐观锁是一种并发类型的锁,其本身不对数据进行加锁而是通过业务实现锁的功能,不对数据进行加锁就意味着允许多个请求同时访问数据,同时也省掉了对数据加锁和解锁的过程,这种方式因为节省了悲观锁加锁的操作,所以可以一定程度的的提高操作的性能,不过在并发非常高的情况下,会导致大量的请求冲突,冲突导致大部分操作无功而返而浪费资源,所以在高并发的场景下,乐观锁的性能却反而不如悲观锁。

悲观锁:十分悲观,认为总是出现问题,无论干什么都会上锁,再去操作

悲观锁是基于一种悲观的态度类来防止一切数据冲突,它是以一种预防的姿态在修改数据之前把数据锁住,然后再对数据进行读写,在它释放锁之前任何人都不能对其数据进行操作,直到前面一个人把锁释放后下一个人数据加锁才可对数据进行加锁,然后才可以对数据进行操作,一般数据库本身锁的机制都是基于悲观锁的机制实现的;

特点:可以完全保证数据的独占性和正确性,因为每次请求都会先对数据进行加锁, 然后进行数据操作,最后再解锁,而加锁释放锁的过程会造成消耗,所以性能不高;

7.2 配置乐观锁

1 在数据库中增加version字段

2 同步到实体类

在实体类中添加version字段并且加上@Version注解

    @Versionprivate Integer version;

3 配置插件

@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}

4 测试使用

测试这个地方就不测试成功的情况,我们直接测试失败的情况,模拟两个线程同时修改数据,这个时候就会到后面修改数据的线程无法修改成功。

    @Testvoid testOptimisticLocker_failure() {//模拟多线程实现插队效果//线程1User user = userMapper.selectById(1L);user.setName("罗");user.setAge(21);//线程2User user2 = userMapper.selectById(1L);user2.setName("小罗");user2.setAge(19);userMapper.updateById(user2);   //在这里插队userMapper.updateById(user);    //如果没有乐观锁就会覆盖插队线程的值}

八、SQL分析与打印

8.1 引入依赖

首先,需要在项目中引入p6spy依赖。

<dependency><groupId>p6spy</groupId><artifactId>p6spy</artifactId><version>3.9.1</version>
</dependency>

8.2 配置

修改application.yml配置文件

spring:datasource:driver-class-name: com.p6spy.engine.spy.P6SpyDriverurl: jdbc:p6spy:h2:mem:test# 其他数据库配置...

注意这个地方我们需要修改数据库的驱动名和 url 前缀为 jdbc:p6spy 跟着冒号为对应数据库连接地址。

spy.properties

新建文件放在resources目录下,p6spy的配置文件spy.properties包含了多个配置项,以下是一些关键配置的示例:

# 模块列表,根据版本选择合适的配置
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory# 自定义日志格式
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger# 日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger# 取消JDBC驱动注册
deregisterdrivers=true# 使用前缀
useprefix=true# 排除的日志类别
excludecategories=info,debug,result,commit,resultset# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss# 实际驱动列表
# driverlist=org.h2.Driver# 开启慢SQL记录
outagedetection=true# 慢SQL记录标准(单位:秒)
outagedetectioninterval=2

8.3测试

我们可以看到下面的结果中帮我们统计了执行sql语句的时间。

九、代码生成器

代码生成器可以参考我的另一篇博客

MyBatis-Plus代码生成器(最新版适合新手跟做)-CSDN博客 

这篇关于史上最全的MybatisPlus学习教程从入门到精通的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1125421

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学