Mybatis-Plus笔记总结

Mybatis-Plus

1.什么是Mybatis-Plus

官网:https://baomidou.com/guide/

  1. 可以节省我们开发时间,因为他可以自动完成大量的CRUD代码;
  2. 在 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.快速开始

  1. 创建数据库表:

    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)
    );
    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. 创建一个空的 Spring Boot 工程

  3. 导入依赖

    <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
    
  4. 连接数据库

    #连接数据库
    spring.datasource.password=root
    spring.datasource.username=root
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/user?useSSL=true&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    
  5. 以前(entity-mapper(mapper.xml)-service-controller)

  6. 现在就简化可配置mapper.xml文件了;在mapper接口处继承BaseMapper

    • 注意:需要在主启动类添加mapperscan注解,扫描mapper文件夹(@MapperScan(“com.simon.mapper”)//扫描mapper文件夹)

    • 编写实体类User

    package com.simon.entity;
    
    import lombok.Data;
    
    @Data
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
    • 编写mapper接口
    package com.simon.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.simon.entity.User;
    import org.springframework.stereotype.Repository;
    
    @Repository//代表持久层
    //继承一个基础类,至此所有的crud操作就已经编写完成了
    public interface UserMapper extends BaseMapper<User> {
    //可以编写一些自己的方法,但是其父类有很多方法可以直接使用
    }
    
  7. 至此就可以直接编写测试类进行CRUD操作了。

    @SpringBootTest
    class MybatisPlusApplicationTests {
    
        @Resource
        private UserMapper userMapper;
        /*
        * 现在所有的方法都是父类的方法,也可以自己编写一些没有的方法
        * */
        @Test
        public void contextLoads() {
            //Wrapper是一个条件构造器,不需要就直接为null
            List<User> users = userMapper.selectList(null);
            users.forEach(System.out::println);
        }
    }
    /*
    User(id=1, name=Jone, age=18, email=test1@baomidou.com)
    User(id=2, name=Jack, age=20, email=test2@baomidou.com)
    User(id=3, name=Tom, age=28, email=test3@baomidou.com)
    User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
    User(id=5, name=Billie, age=24, email=test5@baomidou.com)
    */
    
    

3. 配置日志

#配置日志
#默认的控制台输出,使用log4j需要导入对应的依赖
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

在这里插入图片描述

CRUD

1. 插入数据(insert)

 @Test
    public void contextLoads1() {
        //测试插入数据
//        User user = new User("simon",22,"1092523696@qq.com");
        User user = new User();
        user.setName("simon");
        user.setAge(22);
        user.setEmail("1092523696@qq.com");
        int insert = userMapper.insert(user);
        System.out.println(insert);
        System.out.println(user);
        
//==>  Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
//==> Parameters: 1333586687944278018(Long), simon(String), 22(Integer), 1092523696@qq.com(String)

id主键生成策略

  1. uuid
  2. 自增id
  3. 雪花算法

需要在实体类主键id上添加注解

@TableId(type = IdType.ASSIGN_ID)
private Long id;
/**
 * 数据库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),

2. 更新数据(update)

@Test
    public void contextLoads2() {
        //测试插入数据
//        User user = new User("simon",22,"1092523696@qq.com");
        User user = new User();
        user.setAge(30);
        user.setId(2L);
        int i = userMapper.updateById(user);
        /*
        *   ==>  Preparing: UPDATE user SET age=? WHERE id=?
            ==> Parameters: 30(Integer), 2(Long)
            <==    Updates: 1
        * */
    }

3. 自动填充(时间)

  1. 所有的数据表都应该包含创建时间和修改时间(create_time、modify_time),且这应该被自动的生成。
  • 先在数据库中添加字段create_time、modify_time;

  • 实体类对应属性

    private Date createTime;
    private Date updateTime;
    
  • 需要在实体类属性上添加注解

    @TableField(fill = FieldFill.INSERT)//在插入的时候自动添加
    private Date createTime;
    @TableField(fill = FieldFill.INSERT_UPDATE)//在插入和修改的时候均添加
    private Date updateTime;
    
  • 需要编写处理器处理该注解

    package com.simon.handlers;
    
    
    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;
    
    @Component
    @Slf4j
    public class MyMetaObjectHandler implements MetaObjectHandler {
        @Override
        //插入时的填充策略
        public void insertFill(MetaObject metaObject) {
            log.info("start insert fill.... ");
            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);
        }
    }
    
  1. 现在在进行插入更新操作的时候,就会自动的填充创建时间和更新时间。

4. 乐观锁(version)

  1. 数据库添加version字段,对应实体类添加version属性

    @Version
    private Integer vision;
    
  2. 编写配置类

    package com.simon.config;
    
    
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    @Configuration
    @EnableTransactionManagement
    public class MyConfig {
    
        //注册乐观锁插件
        @Bean
        public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
            return new OptimisticLockerInnerInterceptor();
        }
    
    }
    
  3. 测试

    @Test
    public void contextLoads4() {
        //根据id查询,得到version
        User user = userMapper.selectById(1L);
    
        user.setAge(23);
        user.setName("Tony");
    
        //现在a线程插队执行
        User user1 = userMapper.selectById(1L);
    
        user1.setAge(23);
        user1.setName("Tony1");
    
        userMapper.updateById(user1);
        //可以帮你自动的拼接sql语句
        //这里修改的时候会加上version进行查询修改
        //在多线程的情况下,a线程先修改完成后,b线程想要再次修改的话,就不能成功修改!
        //b线程再执行就会失败
        int i = userMapper.updateById(user);
    }
    

总结:

  1. 在数据库中添加字段version字段,默认值为1,在每次进行修改的时候,就需要先获取version,然后修改成功后,version自动+1;如果多个线程同时操作这条数据时,后面执行的线程就会修改失败。

  2. 在多线程的情况下,使用乐观锁,可以避免数据发生错误,也就是线程之间修改数据的覆盖;保证了数据修改的安全性!

在这里插入图片描述

5. 查询操作(select)

@Test
public void contextLoads5() {
    //通过id查询单个用户
    User user = userMapper.selectById(1L);
    System.out.println(user);

    //通过多个id查询多条数据
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1L,2L,3L));
    users.forEach(System.out::println);

    //通过map作为查询条件进行查询
    //我们还可以使用Wrapper进行封装
    HashMap<String, Object> map = new HashMap<>();
    map.put("id",1L);
    map.put("name","Tony1");
    List<User> map1 = userMapper.selectByMap(map);
    map1.forEach(System.out::println);

    //记录数
    Integer count = userMapper.selectCount(null);
    System.out.println(count);

}

6.删除操作(逻辑删除deleted)

@Test
public void contextLoads7() {
    //根据id删除单个记录
    userMapper.deleteById(1333599021827780610L);

    //批量删除
    userMapper.deleteBatchIds(Arrays.asList(1333586687944278018L,5L));

    //map删除
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","Tom");
    userMapper.deleteByMap(map);

}

逻辑删除:在数据库中还是存在的,还是可以通过条件查询得到数据;管理员是可以通过一定的条件查询已经删除的数据

物理删除:直接从数据库中删除,数据库中是不存在的

  1. 在数据库中添加deleted字段:默认值为0,逻辑删除之后修改为1

在这里插入图片描述

  1. 实体类添加deleted属性,添加注解@TableLogic
@TableLogic//逻辑删除
private Integer deleted;
  1. 配置sql自动注入配置类
//逻辑删除配置,这个是最新版本的sql注入配置
@Bean
public LogicDeleteByIdWithFill logicDeleteByIdWithFill(){
    return new LogicDeleteByIdWithFill();
}

//在3.2.0版本的配置类
@Bean
public ISqlInjector iSqlInjector(){
    return new LogicSqlInjector();
}
  1. 配置properties文件
#配置逻辑删除
mybatis-plus.global-config.db-config.logic-delete-value=1
mybatis-plus.global-config.db-config.logic-not-delete-value=0
  1. 测试
@Test
public void contextLoads8() {
    //根据id删除单个记录
    userMapper.deleteById(1333599021827780610L);
}

在这里插入图片描述

在这里插入图片描述

7.分页查询(分页插件)

  1. 编写配置类
//分页插件配置,最新版本的这个配置类已经废弃掉了,但是还是可以使用
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}
  1. 测试
@Test
public void contextLoads6() {
    //需要一个分页对象,当前页,页面大小
    Page<User> page = new Page<>(2,5);
    userMapper.selectPage(page, null);
    page.getRecords().forEach(System.out::println);

}

8.条件构造器

@Test
public void contextLoads9() {
    //条件构造器wrapper
    //类比map
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //是链式编程可以不断的.
    wrapper
            .isNotNull("name")
            .isNotNull("email")
            .ge("age",25);
    List<User> list = userMapper.selectList(wrapper);
    list.forEach(System.out::println);
}

9.性能分析插件

注意在mybatis-plus:3.2.0之后的版本移除了这个插件。可以设置sql查询的最大时间和对控制台sql语句进行格式化

  1. 配置类
//性能分析插件
@Bean
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor() {
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    // maxTime 指的是 sql 最大执行时长100ms
    performanceInterceptor.setMaxTime(100);
    //SQL是否格式化 默认false
    performanceInterceptor.setFormat(true);
    return performanceInterceptor;
}
  1. 配置properties文件
#性能插件配置,开发环境
spring.profiles.active=dev
  1. 测试执行语句
@Test
public void contextLoads9() {
    //条件构造器wrapper
    //类比map
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //是链式编程可以不断的.
    wrapper
            .isNotNull("name")
            .isNotNull("email")
            .ge("age",25);
    List<User> list = userMapper.selectList(wrapper);
    list.forEach(System.out::println);
}

在这里插入图片描述


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