Mybatis-Plus

概述

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

润物无声
只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。

效率至上
只需简单配置,即可快速进行CRUD操作,从而节省大量时间。

丰富功能
热加载、代码生成、分页、性能分析等功能一应俱全。

实例

1、创建数据库,创建数据库表

CREATE TABLE `user` (
  `id` bigint NOT NULL COMMENT '主键ID',
  `name` varchar(30) DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) 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、创建工程 springboot

3、引入依赖

<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

4.配置数据库驱动

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

5、代码实现

实体类

@Data
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

UserMapper 继承BaseMapper接口

@Repository
public interface UserMapper extends BaseMapper<User> {
}

查询

查看sql输出日志

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

查询所有

@Test
public void findAll(){
    List<User> users = userMapper.selectList(null);
    System.out.println(users);
}

在这里插入图片描述
多个id批量查询

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

在这里插入图片描述
简单条件查询

一般很少用,用得多的是条件构造器进行查询,了解即可

//简单条件查询
@Test
public void testSelect2(){
    HashMap<String, Object> hashMap = new HashMap<>();
    hashMap.put("name","jone");
    hashMap.put("age","18");
    List<User> users = userMapper.selectByMap(hashMap);
    System.out.println(users);
}

在这里插入图片描述
分页查询

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

MpConfig

/**
 * 分页插件
 */
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
    return interceptor;
}

① selectPage分页

//分页查询
@Test
public void testSelectPage(){
    Page<User> page = new Page(1, 3);//页数 ,每页的数量
    Page<User> selectPage = userMapper.selectPage(page, null);
    //返回对象得到分页所有数据
    long pages = selectPage.getPages();//总页数
    long current = selectPage.getCurrent();//当前页
    List<User> records = selectPage.getRecords();//查询数据集合
    long total = selectPage.getTotal();//总记录数
    boolean hasNext = selectPage.hasNext();//下一页
    boolean hasPrevious = selectPage.hasPrevious();//上一页

    System.out.println(pages);
    System.out.println(current);
    System.out.println(records);
    System.out.println(total);
    System.out.println(hasNext);
    System.out.println(hasPrevious);
}

执行结果:
在这里插入图片描述
②测试selectMapsPage分页

@Test
public void testSelectMapsPage() {
    //Page不需要泛型
    Page<Map<String, Object>> page = new Page<>(1, 5);
    Page<Map<String, Object>> pageParam = userMapper.selectMapsPage(page, null);
    List<Map<String, Object>> records = pageParam.getRecords();
    records.forEach(System.out::println);
    System.out.println(pageParam.getCurrent());
    System.out.println(pageParam.getPages());
    System.out.println(pageParam.getSize());
    System.out.println(pageParam.getTotal());
    System.out.println(pageParam.hasNext());
    System.out.println(pageParam.hasPrevious());
}

在这里插入图片描述

插入

@Test
public void testAdd(){
    User user = new User();
    user.setName("lucy");
    user.setAge(20);
    user.setEmail("1231@qq.com");
    int insert = userMapper.insert(user);
    System.out.println(insert);
}

结果:
在这里插入图片描述
在这里插入图片描述

主键策略

ASSIGN_ID

我们可以看到插入的值主键不是自增的这是因为MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)

@TableId(type = IdType.ASSIGN_ID)
private String id;

核心思想:
长度共64bit(一个long型)。
首先是一个符号位,1bit标识,由于long基本类型在Java中是带符号的,最高位是符号位,正数是0,负数是1,所以id一般是正数,最高位是0。
41bit时间截(毫秒级),存储的是时间截的差值(当前时间截 - 开始时间截),结果约等于69.73年。
10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID,可以部署在1024个节点)。
12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID)。
在这里插入图片描述

优点:整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。

AUTO 自增策略
@TableId(type = IdType.AUTO)
private Long id;

要想影响所有实体的配置,可以设置全局主键配置

#全局设置主键生成策略
mybatis-plus:
  global-config:
    db-config:
      id-type: auto
描述
ASSIGN_ID分配ID(使用了雪花算法) ,主键类型为Number(Long和Integer)或String
AUTO数据库ID自增
INPUTinsert前自行set主键值
ASSIGN_UUID分配UUID,主键类型为String
NONE无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)

修改

//修改
@Test
public void testUPdate(){
    User user = new User();
    user.setId(1579087946689576962L);
    user.setName("frank");
    int count = userMapper.updateById(user);
    System.out.println(count);
}

在这里插入图片描述

自动填充

在User表中添加datetime类型的新的字段 create_time、update_time
在这里插入图片描述
2、实体类修改

实体上增加字段并添加自动填充注解

@TableField(fill = FieldFill.INSERT)//添加的时候有值
private Date createTime;  //create_time

@TableField(fill = FieldFill.INSERT_UPDATE)//修改的时候有值
private Date updateTime; //update_time

3、实现元对象处理器接口

/**
 * @author acoffee
 * @create 2022-10-11 21:57
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    //添加是执行的方法
    @Override
    public void insertFill(MetaObject metaObject) {
        this.setFieldValByName("createTime",new Date(),metaObject);
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }

    //修改是执行的方法
    @Override
    public void updateFill(MetaObject metaObject) {
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

测试结果:
在这里插入图片描述

mq实现乐观锁

简单介绍一下乐观锁:

主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新

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

mq实现乐观锁

修改实体类

@Version
@TableField(fill = FieldFill.INSERT)//插入数据的时候初始化version
private Integer version;
@Override
  public void insertFill(MetaObject metaObject) {
      this.setFieldValByName("version",1,metaObject);
  }

创建配置文件

创建包config,创建文件MpConfig

@Configuration
public class MpConfig {
    /**
     * 乐观锁插件:mp 3.4.0之后
     */
    @Bean
    public MybatisPlusInterceptor optimisticLockerInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
    
//乐观锁插件:mp 3.4.0之前
//    @Bean 
//    public OptimisticLockerInterceptor optimisticLockerInterceptor () {
//        return new OptimisticLockerInterceptor();
//    }
}

测试

//测试乐观锁
@Test
public void testOptimisticLocker(){
    //根据id查询
    User user = userMapper.selectById(2L);
    System.out.println(user);
    //修改
    user.setName("bubu");
    userMapper.updateById(user);
}

在这里插入图片描述

删除

//删除
@Test
public void testDelete(){
    int result = userMapper.deleteById(1579837508760965121L);
    System.out.println(result);//1
}

//批量删除
@Test
public void testBatchDelete(){
    int count = userMapper.deleteBatchIds(Arrays.asList(1579847783669075969L, 1579837508760965122L));
    System.out.println(count);//2
}

//简单条件删除
@Test
public void testDeleteByMap() {
    HashMap<String, Object> map = new HashMap<>();
    map.put("name", "lucy");
    map.put("age", 20);
    int result = userMapper.deleteByMap(map);
    System.out.println(result);
}
逻辑删除

物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录

逻辑删除的使用场景:
可以进行数据恢复
有关联数据,不便删除

逻辑删除实现流程

1、添加 deleted字段

alter table `user` add COLUMN deleted INTEGER DEFAULT 0 //一般是0代表不删除 1代表删除

在这里插入图片描述

2、实体类修改

 @TableLogic
 private Integer deleted;

MyMetaObjectHandler

this.setFieldValByName("deleted",0,metaObject);

测试类

//逻辑删除
@Test
public void testDeleteById(){
    int count = userMapper.deleteById(1L);
    System.out.println(count);//1
    User user = userMapper.selectById(1L);
    System.out.println(user);//null
}

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

条件构造器和常用接口

Wrapper简介
在这里插入图片描述

类名描述
Wrapper条件构造抽象类,最顶端父类
AbstractWrapper用于查询条件封装,生成 sql 的 where 条件
QueryWrapper查询条件封装
UpdateWrapperUpdate 条件封装
AbstractLambdaWrapper使用Lambda 语法
LambdaQueryWrapper用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapperLambda 更新封装Wrapper

ge、gt、le、lt

@Test
public void testSelect(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // ge、gt、le、lt
    wrapper.ge("age", 21);//ge:大于等于
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

在这里插入图片描述
eq、ne

@Test
public void testSelect3(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // eq、ne
    wrapper.eq("age", 21);//eq:等于
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

在这里插入图片描述
between、notBetween
包含大小边界

@Test
public void testSelect4(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // between、notBetween
    wrapper.between("age", 21,25);
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

在这里插入图片描述
like、notLike、likeLeft、likeRight

@Test
public void testSelect5(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // like、notLike、likeLeft、likeRight
    wrapper.likeRight("name", 'b');//likeRight:以什么开头
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

在这里插入图片描述

orderBy、orderByDesc、orderByAsc

@Test
public void testSelect6(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // orderBy、orderByDesc、orderByAsc
    wrapper.orderBy(true,false,"age","id");//id:升序 age:降序
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

在这里插入图片描述

@Test
public void testSelect6(){
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    // orderBy、orderByDesc、orderByAsc
    wrapper.orderByDesc("age","id");//先按age降序 在按照id降序
    List<User> users = userMapper.selectList(wrapper);
    System.out.println(users);
}

其他api可以看这篇文章

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值