• MybatisPlus


    简介

    官网 :https://baomidou.com/

    MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

    支持的数据库

    MySQL,Oracle,DB2,H2,HSQL,SQLite,PostgreSQL,SQLServer,Phoenix,Gauss ,ClickHouse,Sybase,

    OceanBase,Firebird,Cubrid,Goldilocks,csiidb

    快速开始

    数据库数据

    # 创建 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)
    );
    
    # 向表中添加数据
    DELETE FROM 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');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    创建项目

    创建一个 springboot 项目或 maven-quickstart 项目

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.1.RELEASEversion>
    parent>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.25version>
    dependency>
    
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.5.1version>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    配置数据库连接

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=admin
    
    • 1
    • 2
    • 3
    • 4

    创建实体

    @Data
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    创建持久层接口(Mapper)

    package com.hkp.mapper;
    
    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.hkp.entity.User;
    
    //继承 BaseMapper 类 ,参数是实体类 ;里面封装了 CRUD 方法
    public interface UserMapper extends BaseMapper<User> {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    启动类添加注解,扫描持久层包

    @MapperScan("com.hkp.mapper")
    
    • 1

    测试

    package com.hkp;
    
    import com.hkp.entity.User;
    import com.hkp.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    import javax.annotation.Resource;
    import java.util.List;
    
    @SpringBootTest
    public class AppTest {
    
        @Resource
        private UserMapper userMapper;
    
        @Test
        public void selectAll(){
            //selectList() 方法的参数为 Mybatis-Plus 内置的条件封装器 Wrapper,所以不填写就是无任何条件
            List<User> userList = userMapper.selectList(null);
            //将所有用户循环输出
            userList.forEach(System.out::println);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述

    添加日志

    添加日志,可以在控制台看到我们的SQL语句,有助于开发

    修改 application.properties

    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false&useUnicode=true&characterEncoding=utf-8
    spring.datasource.username=root
    spring.datasource.password=admin
    
    #开启日志 ,使用 log4j 等其他的日志 需要导包,这里使用默认的日志; 将日志打印到控制台
    mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    启动测试方法

    在这里插入图片描述

    注解

    @TableName

    描述

    表名注解,标识实体类对应的表名

    使用位置

    实体类

    package com.hkp.entity;
    
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    @TableName("sys_user")
    @Data
    public class User {
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    @TableId

    描述

    主键注解

    使用位置

    实体类主键字段

    package com.hkp.entity;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    @TableName("sys_user")
    @Data
    public class User {
        @TableId
        private Long id;
        private String name;
        private Integer age;
        private String email;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    注解的属性

    属性类型必须制定默认值描述
    valueString“”主键字段名
    typeEnumidType.NONE指定主键类型

    idType 的值

    描述
    AUTO数据库 ID 自增
    NONE无状态,该类型为未设置主键类型
    INPUTinsert 前自行 set 主键值
    ASSIGN_ID分配 ID ,主键类型为 :Number ( Long 和 Integer ) 或 String
    ASSIGN_UUID分配 UUID ,主键类型为 :String

    @TableField

    描述

    字段注解(非主键)

    package com.hkp.entity;
    
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    @TableName("sys_user")
    @Data
    public class User {
        @TableId
        private Long id;
        @TableField("username")
        private String name;
        private Integer age;
        private String email;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    主要属性

    属性类型是否必须默认值描述
    valueString“”主要用于 实体中 和 数据表 中名称不一致
    fillEnumFieldFill.DEFAULT可以设置字段的自动填充规则,默认是可变的

    FieldFill 的值

    描述
    DEFAULT默认不处理
    INSERT插入时填充字段
    UPDATE更新时填充字段
    INSERT_UPDATE插入和更新时填充字段

    @Version

    描述

    乐观锁注解、标记

    作用位置

    字段上

    @TableLogic

    描述

    表字段逻辑删除注解

    属性

    属性类型是否必须默认值描述
    valueString“”逻辑未删除值
    delvalString“”逻辑删除值

    CRUD

    新增

    1、在测试接口中测试

    @Test
    public void insertUser(){
        User user=new User();
        user.setName("测试数据");
        user.setAge(12);
        user.setEmail("123456@qq.com");
        int insert = userMapper.insert(user);
        System.out.println(insert);
        System.out.println(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、查看控制台日志效果

    在这里插入图片描述

    注意 :

    可以看到,我并没有往实体中设置 id ,但是却自动加上了一个id

    如果 主键 id 的类型为 Integer 默认的策略是 NONE

    如果 主键id 的类型为 long 默认的策略是 ID_WORKER (雪花算法)

    修改

    1、在测试类中测试

    @Test
    public void updateUser(){
        User user=new User();
        user.setId(1310469473752416258L);
        user.setName("测试数据update");
        int i = userMapper.updateById(user);
        System.out.println(i);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、查看效果

    在这里插入图片描述

    从结果的 SQL 语句中可以看出 这个 修改是动态的修改,也就是需要修改什么属性就传什么属性,不需要修改就不传,保持原来的数据

    查询

    根据 id 查询

    1、测试代码

    @Test
    public void selectById(){
        User user = userMapper.selectById(1);
        System.out.println(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、查看结果

    在这里插入图片描述

    根据多个 ID 查询

    1、测试代码

    @Test
    public void selectByIds(){
        List<Integer> ids = new ArrayList<>();
        ids.add(1);
        ids.add(2);
        ids.add(3);
        List<User> users = userMapper.selectBatchIds(ids);
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2、查看结果

    在这里插入图片描述

    多条件查询 Map

    1、测试代码

    @Test
    public void selectByMap(){
        //注意map中的 key 值必须是数据库的字段名
        Map<String,Object> map=new HashMap<String,Object>();
        map.put("name","Tom");
        map.put("age",28);
        List<User> users = userMapper.selectByMap(map);
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2、查看结果

    在这里插入图片描述

    分页查询

    1、配置分页插件

    // 低版本
    @Configuration
    public class MybatisConfig {
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            return new PaginationInterceptor();
        }
    }
    
    // 高版本
    @Configuration
    public class MybatisConfig {
        @Bean
        public MybatisPlusInterceptor mybatisPlusInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
            return interceptor;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    2、测试

    @Test
    public void SlectPage(){
        //page 中第一个参数表示第几页,第二个参数表示一页中有多少条数据
        Page<User> page=new Page<>(2,5);
        userMapper.selectPage(page,null);
        // 所有的结果都在 page 中 :查询出来的数据,总页数
        List<User> userList = page.getRecords();
        userList.forEach(System.out::println);
        // 每页共有多少条数据
        System.out.println(page.getSize());
        //数据总条数
        System.out.println(page.getTotal());
        //共有多少页
        System.out.println(page.getPages());
        //是否还有下一页
        System.out.println(page.hasNext());
        //是否有上一页
        System.out.println(page.hasPrevious());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3、查看效果

    在这里插入图片描述

    删除

    根据 ID 删除

    1、测试代码

    @Test
    public void deleteById(){
        int num = userMapper.deleteById(2);
        System.out.println(num);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2、查看效果

    在这里插入图片描述

    根据多个 ID 删除

    1、测试代码

    @Test
    public void deleteByIds(){
        List<Integer> ids = new ArrayList<>();
        ids.add(4);
        ids.add(5);
        int num = userMapper.deleteBatchIds(ids);
        System.out.println(num);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、查看效果

    在这里插入图片描述

    多条件删除 Map

    1、测试代码

    @Test
    public void deleteByMap(){
        Map<String,Object> map = new HashMap<>();
        //注意map中的 key 值必须是数据库的字段名
        map.put("name","测试数据update");
        int num = userMapper.deleteByMap(map);
        System.out.println(num);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、查看效果

    在这里插入图片描述

    逻辑删除

    物理删除 :直接从数据库中删除了,数据永远没有了。

    逻辑删除 :没有从数据库中删除,通过一个变量让他失效了。实际上执行的是一个 update 语句。

    # 例如:
    # 删除: 
    update user set deleted=1 where id = 1 and deleted=0
    # 查找: 
    select id,name,deleted from user where deleted=0
    
    • 1
    • 2
    • 3
    • 4
    • 5

    实现步骤

    1、在数据库中添加 变量 用来标记是否是逻辑删除 ,并给默认值为0

    0 :逻辑未删除,1:逻辑已删除

    在这里插入图片描述

    2、在实体类中添加属性,并添加注解 @TableLogic

    package com.hkp.entity;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableLogic;
    import lombok.Data;
    
    @Data
    public class User {
        @TableId
        private Long id;
        private String name;
        private Integer age;
        private String email;
        @TableLogic
        private Integer deleted;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    3、配置逻辑删除插件 ( 3.1.1 版本之后就不需要这个步骤了 )

    @Configuration
    public class MybatisConfig {
        @Bean
        public ISqlInjector sqlInjector(){
            return new LogicSqlInjector();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4、配置 application.properties 文件

    # 全局逻辑删除的实体字段名
    mybatis-plus.global-config.db-config.logic-delete-field=deleted
    # 逻辑已删除值(默认为1)
    mybatis-plus.global-config.db-config.logic-delete-value=1
    # 逻辑未删除值(默认为0)
    mybatis-plus.global-config.db-config.logic-not-delete-value=0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    执行 根据 id 删除语句,结果如下 :

    在这里插入图片描述

    执行根据 多个id 删除语句,结果如下 :

    在这里插入图片描述

    执行查询语句,结果如下 :

    在这里插入图片描述

    此时发现,查询的SQL 语句中加入了一个条件 where deleted=0

    条件构造器 wrapper

    更多知识去文档里学习 :

    https://baomidou.com/pages/10c804/#abstractwrapper

    like

    语法 :

    like(R column,Object val)
    
    • 1

    根据 姓名模糊查询

    @Test
    public void like(){
        //根据姓名模糊查询
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.like("name","j");
        List<User> users = userMapper.selectList(wrapper);
        //将所有用户循环输出
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果

    在这里插入图片描述

    根据姓名左边模糊查询 和 右边模糊查询

    @Test
    public void like2(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.likeLeft("name","a")
            .likeRight("name","j");
        List<User> users = userMapper.selectList(wrapper);
        //将所有用户循环输出
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    运行结果

    在这里插入图片描述

    between

    between and 左右均包含

    语法 :

    between(R column, Object val1, Object val2)
    
    • 1

    查询年龄在 20-30 岁之间

    @Test
    public void between(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.between("age","12","28");
        List<User> users = userMapper.selectList(wrapper);
        //将所有用户循环输出
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果

    在这里插入图片描述

    isNotNull

    语法 :

    isNotNull(R column)
    
    • 1

    查询姓名不为空的用户

    @Test
    public void isNotNull(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name");
        List<User> users = userMapper.selectList(wrapper);
        //将所有用户循环输出
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果 :

    在这里插入图片描述

    eq

    语法 :

    eq(R column, Object val)
    
    • 1

    查询姓名等于 tom 的用户

    @Test
    public void eq(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("name","tom");
        User user = userMapper.selectOne(wrapper);
        //将所有用户循环输出
        System.out.println(user);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果 :

    在这里插入图片描述

    扩展

    eq :等于

    ne :不等于

    ge

    语法 :

    ge(R column, Object val)
    
    • 1

    查询年龄大于等于28岁的用户

    @Test
    public void ge(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.ge("age",28);
        List<User> users = userMapper.selectList(wrapper);
        //将所有用户循环输出
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果

    在这里插入图片描述

    扩展

    gt :大于

    ge :大于等于

    lt :小于

    le :小于等于

    orderByDesc

    语法 :

    orderByDesc(R... columns) // 多个字段用逗号隔开
    orderByDesc("id", "name")--->order by id DESC,name DES
    
    • 1
    • 2

    根据 id 降序排序

    @Test
    public void desc(){
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        //将所有用户循环输出
        users.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    运行结果

    在这里插入图片描述

    扩展

    orderByAsc :升序

    orderByDesc :降序

  • 相关阅读:
    微PE辅助VMware安装操作系统
    Linux编译器 -- gcc/g++ 调试器 -- gdb
    bpftrace:简便输出调试信息
    ORA-55610: Invalid DDL statement on history-tracked table
    前端经典面试题:在浏览器从输入 URL 到页面加载显示完成的过程?从输入URL到页面加载发生了什么?
    CSRF漏洞
    (2023|ICLR,检索引导,交叉引导,EntityDrawBench)Re-Imagen:检索增强的文本到图像生成器
    数据结构实验二 堆栈
    关系型数据库之 MySQL 详解:从入门到精通【面试圣经】
    offer突击训练营,给你一个offer的保障,求职跳槽的看过来!
  • 原文地址:https://blog.csdn.net/weixin_46047612/article/details/126133819