MyBatisPlus(一):再也不用写 CRUD,时间让它自动填充!

MyBatis-Plus

概述

官方网址:https://mp.baomidou.com/guide/
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,它在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
它是 MyBatis 最好的搭档,就好像魂斗罗中的 1p,2p 两个玩家一样。
在这里插入图片描述
特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

SpringBoot 整合 MyBatis-Plus

创建数据库

CREATE DATABASE mybatis_plus

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');

创建空的 SpringBoot 项目,引入需要的依赖

<!-- 数据库连接-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.19</version>
</dependency>
<!-- lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.12</version>
</dependency>
<!-- mybatis_plus -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.0.5</version>
</dependency>

连接数据库

# 基础的配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&useSSL=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123456

创建实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    private Long id;

    private String name;

    private Integer age;

    private String email;

}

创建mapper类,让 mapper 类继承 BaseMapper ,泛型是对应的实体类

@Mapper
public interface UserMapper extends BaseMapper<User> {

}

在启动类中添加扫描 mapper

@SpringBootApplication
@MapperScan("com.czx.mapper")         //注意:一定要扫描
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);
    }
}

至此,我们已经写好了全部的 CRUD ,不信? 我们来测试。
使用 junit 编写测试代码,首先出数据库中所有的 user

@SpringBootTest
class MybatisPlusApplicationTests {

    @Autowired
    private UserMapper userMapper;

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

看查询结果,所有的用户都被查寻出来了,我们并没有写任何 sql 语句,那是谁帮我们写的呢?当然是 MyBatis-Plus 帮我们写的!(createTime 和 updateTime 稍后再说)
在这里插入图片描述
我们再测试一下插入功能

@Test
    public void testInsert(){

        User user = new User();
        user.setName("Czx");
        user.setAge(7);
        user.setEmail("12345678@qq.com");

        userMapper.insert(user);
    }

我们发现,我们在执行插入操作的时候,id 插入的是很长一串无规则的数据,但我们并没有给 id ,那么这个 id 又是哪里来的。
在这里插入图片描述
这里要说说 MyBatis-Plus 在实体类中使用的注解了 @TableId()
现在我们对 id 添加如下注解,再来分析注解的作用

//插入数据时自增的方式
@TableId(type=IdType.AUTO)
private Long id;

我们来分析源码,按住 ctrl 依次点击红框
在这里插入图片描述
在这里插入图片描述
我们发现,在 IdType中,有好几个参数。这些参数就是 id 产生时,所使用的。

  • auto:按序自增,在使用这一项时,数据库表中 id 必须勾选自增选项
    在这里插入图片描述
  • none:当表没有主键时使用
  • input:插入操作时,手动给定 id
  • id_worker、uuid、id_worker_str 这三项都是自动生成 id ,其中默认的是 id_worker

那么 id_worker 是怎样生成 id 的?采用的是雪花算法来产生 id 的。
雪花算法:
1、第一位 占用1bit,其值始终是0,没有实际作用。
2、时间戳 占用41bit,精确到毫秒,总共可以容纳约69年的时间。
3、工作机器id 占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,做多可以容纳1024个节点。
4、序列号 占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID。
在这里插入图片描述
这样,id 的生成我们就搞清楚了。下面我们进行这个操作

@Test
public void testUpdate(){
    User user = new User();
    user.setId(1278951504018575367L);
    user.setAge(15);
    userMapper.updateById(user);
    }
}

年龄已经修改成了 15岁。
在这里插入图片描述
通过日志,我们可以看出,MyBatis_Plus 替我们组合了动态 sql
在这里插入图片描述

阿里巴巴Java开发手册中对数据库的代码编写,做了强制要求,必须要有 id、gmt_create、gmt_modified 这三项。现在我们来更新数据库,在数据库中添加 create_time,update_time 两项来表示数据库数据的创建时间和更改时间。
接下来我们就按照要求改变我们的代码,首先更改数据库
在这里插入图片描述
接着,同步实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {

    //插入数据时自增的方式
    @TableId(type=IdType.AUTO)
    private Long 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;

}

这里出现了 @TableField()注解,我们来说说这个注解的作用。
这个参数就是用来标注什么情况下更新字段数据的。举个例子:上面的两个参数是 Date 型的,时间是时时刻刻在变化的,对某一操作的时间点进行记录,每一次操作记录一次,那么这个参数就需要不断的更新。
点进源码,我们发现它还是有几个参数
在这里插入图片描述
default:默认不更新该字段的数据
insert:在插入操作时,更新字段数据
update:在更新操作时,更新字段数据
insert_update:在插入和更新的时候都更新字段数据

接着我们分包,再创建实体类,编写更新策略。
首先去实现 MetaObjectHandler 接口,重写接口中的两个方法,一个是插入时的策略,一个是更新时的策略。

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    //在执行插入功能时,进行自动填充的策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("insert start ...");
        //default MetaObjectHandler 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("update start...");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}

我们来解释一下方法

setFieldValByName(String fieldName, Object fieldVal, MetaObject metaObject)
setFieldValByName 有三个参数:
fieldName 是想更新的字段
fieldVal 是更新成什么样,所以它给了 Object 类
最后一个是固定的 metaObjec

所以,我们对字段的更新就成了如下:
在这里插入图片描述
对于插入操作,在操作时,将插入数据的 创建时间、更新时间 一同更新
在这里插入图片描述
对于更新操作,在操作时,将数据的 更新时间 进行更新
下面我们来测试

@Test
public void testInsert(){

    User user = new User();
    user.setName("Czx");
    user.setAge(7);
    user.setEmail("12345678@qq.com");

    userMapper.insert(user);
}

@Test
public void testUpdate(){
    User user = new User();
    user.setId(1278951504018575369L);
    user.setAge(500);
    userMapper.updateById(user);

}

先执行插入操作,创建时间和更改时间同步更新了
在这里插入图片描述

再执行修改操作,创建时间没有改变,更新时间变化了。
在这里插入图片描述

这种写法在时间的更新上很常用,我们下篇再见…(∩_∩)~

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值