MyBatisPlus-基本配置与常见应用

2024-01-08 05:58:12

MyBatisPlus

一、快速入门

MyBatis Plus是基于MyBatis的增强工具,提供了更简单、更便捷的方式来操作数据库。它是一个功能丰富的ORM(对象关系映射)框架,可以帮助开发人员更快速地进行数据库操作。

MyBatis Plus的主要特点如下:

  1. 自动生成代码:MyBatis Plus可以根据数据库表结构自动生成实体类、接口和XML映射文件,大大减少了手动编写重复代码的工作量。

  2. 强大的CRUD操作:MyBatis Plus提供了一系列的CRUD(创建、读取、更新、删除)方法,支持多种查询方式,如通过主键、条件查询和分页查询等。

  3. 简化的分页插件:MyBatis Plus提供了简单易用的分页插件,可以方便地进行分页查询,并支持多种数据库的分页方式。

  4. 条件构造器:MyBatis Plus提供了条件构造器,可以通过链式调用的方式来构建复杂的查询条件。这使得查询语句的编写更加灵活和简洁。

  5. 支持主键生成策略:MyBatis Plus支持多种主键生成策略,如自增、UUID和雪花算法等。

  6. 乐观锁支持:MyBatis Plus提供了乐观锁的支持,可以解决并发更新时的数据冲突问题。

  7. Lambda表达式:MyBatis Plus支持使用Lambda表达式进行查询,可以更直观地表达查询条件。

总之,MyBatis Plus是一个功能强大、易用性高的ORM框架,可以帮助开发人员更快速地进行数据库操作,减少开发工作量,提高开发效率

文档:https://mp.baomidou.com/

使用第三方组件

  1. 导入对应依赖
  2. 研究依赖如何配置
  3. 代码如何编写
  4. 提高扩展技术能力

步骤

1、创建数据库 mybatis_plus

2、创建user表

DROP TABLE IF EXISTS 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)
);
-- 真实开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified

3、创建项目

4、导入依赖

<!--数据库驱动-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.20</version>
</dependency>
<!--mybatis-plus-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>
<!--lombok-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

说明:我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus!

5、连接数据库,这一步和mybatis相同

# mysql
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?userSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

6、传统方式:pojo-dao(连接mybatis,配置mapper.xml文件)- service - controller

6、使用了mybatis-plus 之后

  • pojo
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
  • mapper接口
// 在对应的Mapper上面继承基本的接口 BaseMapper
@Repository // 代表持久层
public interface UserMapper extends BaseMapper<User> {
    // 所有的CRUD操作都已经基本完成了
    // 你不需要像以前的配置一大堆文件了
}

注意点:我们需要在主启动类上去扫描我们的mapper包下的所有接口 @MapperScan(“mapper的全路径”)

在这里插入图片描述

  • 测试类中测试
@SpringBootTest
class MybatisPlusApplicationTests {

    // 继承了BaseMapper,所有的方法都来自父类
    // 我们也可以编写自己的扩展方法
    @Autowired
    UserMapper userMapper;

    @Test
    void contextLoads() {
        // 参数是一个 Wrapper , 条件构造器,这里我们先不用 null
        // 查询全部用户
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }
}

思考问题:

1、SQL是谁帮我们写的?MyBatis-Plus都写好了

去看一下BaseMapper的源码

2、方法哪里来的?MyBatis-Plus 都写好了

二、配置日志

我们所有的sqld现在都是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!

# 配置日志 (系统自带的,控制台输出)
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

配置完毕日志之后,后面的学习就需要注意这个自动生成的SQL,你们就会喜欢上MyBatis-Plus !

自动生成的SQL语句

在这里插入图片描述

理解一下sqlsessison对象创建的过程

三、CRUD

1. 插入操作

在这里插入图片描述

数据库插入的id默认值为:全局的唯一id

在这里插入图片描述

id自动生成,并且全局唯一

2. 主键生成策略(都测试一下)

在这里插入图片描述

①@TableId源码

在这里插入图片描述

主键的类型默认为空,需要指定

在这里插入图片描述

指定Id的类型

在这里插入图片描述

public enum IdType {
    AUTO(0), // 数据库id自增
    NONE(1), // 未设置主键
    INPUT(2), // 手动输入,自己写id
    ID_WORKER(3), // 默认的全局唯一id
    UUID(4), // 全局唯一id uuid
    ID_WORKER_STR(5); // ID_WORKER 字符串表示法
}

默认 ID_WORKER 全局唯一id

分布式系统唯一id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法:

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!

主键自增

我们需要配置主键自增:

<1>实体类字段上 @TableId(type = IdType.AUTO)

<2>数据库字段上一定是自增的
在这里插入图片描述

3. 更新操作

在这里插入图片描述

//测试更新
@Test
public void testUpdate(){
    User user = new User();
    // 通过条件自动拼接动态sql
    user.setId(6L);
    user.setName("关注我的微信公众号");
    user.setAge(18);
    // 注意: updateById 但是参数是一个 对象
    int i = userMapper.updateById(user);
    System.out.println(i);
}

所有的sql都是自动帮你动态配置的!

4. 自动填充

创建时间、修改时间!这些个操作一般都是自动化完成的,我们不希望手动更新!

**阿里巴巴开发手册:**所有的数据库表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别(工作中不允许修改数据库)

1.在表中新增字段 create_time,update_time

在这里插入图片描述

2.再次测试插入方法,我们需要先把实体类同步

private Date createTime;
private Date updateTime;

3.再次查看更新结果即可

在这里插入图片描述

方式二:代码级别

1.删除数据库中的默认值、更新操作

在这里插入图片描述

2.实体类的字段属性上需要增加注解

在这里插入图片描述

//字段添加填充内容
@TableField(fill = FieldFill.INSERT)
private Date createTime;

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

查看一下源码理解一些可以设置的属性

3.编写处理器来处理这个注解即可

在这里插入图片描述

在这里插入图片描述

package com.kuang.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
@Component // 一定不要忘记把处理器加到IOC容器中
public class MyMetaObjectHandler implements MetaObjectHandler {

    // 插入时候的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ...");
        // setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

    // 更新时的填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        log.info("start update fill ...");
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

}

4.测试插入

5.测试更新,观察时间

5. 乐观锁

在面试过程中,我们经常会被问到乐观锁,悲观锁。

乐观锁:顾名思义,它总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试

悲观锁:顾名思义,它总是认为总是出现问题,无论干什么都上锁!再去操作!

乐观锁实现方式
  • 取出记录时,获取当前version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失败

①数据库添加字段

在这里插入图片描述

在这里插入图片描述

②实体类添加属性,添加乐观锁注解

在这里插入图片描述

@Version // 乐观锁的version注解
private Integer version;

③添加MybatisPlus的配置类,注册乐观锁插件

在这里插入图片描述

// 扫描我们的 mapper文件夹
@MapperScan("com.kuang.mapper")
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {

    // 注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
}

④测试乐观锁更新成功

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

⑤测试乐观锁更新失败

在这里插入图片描述

测试:

在这里插入图片描述

线程1先查询,再到线程2查询,查询到的version=2,但是线程2先完成更新操作,此时数据库的version=3,所以线程2将无法完成更新操作,这就是乐观锁的作用

    // 测试乐观锁成功
    @Test
    public void testVersionSuccess(){
        // 1. 查询用户信息
        User user = userMapper.selectById(1L);
        // 2. 修改用户信息
        user.setName("fan");
        user.setAge(24);
        // 3. 执行更新操作
        userMapper.updateById(user);
    }

    // 测试乐观锁失败!多线程下
    @Test
    public void testVersionFall(){
        // 线程1
        User user1 = userMapper.selectById(1L);
        user1.setName("fan111");
        user1.setAge(14);

        // 线程2
        User user2 = userMapper.selectById(1L);
        user2.setName("fan222");
        user2.setAge(24);
        userMapper.updateById(user2);
        
        //自旋锁来多次尝试提交!
        userMapper.updateById(user1); //如果没有乐观锁就会覆盖插队线程的值
    }
}

6. 查询操作

// 测试查询
@Test
public void testSelectById(){
    User user = userMapper.selectById(1);
    System.out.println(user);
}

// 批量查询
@Test
public void testSelectByBatchIds(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    users.forEach(System.out::println);
}

// 按照条件查询之一使用 map
@Test
public void testSelectByMap(){
    HashMap<String, Object> map = new HashMap<>();
    // 自定义要查询
    map.put("name","Dainel");
    map.put("age","6");
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

测试:

7. 分页查询

分页网站频繁使用

  1. 原始使用limit进行分页
  2. pageHelper第三方插件
  3. MybatisPlus内置了分页插件
使用分页

①配置拦截器

在这里插入图片描述

// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

②直接使用Page对象即可

在这里插入图片描述

在这里插入图片描述

得到记录条数,实际上查询时,使用了count函数

在这里插入图片描述

测试:

在这里插入图片描述

底层都使用limit

在这里插入图片描述

8. 删除操作

// 测试删除
@Test
public void testdelete(){
    userMapper.deleteById(6L);
}

// 测试批量删除
@Test
public void testdeleteBatchId(){
    userMapper.deleteBatchIds(Arrays.asList(1287326823914405893L,1287326823914405894L));
}

//通过map删除
@Test
public void testDeleteByMap(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","KUANG");
    userMapper.deleteByMap(map);
}

测试:

在这里插入图片描述

9. 逻辑删除

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

逻辑删除:在数据库中没有被移除,而是通过一个变量让他生效!deleted=0 --> deleted=1

管理员可以查看被删除的记录!防止数据的丢失!类似于回收站!

测试

①在数据库表中增加一个deleted字段

在这里插入图片描述

②实体类中增加属性

在这里插入图片描述

③配置

<1>配置逻辑删除组件

在这里插入图片描述

<2>配置逻辑删除

在这里插入图片描述

测试:

在这里插入图片描述

使用注解后,虽然是删除操作,但是只是逻辑删除,即是更新操作,将deleted=0–>deleted=1

在这里插入图片描述

注:数据库的数据还在,只是deleted的值发生变化

<4>再查询一下,也查不出来,因为多了个判断条件

在这里插入图片描述

以上所有的CRUD操作及其扩展操作,我们必须精通掌握!会大大提高工作效率!

四、性能分析插件

我们在平时的开发中,会遇到一些慢sql。解决方案:测试,druid监控…

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

MyBatisPlus也提供性能分析插件,如果超过这个时间就停止运行!

1、导入插件

在这里插入图片描述

// SQL执行效率插件
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor(){
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(100); //ms 设置sql执行的最大时间,如果超过了则不执行
    performanceInterceptor.setFormat(true); // 是否格式化
    return performanceInterceptor;
}

② 测试使用

// 测试查询
@Test
public void testSelectById(){
    User user = userMapper.selectById(3);
    System.out.println(user);
}

测试:

在这里插入图片描述

只要超出时间就会抛出异常

使用性能分析插件可以提高效率,新版本MP已经移除该拆件了,可以使用druid

五、条件构造器

十分重要:wrapper

我们写一些复杂的sql就可以使用它来代替!

注:将wrapper作为条件放入crud的方法中,作为参数传递,wrapper可以定制化条件SQL语句

在这里插入图片描述

1、非空 大于

在这里插入图片描述

结果:

在这里插入图片描述

在这里插入图片描述

2、查询一个名字

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

3、使用between

在这里插入图片描述

结果:

在这里插入图片描述

在这里插入图片描述

4、like模糊查询

在这里插入图片描述

结果:

在这里插入图片描述

5、连接查询(内查询)

在这里插入图片描述

结果:

在这里插入图片描述

6、升序排序

在这里插入图片描述

结果:

在这里插入图片描述

多测试一下,需要用到回来看看

六、代码生成器

dao、pojo、service、controller都给我自己去编写完成!

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

注意:在全局配置中总有一句代码,怎么写都是爆红,我一开始以为是依赖冲突,一直去换依赖,步步排查才发现原来是有依赖导错了

在这里插入图片描述

在这里插入图片描述

有空多用用

// 代码自动生成器
public class AutoGeneratorTest {
    public static void main(String[] args) {
        // 需要构建一个 代码自动生成器 对象
        AutoGenerator mpg = new AutoGenerator();
        // 配置策略

        // 1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("小爽帅到拖网速");
        gc.setOpen(false);
        gc.setFileOverride(false);  // 是否覆盖
        gc.setServiceName("%Serive"); // 服务接口,去Service的I前缀
        gc.setIdType(IdType.ID_WORKER); // 主键生成策略
        gc.setDateType(DateType.ONLY_DATE);
        gc.setSwagger2(true);

        // 给代码自动生成器注入配置
        mpg.setGlobalConfig(gc);

        // 2、 设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2b8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("83821979Zs");
        dsc.setDbType(DbType.MYSQL);
        mpg.setDataSource(dsc);

        // 3、包的配置

        PackageConfig pc = new PackageConfig();
        pc.setModuleName("blog");
        pc.setParent("com.shuang");
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");

        mpg.setPackageInfo(pc);

        // 4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("user"); // 设置要映射的表名
        strategy.setNaming(NamingStrategy.underline_to_camel);  // 内置下划线转驼峰命名
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);  // 自动Lombok

        strategy.setLogicDeleteFieldName("deleted");  // 逻辑删除字段

        // 自动填充策略
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModifid = new TableFill("gmt_modifid", FieldFill.INSERT);

        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModifid);
        strategy.setTableFillList(tableFills);

        // 乐观锁
        strategy.setVersionFieldName("version");

        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true); // Localhost:8080/hello_id_2

        mpg.setStrategy(strategy);

        // 执行
        mpg.execute();
    }
}

MyBatisPlus-基本配置与常见应用 到此完结,笔者归纳、创作不易,大佬们给个3连再起飞吧

文章来源:https://blog.csdn.net/kdzandlbj/article/details/135447370
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。