速通 MyBatis-Plus , 深入浅出 实战演示

目录

速通 MyBatis-Plus , 深入浅出 实战演示

1、简单介绍

MyBatis-Plus 官网

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

2、项目演示(CRUD操作及其扩展延伸的操作)

2-1:简单通过 MyBatis-Plus 查询单表所有数据

2-1-1:创建项目

我这边先创建一个 springboot 项目,按个人爱好取名。

2-1-2:添加依赖

目前就先添加 mybatis-plus插件依赖、mysql数据库驱动依赖 和 lombok 依赖。

官网的依赖如图:

java 复制代码
        <!-- mybatis-plus插件依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

        <!--  mysql数据库驱动依赖  -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
2-1-3:Navicat 添加数据库并初始化数据

这里的创建基础数据的 SQL 可以直接从官网的 快速开始 那里拷贝。

sql 复制代码
DROP TABLE IF EXISTS `user`;

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

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-1-4:简单创建一个 User 实体类
java 复制代码
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
2-1-5:创建 Mapper 接口(相当dao接口)

如图,只需简单继承 MyBatis-Plus 的 BaseMapper 接口即可,暂时无需自己写查询方法。

java 复制代码
/**
 * 继承 mybatisplus 的 BaseMapper 接口,就可以用到 mybatisplus 的功能了。
 * BaseMapper<User> 的 User 表示这个 UserMapper 接口操作的是 User 这个实体类
*/
//@Repository 也可以用这个注解代表这个接口是持久层
@Mapper
public interface UserMapper extends BaseMapper<User> {
    //不需要像以前一样写各种查询方法了,继承这个BaseMapper,已经帮我们把crud编写完成了
}
2-1-6:配置文件添加连接数据库的配置
java 复制代码
spring.application.name=mybatis-plus

# 连接数据库
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2-1-7:IDEA 添加 MySQL
2-1-8:启动类添加 @MapperScan 注解扫描 mapper
2-1-9:简单写个测试,成功查询表中所有数据

查询成功

2-2:配置日志--查看SQL具体执行命令

java 复制代码
# 配置日志-- StdOutImpl 默认的控制台输出
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

如图,配置完就可以在控制台查看 SQL 的执行步骤了。

2-3:插入一条数据--->主键生成策略

Mybatis-Plus 这里简单说成 MP

2-3-1:MP 默认自动生成id ---> 雪花算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。

其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。

如图,使用 Mybatis-Plus 实现出入一条数据,如果我们不指定 id ,那么MP会自动帮我们回填 id ,id 是通过推特的雪花算法实现的。

2-3-2:自增id ---> @TableId(type = IdType.AUTO)

如图,两个条件都满足后,就能实现id的自动递增:

条件1:ID 字段 添加注解:@TableId(type = IdType.AUTO)

条件2:MySQL 的 ID 列,需要勾选上 【自动递增】的选项。

TableId 的一些源码解释:

INPUT 的话,如果我们不手动给对象设置id,会报错

@TableId(type = IdType.INPUT)

private Long id;

注意:如果数据库的【自动递增】选项有勾选上的话,即使插入的对象没有设置id,那么插入的对象的id也是自动递增的。

如果数据库的【自动递增】选项没有勾选上,插入的对象有没有手动填写id,那么就会直接报错。

2-4:更新操作

2-4-1:简单更新操作 --->MP会通过条件自动拼接SQL

我这里修改了年龄和名字这两个字段的数据,可以看出,当该对象需要修改多个字段数据时,那么 MP 会自动帮我们 动态的拼接SQL

只修改单个字段数据的是这样的,对比一下:

2-4-2:自动填充 ---> 【自定义处理类】实现【创建时间、修改时间】的字段的数据自动填充

更新时自动更新一些固定字段(如:创建时间、修改时间 字段)

2-4-2-1:数据库增加 创建时间、修改时间 列

先给数据库表新增几个固定的字段,如 创建时间、修改时间

2-4-2-2:同步 User 实体类的字段 ---> @TableField(fill = FieldFill.INSERT)
2-4-2-3:创建一个处理器类,实现自动填充的功能

通过实现 MetaObjectHandler 接口,重写 insertFill 和 updateFill 方法,实现插入和修改数据时,时间的自动插入和更新。

java 复制代码
//作为组件交给spring容器进行管理--自动填充日期时间的处理器
@Component
@Slf4j
public class createAndUpdateHandler implements MetaObjectHandler {

    /**
     * 插入时的填充策略--根据名字去填充
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("插入数据时自动填充开始.........");
        //参数1:要修改的字段名  参数2:要插入的字段值   参数3:要给哪个数据处理
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
    /**
     * 更新时的填充策略
     */
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("更新数据时自动填充开始.........");
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }
}
2-4-2-4:测试插入和更新

插入一条新数据,插入时间和更新时间正确。

修改一条数据,创建时间不变,修改时间变化,代码正确。

2-5:使用 MyBatis-plus 的乐观锁插件进行演示

2-5-1:官网乐观锁插件代码

官网的乐观锁插件讲解及一些配置插件

乐观锁:简单来说就是十分乐观,它总认为每次修改都不会出现问题,无论干什么都不用上锁,只需要在修改值的时候通过 version 值判断一下,该值是否在修改的过程中被其他线程修改过,如果没有,则修改成功;如果被其他线程修改过了,则重新自旋。

2-5-1:给数据库中的 User 表增加 Version 字段

先把version版本号的默认值设置为1

2-5-2:实体类添加对应的字段
2-5-3:注册 乐观锁 组件 --> 添加配置类 (@Bean对象)

把官网的乐观锁插件代码直接拷贝过来即可。

顺便添加个依赖

java 复制代码
@MapperScan("cn.ljh.mybatisplus.mapper") //扫描功能放在这个配置类即可,不用放在启动类
@EnableTransactionManagement //开启自动管理事务的注解,默认也是开启的
@Configuration //配置类
public class MyBatisPlusConfig{

    //注册乐观锁插件---可去官方文档获取代码
    //这是一个拦截器,在执行所有操作的时候会进行拦截,然后进行自动化的处理
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

依赖:

java 复制代码
        <!-- 使用 MyBatis-plus 乐观锁插件时,需要添加的依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-extension</artifactId>
            <version>3.5.0</version>
        </dependency>
2-5-4:测试类测试乐观锁
测试乐观锁--修改数据成功演示(单线程演示)

这是简单的单线程演示,主要是看 MyBatis-Plus 在执行修改操作时,会自动带上 verison 版本号作条件判断。

测试乐观锁--修改数据失败演示(多线程演示)

可以看出,线程A在执行修改的过程中,线程B 出入进来并先于线程A 完成对 id=1 的数据的修改,因为线程B修改成功,所以该数据的版本号 +1 ,然后线程A再执行修改的时候,发现版本号在修改期间已经发生变化了,所以线程A修改失败,接下来会采用 CAS 自旋锁的方式多次尝试提交。

看下 SQL 的执行日志

2-5-5:简化乐观锁插件的代码

上面的是直接拷贝官网的代码丢进来,因为后面在弄 SQL 性能分析插件的时候,有些依赖出现冲突,所以这里改下看能不能使用。

经过测试类测试,这个简化的代码写法也能实现相同的乐观锁功能(版本号判断)。

java 复制代码
    // 简化下乐观锁插件代码
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        log.info("使用到 MyBatis-Plus 乐观锁插件------------------------------------------------------");
        return new OptimisticLockerInterceptor();
    }

2-6:查询操作

2-6-1:简单的根据id查询数据
2-6-2:测试批量查询

批量查询,MP 这里是通过 IN 关键字来实现的。

java 复制代码
    //测试批量查询
    @Test
    void selectBatchIdsTest(){
        //批量查询
        List<User> users = userMapper.selectBatchIds(Arrays.asList(1L, 2L));
        //遍历循环打印
        users.stream().forEach(System.err::println);
    }
2-6-3:按条件查询之一:使用 Map 操作

注意:使用 Map 操作来查询,SQL 的查询条件是通过 AND 来拼接的。

具体源码:

2-7:分页查询 --->使用MP的分页插件

2-7-1:官网分页插件代码

先看官网的 分页插件

这个是官网提供的分页插件代码:

java 复制代码
@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 添加分页插件
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); // 如果配置多个插件, 切记分页最后添加
        // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
        return interceptor;
    }
}
2-7-2:在配置类添加分页插件(@Bean对象)

直接拷贝过来,我这里修改了方法的名称。

2-7-4:测试类测试分页插件功能
2-7-5:简化分页插件的代码

上面的是直接拷贝官网的代码丢进来,因为后面在弄 SQL 性能分析插件的时候,有些依赖出现冲突,所以这里改下看能不能使用。

经过测试类测试,这个简化的代码写法也能实现相同的分页插件功能。

2-8:物理删除操作

2-8-1:根据 id 删除单条数据
2-8-1:根据 id 批量 删除数据
2-8-1:根据 map 按条件删除

注意:通过 Map 按条件删除数据,动态拼接删除条件用的是 AND 。

2-9:逻辑删除操作

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

逻辑删除:没有删除掉,只是通过修改一个变量让其失效,在查询的时候,带上该变量即可。

2-9-1:User表 添加一个 deleted 字段
2-9-2:实体类 添加一个 deleted 字段(只需添加 @TableLogic 注解即可实现逻辑删除功能)

如图:根据官网提示,给逻辑删除字段添加一个 @TableLogic 注解。

只需要添加 @TableLogic 注解 这个逻辑删除的注解,就可以实现逻辑删除功能了,

经过测试,默认数据未删除时,deleted = 0;

数据已删除时,deleted=1;

2-9-3:配置文件 添加 逻辑删除配置(现在不用添加该配置也可以,仅用于记录)

后面经过测试,即使没有配置这个,也能进行逻辑删除。MP 默认逻辑删除的字段值为 1。

2-9-4:测试逻辑删除

注意:逻辑删除其实就是一个更新deleted字段的更新操作而已。

执行删除,再也不是物理删除了。

该条记录依然存在数据库,只是 deleted 字段的值发生变化而已。

2-9-5:测试查询已经被逻辑删除的数据

如图,数据库表有该条记录,但是没查出来,因为 deleted 字段添加了 @TableLogic 逻辑删除注解后,执行删除时,MP 会自动拼接这个【AND deleted= 0】 的查询条件。

默认 deleted = 0 为【未删除】,deleted = 1为【已删除】

3、SQL性能分析

对于开发中遇到的慢SQL,我们可以使用 MP 提供的性能分析插件来检测,如果该 SQL 执行的时间超过我们设置的时间,就停止运行。

3-1:性能分析插件

作用:SQL 性能分析拦截器,用于输出每条 SQL 语句及其执行时间。

正式开发环境,这个插件就不能部署上去了,只能在开发的时候自己测试使用。

3-1-1:配置类添加性能分析的插件(@Bean对象)
3-1-1:配置文件中配置当前项目开发环境为 dev

注意:因为我这个插件和上面的分页和乐观锁插件的版本起冲突了,先把代码思路写下来,版本冲突后续再解决。

官网的性能插件分析描述

4、条件查询器 Wrapper(实现复杂查询)

官网的条件构造器描述

条件查询

4-1:查询 name、Email 不为空,age >= 20 的用户【 isNotNull、ge 】

isNotNull:不为空

ge:大于等于

java 复制代码
    //查询 name、Email 不为空,age >= 20 的用户
    @Test
    void selectListTest(){
        //封装查询条件的对象
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .isNotNull("name")   //name 不为空
                .isNotNull("email")  //email  不为空
                .ge("age",20);   //age  >= 20
        userMapper.selectList(queryWrapper).forEach(System.err::println);
    }
4-2:查询名字等于 xxx 的一条数据【 eq、 selectOne 】

selectOne:查询一条数据

注意:如果查询一个数据,可能会出现多条数据的话,需要用 List 或者 Map 接收,否则会报错

java 复制代码
    //查询名字等于 xxx 的一条数据
    @Test
    void selectOneTest(){
        //创建封装查询条件的Wrapper对象
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //如果查询一个数据,可能会出现多条数据的话,需要用 List 或者 Map 接收,否则会报错
        queryWrapper.eq("name","老白");
        User user = userMapper.selectOne(queryWrapper);
        System.err.println(user);
    }
4-3:查询名字等于 xxx 的数据,返回多条数据【 eq、 selectList 】

selectList :查询多条数据

查询名字等于 xxx 的数据,会返回多条数据, List 或者 Map 接收

java 复制代码
    //查询名字等于 xxx 的数据,会返回多条数据, List 或者 Map 接收
    @Test
    void selectOnesTest(){
        //创建封装查询条件的Wrapper对象
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name","老紫");
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.err::println);
    }
4-4:查询年龄在 20 - 30 之间的用户 【 between 】

between 是闭区间,age = 20 和 age = 30 都会查出来

java 复制代码
    //查询年龄在 20 - 30 之间的用户
    @Test
    void te(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //是闭区间,age = 20 和 age = 30 都会查出来
        queryWrapper.between("age","20","30");
        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.err::println);
    }
4-5:查询年龄在 20 - 30 之间的用户有几个 【 between 、selectCount 】

selectCount:查询符合条件的数据条数。

java 复制代码
    //查询年龄在 20 - 30 之间的用户有几个
    @Test
    void betweenAndCountTest(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //是闭区间,age = 20 和 age = 30 都会查出来
        queryWrapper.between("age","20","30");
        Integer UserCount = userMapper.selectCount(queryWrapper);
        System.err.println("该区间用户数量:" + UserCount);
    }

模糊查询

4-6:模糊查询【 like、notLike、likeRight 】

likeLeft:就是 % 放左边,相当于 %xxx

likeRight:相当于 xxx%

java 复制代码
    // 模糊查询【 like、notLike、likeRight 】
    @Test
    void test(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        // notLike:相当于 not Like "%红%"
        // likeRight:相当于 "xxx%",right 就表示 % 放在右边,说明这里是以 xxx 为开头
        queryWrapper
                .like("name","紫")  // %紫%
                .notLike("name","白")  // %白%
                .likeRight("email","123"); // 123%
        List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
        maps.forEach(System.err::println);
    }

其他查询

4-7:子查询 【 inSql 】
java 复制代码
    // id 在子查询中查出来
    @Test
    void inSqlTest(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.inSql("id","select id from user where id < 8");

        List<Object> objs = userMapper.selectObjs(queryWrapper);
        objs.forEach(System.err::println);
    }
4-8:排序---根据 id 倒序排序
java 复制代码
    // 排序---根据 id 倒序排序
    @Test
    void orderByDescTest(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("id");

        List<User> users = userMapper.selectList(queryWrapper);
        users.forEach(System.err::println);
    }
相关推荐
Asu52028 小时前
思途AOP学习笔记 0806
java·sql·学习·mybatis
期待のcode11 小时前
配置Mybatis环境
java·tomcat·mybatis
熊猫片沃子15 小时前
mybatis 与mybatisplus 比较总结
java·后端·mybatis
寒士obj20 小时前
MyBatis基础操作完整指南
mybatis
Asu52021 天前
思途Mybatis学习 0805
java·spring boot·学习·mybatis
Mr Aokey1 天前
注解退散!纯XML打造MyBatis持久层的终极形态
xml·java·mybatis
Noii.2 天前
Mybatis的应用及部分特性
java·数据库·mybatis
熊猫片沃子2 天前
Mybatis中进行批量修改的方法
java·后端·mybatis
Code blocks2 天前
SpringBoot中策略模式使用
java·spring boot·后端·mybatis·策略模式
飞翔的佩奇2 天前
基于SpringBoot+MyBatis+MySQL+VUE实现的房屋交易平台管理系统(附源码+数据库+毕业论文+部署教程+配套软件)
数据库·spring boot·mysql·vue·毕业设计·mybatis·房屋交易平台