欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MyBatisPlus详解

程序员文章站 2022-04-15 22:55:46
MyBatisPlus详解 官网链接: "链接" 简介 MyBatis Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。 为什么要学习它 ......

mybatisplus详解

官网链接:

简介

mybatis-plus(简称 mp)是一个 mybatis 的增强工具,在 mybatis
的基础上只做增强不做改变,为简化开发、提高效率而生。
mybatis 最好的搭档,就像 魂斗罗 中的 1p、2p,基友搭配,效率翻倍。

MyBatisPlus详解

为什么要学习它呢?

mybatisplus可以节省我们大量工作时间,所有的crud代码它都可以自动化完成!

特性

MyBatisPlus详解

支持数据库

MyBatisPlus详解

架构

MyBatisPlus详解

快速开始

  1. 创建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. 创建springboot项目,导入依赖
<parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>2.2.6.release</version>
        <relativepath/>
    </parent>
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-test</artifactid>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupid>com.baomidou</groupid>
            <artifactid>mybatis-plus-boot-starter</artifactid>
            <version>3.3.1.tmp</version>
        </dependency>
        <dependency>
            <groupid>com.h2database</groupid>
            <artifactid>h2</artifactid>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

MyBatisPlus详解
3. 配置 连接数据库
MyBatisPlus详解

spring:
  datasource:
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/mybatis_plus?useunicode=true&characterencoding=utf-8&servertimezone=utc&usessl=false
    driver-class-name: com.mysql.cj.jdbc.driver

  1. 编写实体类
@data
public class user {
    private long id;
    private string name;
    private integer age;
    private string email;
}
  1. 编写mapper类
public interface usermapper extends basemapper<user> {

}
  1. 创建启动类

MyBatisPlus详解

@springbootapplication
@mapperscan("com.mybatisplus.mybatisplus.mapper")
public class mybatisplusapplication {

    public static void main(string[] args) {
        springapplication.run(mybatisplusapplication.class, args);
    }

}
  1. 测试
    查询全部用户
    MyBatisPlus详解
    MyBatisPlus详解
@springboottest
class mybatisplusapplicationtests {
    @autowired
    usermapper mapper;

    @test
    void contextloads() {
        list<user> users = mapper.selectlist(null);
        users.foreach(system.out::println);//打印输出
    }

}

通过以上几个简单的步骤,我们就实现了 user 表的 crud 功能,甚至连 xml 文件都不用编写!
从以上步骤中,我们可以看到集成mybatis-plus非常的简单,只需要引入 starter 工程,并配置 mapper 扫描路径即可。
但 mybatis-plus 的强大远不止这些功能,想要详细了解 mybatis-plus 的强大功能?那就继续往下看吧!(官网原话)

配置日志

所以的sql不可见,我们需要观看sql是怎么执行的
MyBatisPlus详解

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

MyBatisPlus详解

crud拓展

insert插入

MyBatisPlus详解

@test
    public void testinsert(){
        user u=new user();
        u.setname("joker_dj");
        u.setage(18);
        u.setemail("2332810801@qq.com");
        mapper.insert(u);
    }

MyBatisPlus详解
id会自动生成
MyBatisPlus详解
常见的id生成有
MyBatisPlus详解

id生成策略
博客:

雪花算法

自增id:对于数据敏感场景不宜使用,且不适合于分布式场景。
guid:采用无意义字符串,数据量增大时造成访问过慢,且不宜排序。

最高位是符号位,始终为0,不可用。
41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。
10位的机器标识,10位的长度最多支持部署1024个节点。
12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个id序号,12位的计数序列号支持每个节点每毫秒产生4096个id序号。
原文:

测试不同的主键自增策略

MyBatisPlus详解
MyBatisPlus详解
MyBatisPlus详解
自增策略
MyBatisPlus详解

public enum idtype {
    auto(0),//主键自增
    none(1),//不使用
    input(2),//手动输入
    id_worker(3),//默认全局唯一id
    uuid(4),//全局唯一id uuid
    id_worker_str(5);//字符串表示法
}

update更新

MyBatisPlus详解
MyBatisPlus详解
MyBatisPlus详解

自动填充

创建时间、修改时间、这些操作是自动化完成的,我们不希望手动更新
阿里巴巴手册:所有数据表:gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

方式一:数据库级别

  1. 在表中新增字段 create_time, update_time
    MyBatisPlus详解
    再次测试,同步实体类
    MyBatisPlus详解
    运行测试

MyBatisPlus详解

方式二:代码级别

  1. 删除数据库的默认值
    MyBatisPlus详解
  2. 实体类上增加注解
    MyBatisPlus详解
  3. 编写handler策略
    MyBatisPlus详解
@slf4j
@component
public class mymetaobjecthandler implements metaobjecthandler {
    /*插入时的填充策略*/
    @override
    public void insertfill(metaobject metaobject) {
        log.info("填充....");//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("更新....");
        this.setfieldvalbyname("updatetime",new date(),metaobject);
    }
}

MyBatisPlus详解

乐观锁

在面试过程中,我们经常会被问道乐观锁,悲观锁!这个其实非常简单!

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

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

测试mybatisplus的乐观锁

添加字段 默认值为1
MyBatisPlus详解
同步实体类
MyBatisPlus详解
配置乐观锁

@enabletransactionmanagement
@configuration
public class config {
    @bean
    public optimisticlockerinterceptor optimisticlockerinterceptor() {
        return new optimisticlockerinterceptor();
    }
}

测试乐观锁成功案例
MyBatisPlus详解

MyBatisPlus详解

会发现更新操作时默认带上version
MyBatisPlus详解
失败案例
MyBatisPlus详解

MyBatisPlus详解
第二次修改并没有成功

select查询操作

MyBatisPlus详解

@test
    public void testselect01(){//查询单个用户
        user user = mapper.selectbyid(1l);
        system.out.println(user);
    }
    @test
    public void testselect02(){//查询多个用户 批量查询
        list<user> users = mapper.selectbatchids(arrays.aslist(1, 2, 3));
        users.foreach(system.out::println);
    }
    //条件查询 map方式
    @test
    public void testselect03(){
        hashmap<string, object> map = new hashmap<>();
        map.put("name","joker_dj2");//查询字段name为joker_dj2的结果
        map.put("age",18);//查询字段age为18的值
        //...
        list<user> users = mapper.selectbymap(map);
        system.out.println(users);
    }

分页查询

分页插件有很多

  1. 原始的limit进行1分页
  2. pagehelper第三方插件
  3. mybatisplus内置插件

如何使用
配置config
MyBatisPlus详解

//分页插件
    @bean
    public paginationinterceptor paginationinterceptor() {
        return new paginationinterceptor();
    }

直接使用即可
MyBatisPlus详解

//分页插件
    @test
    public void testpage(){
        //参数一:当前页
        //参数二:页面大小
        page<user> objectpage = new page<>(1, 5);//第1页,5行数据
        mapper.selectpage(objectpage, null);//分页查询 条件为null
        objectpage.gettotal();//获取总记录数
        objectpage.getrecords();//获取数据
        objectpage.getrecords().foreach(system.out::println);//打印输出
    }

MyBatisPlus详解

删除操作

MyBatisPlus详解

 //删除操作 根据id删除 单个
    @test
    public void testdelete(){
        mapper.deletebyid(5l);
    }
    @test//批量删除
    public void testdelete02(){
        mapper.deletebatchids(arrays.aslist(1,2,3));//删除id为1 2 3 的用户
    }
    //通过map操作
    @test
    public void testmapdelete(){
        hashmap<string, object> map = new hashmap<>();
        map.put("name","joker_dj2");//删除name为joker_dj2的用户
        mapper.deletebymap(map);
    }

逻辑删除

  1. 物理删除:从数据库直接移除
  2. 逻辑移除:在数据库中没有直接删除,而是通过一个变量让他失效
    场景:
    管理员可以查看被删除的数据,防止数据丢失,类似于回收站

使用:
3. 在数据库中增加一个delete字段 默认值为0
MyBatisPlus详解

  1. 实体类同步
    MyBatisPlus详解
  2. 配置逻辑删除
    MyBatisPlus详解
    MyBatisPlus详解
    测试删除
    MyBatisPlus详解
    可以看到,测试的是删除操作,实际上走的是更新操作,并不是删除操作
    测试查询 会跟上where deleted=0的sql 非管理员
    MyBatisPlus详解

性能分析插件

我们在平时的开发中,会遇到一些慢sql。测试! druid,,,,,
作用:性能分析拦截器,用于输出每条 sql 语句及其执行时间
mybatisplus也提供性能分析插件,如果超过这个时间就停止运行!

使用

  1. 导入插件
    MyBatisPlus详解

  2. 配置项目为测试环境
    MyBatisPlus详解
    MyBatisPlus详解

条件构造器

wrapper十分重要
复杂的sql就靠它
MyBatisPlus详解
使用

  1. 判断空
    MyBatisPlus详解
//查询name不为空,并且邮箱不为空的用户,年龄大于18的用户
    @test
    public void testwrapper(){
        querywrapper<user> wrapper = new querywrapper<>();
        wrapper
                .isnotnull("name")//查询不为空的用户
                .isnotnull("email")//箱不为空
                .ge("age",19);//年龄大于18的用户 19>18
        ;
        mapper.selectlist(wrapper);
    }

MyBatisPlus详解
2. 等于,模糊查询
MyBatisPlus详解

 @test
    public void  test01(){//查询一个name等于joker_dj的用户
        querywrapper<user> wrapper = new querywrapper<>();
        wrapper.eq("name","joker_dj");
        mapper.selectone(wrapper);
    }
    @test
    public void test02(){//查询年龄在18-21的用户个数
        querywrapper<user> wrapper = new querywrapper<>();
        wrapper.between("age",18,21);
        integer integer = mapper.selectcount(wrapper);
        system.out.println(integer);
    }
    @test
    public void test03(){//模糊查询
        querywrapper<user> wrapper = new querywrapper<>();
        wrapper
                .notlike("name","j")//查询姓名不包含j的用户
                .likeright("email","t") //左和右likeleft '%t' likeright 't%'
        ;
        list<map<string, object>> maps = mapper.selectmaps(wrapper);
        maps.foreach(system.out::println);
    }
  1. 子查询
    MyBatisPlus详解
    MyBatisPlus详解
  2. 排序
    MyBatisPlus详解

代码生成器

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

autogenerator 是 mybatis-plus 的代码生成器,通过 autogenerator 可以快速生成 entity、
mapper、mapper xml、service、controller 等各个模块的代码,极大的提升了开发效率。

  1. 导入依赖
<parent>
        <groupid>org.springframework.boot</groupid>
        <artifactid>spring-boot-starter-parent</artifactid>
        <version>2.2.6.release</version>
        <relativepath/>
    </parent>
    <dependencies>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter</artifactid>
        </dependency>
        <dependency>
            <groupid>org.springframework.boot</groupid>
            <artifactid>spring-boot-starter-test</artifactid>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupid>org.projectlombok</groupid>
            <artifactid>lombok</artifactid>
            <optional>true</optional>
        </dependency>
        <!--mybatis和mybatisplus最好只导入其中一个-->
        <dependency>
            <groupid>com.baomidou</groupid>
            <artifactid>mybatis-plus-boot-starter</artifactid>
            <version>3.0.5</version>
        </dependency>
        <dependency>
            <groupid>com.baomidou</groupid>
            <artifactid>mybatis-plus-generator</artifactid>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupid>org.apache.velocity</groupid>
            <artifactid>velocity-engine-core</artifactid>
            <version>2.1</version>
        </dependency>
        <dependency>
            <groupid>mysql</groupid>
            <artifactid>mysql-connector-java</artifactid>
            <version>8.0.19</version>
        </dependency>
    </dependencies>
  1. 编写生成器代码
 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("joker_dj");//设置作者
        gc.setopen(false);//是否打开资源管理器
        gc.setfileoverride(false); // 是否覆盖
        gc.setservicename("%sservice"); // 去service的i前缀
        gc.setidtype(idtype.auto);//设置主键的算法 //对应数据的主键(uuid,自增id,雪花算法,redis,zookeeper)
        gc.setdatetype(datetype.only_date);//日期类型
        gc.setswagger2(true);//是否配置swagger2
        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("123456");
        dsc.setdbtype(dbtype.mysql);//配置数据库类型 mysql
        mpg.setdatasource(dsc);
        //3、包的配置
        packageconfig pc = new packageconfig();
        pc.setmodulename("codegeneration");//模块名称
        pc.setparent("com.dj");//配置工程包名称
        pc.setentity("entity");//配置entity的包名
        pc.setmapper("mapper");//配置mapper的包名
        pc.setservice("service");//配置service的包名
        pc.setcontroller("controller");//配置controller的包名
        mpg.setpackageinfo(pc);//配置包
        //4、策略配置
        strategyconfig strategy = new strategyconfig();
        strategy.setinclude("user"); ////设置映射的表名 多个表strategyconfig.setinclude("user","cloud","...");
        strategy.setnaming(namingstrategy.underline_to_camel);
        strategy.setcolumnnaming(namingstrategy.underline_to_camel);//字段名转驼峰命名
        strategy.setentitylombokmodel(true); // 自动lombok;
        strategy.setlogicdeletefieldname("deleted");//逻辑删除的字段名称
        // 自动填充配置
        tablefill create_time = new tablefill("create_time", fieldfill.insert);//自动填充更新的字段
        tablefill update_time = new tablefill("update_time", fieldfill.insert_update);//自动更新的字段
        arraylist<tablefill> tablefills = new arraylist<>();
        tablefills.add(create_time);//创建的策略
        tablefills.add(update_time);//更新的策略
        strategy.settablefilllist(tablefills);
        // 乐观锁
        strategy.setversionfieldname("version");
        strategy.setrestcontrollerstyle(true);
        strategy.setcontrollermappinghyphenstyle(true);
        mpg.setstrategy(strategy);
        mpg.execute(); //执行
    }