020_MyBatisPlus CRUD扩展


Insert 插入

新增测试

package com.qing;

import com.qing.mapper.UserMapper;
import com.qing.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testInsert() {
        User user = new User();
        user.setName("张三丰");
        user.setAge(999);
        user.setEmail("wudang@qq.com");
        int rows = userMapper.insert(user);
        System.out.println(rows);
        System.out.println(user);
    }

}

image.png

插入数据时,自动生成id
id自动回填到user对象
插入的id的默认值为:全局唯一id,是雪花算法生成的id

主键生成策略

参考文档:https://www.cnblogs.com/haoxinyue/p/5208136.html

源码分析

不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

image.png
image.png
image.png

雪花算法 IdType.ID_WORKER

参考文档:https://blog.csdn.net/lq18050010830/article/details/89845790
SnowFlake 算法,是 Twitter 开源的分布式 id 生成算法。其核心思想就是:使用一个 64 bit 的 long 型的数字作为全局唯一 id。在分布式系统中的应用十分广泛,且ID 引入了时间戳,基本上保持自增的。
这 64 个 bit 中,其中 1 个 bit 是不用的,然后用其中的 41 bit 作为毫秒数,用 10 bit 作为工作机器 id,12 bit 作为序列号。

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.ID_WORKER)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

image.png

主键自增 IdType.AUTO

数据库主键必须设置为自增

image.png

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

image.png
image.png

未设置主键类型 IdType.NONE

暂时不确定,生成的主键为雪花算法生成的

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.NONE)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

image.png

手动输入 IdType.INPUT

不手动设置主键时,如果数据库主键没有设置自增,插入的主键为null,会报错
如果主键设置为自增,插入的主键是自增值

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.INPUT)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

image.png

UUID IdType.UUID

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.UUID)
    private String id;
    private String name;
    private Integer age;
    private String email;
}

image.png

雪花算法的字符串表示 IdType.ID_WORKER_STR

Update 更新

更新测试

package com.qing;

import com.qing.mapper.UserMapper;
import com.qing.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testUpdate() {
        User user = new User();
        user.setId("1");
        user.setName("张三丰");
        user.setAge(9999);
        user.setEmail("wudang9999@qq.com");
        int rows = userMapper.updateById(user);
        System.out.println(rows);
    }

}

image.png

自动填充

方式一:数据库级别

image.png

方式二:代码级别

使用说明:https://baomidou.com/pages/4c6bcf/
image.png

字段添加注解

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.UUID)
    private String id;
    private String name;
    private Integer age;
    private String email;
    // 新增时自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    // 新增和修改时自动填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
}

编写处理器处理注解

package com.qing.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.time.LocalDateTime;
import java.util.Date;

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    /**
     * 插入时的填充策略
     * @param metaObject
     */
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.setFieldValByName("createTime", new Date(), metaObject);
        this.setFieldValByName("updateTime", new Date(), metaObject);
    }

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

测试

package com.qing;

import com.qing.mapper.UserMapper;
import com.qing.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testInsert() {
        User user = new User();
        user.setName("张三丰");
        user.setAge(999);
        user.setEmail("wudang@qq.com");
        int rows = userMapper.insert(user);
        System.out.println(rows);
        System.out.println(user);
    }

}

image.png

乐观锁

image.png
使用说明:https://baomidou.com/pages/0d93c0/#optimisticlockerinnerinterceptor
image.png

乐观锁实现方式

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

举例说明:
image.png

MybatisPlus乐观锁插件实现

数据库表添加字段version

image.png

实体类字段添加@version注解

image.png

package com.qing.pojo;

import com.baomidou.mybatisplus.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    // 不加注解,默认主机生成策略为IdType.ID_WORKER,即雪花算法
    @TableId(type = IdType.UUID)
    private String id;
    private String name;
    private Integer age;
    private String email;
    // 新增时自动填充
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    // 新增和修改时自动填充
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    @Version // 乐观锁version注解
    private Integer version;
}

配置插件,注册乐观锁组件

image.png
image.png

package com.qing.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@MapperScan("com.qing.mapper") // 扫描mapper包
@EnableTransactionManagement
@Configuration // 配置类
public class MybatisPlusConfig {

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

测试乐观锁成功

package com.qing;

import com.qing.mapper.UserMapper;
import com.qing.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 测试乐观锁成功
     */
    @Test
    public void testOptimisticLocker() {
        User user = userMapper.selectById("1");
        user.setName("张道陵");
        int rows = userMapper.updateById(user);
        System.out.println(rows);
    }

}

image.png

测试乐观锁失败

package com.qing;

import com.qing.mapper.UserMapper;
import com.qing.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 测试乐观锁失败
     */
    @Test
    public void testOptimisticLocker2() {
        // 线程1
        User user = userMapper.selectById("1");
        user.setName("张三丰1号");
        // 模拟线程2
        User user2 = userMapper.selectById("1");
        user2.setName("张三丰2号");
        int rows2 = userMapper.updateById(user2);
        System.out.println("线程2执行行数:" + rows2);
        int rows = userMapper.updateById(user);
        System.out.println("线程1执行行数:" + rows);
    }

}

image.png
version已经被线程2修改,所以线程1执行失败

Select 查询

image.png
image.png

分页查询

使用说明:https://baomidou.com/pages/97710a/
image.png
image.png

MybatisPlus分页插件实现

配置拦截器组件

package com.qing.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@MapperScan("com.qing.mapper") // 扫描mapper包
@EnableTransactionManagement
@Configuration // 配置类
public class MybatisPlusConfig {

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

    /**
     * 注册分页插件
     */
    @Bean
    public PaginationInterceptor paginationInnerInterceptor() {
        return new PaginationInterceptor();
    }
}

使用Page对象

package com.qing;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.qing.mapper.UserMapper;
import com.qing.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 测试分页查询
     */
    @Test
    public void testPage() {
        Page<User> page = new Page(1, 5);
        System.out.println("查询前:" + page.getRecords());
        userMapper.selectPage(page, null);
        System.out.println("查询后:" + page.getRecords());
        System.out.println("数据总数:" + page.getTotal());
    }

}

image.png

Delete 删除

image.png
image.png
image.png

逻辑删除

image.png
作用:防止数据的丢失,类似于回收站
使用说明:https://baomidou.com/pages/6b03c5/
image.png
image.png

MybatisPlus实现逻辑删除

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

posted @ 2022-02-26 20:50  清风(学习-踏实)  阅读(132)  评论(0)    收藏  举报