MyBatisPlus详解

本次笔记来自狂神说以及官网
官网:https://baomidou.com/pages/24112f/

MyBatisPlus详解

1.MyBatisPlus概述

1.1 为什么要学MyBatisPlus(MP)?

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

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

注意点:
CURD代表创建(Create)、更新(Update)、读取(Retrieve)和删除(Delete)操作。

1.2 MP 特性

  • 无侵入:
    只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:
    启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.快速开始

2.0 注意点

  1. 如果数据库表名和实体类名不一样,
    加上注解@TableName(“name”),值就是数据库的表名

  2. 如果数据库的字段名和实体类的变量不一致,
    加上注解@TableField(“name”),值就是数据库的字段名

  3. 全局配置策略
    博客:https://cloud.tencent.com/developer/article/1809566

2.1 使用第三方组件步骤

1、导入对应的依赖
2、研究依赖如何配置
3、代码如何编写
4、提高扩展技术能力!

2.2 创建数据库(user)

在这里插入图片描述

2.3 使用SpringBoot初始化

2.4 pom.xml

<!--        数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
<!--        mybatis-plus 导mybatis-plus就不用导mybatis-->
<!--        mybatis-plus 是自己开发,并非官方的-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.0.5</version>
        </dependency>

说明:
我们使用mybatis-plus可以节省我们大量的代码,尽量不要同时导入mybatis和mybatis-plus !版本的差异!

2.5 aplication.yml

spring:
  datasource:
    username: root
    password: zjj
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&userUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
#mysql 8 驱动不同com.mysql.cj.jdbc.Driver,并且需要增加时区的配置 
#UTC 或 serverTimezone=GMT%2B8 但serverTimezone=GMT%2B8可以防止有时差

2.6 idea 连接数据库(可不配)

如果出现这个错误:下载失败Driver files are not download
解决方法:
1.Driver:MySQL>Go to Driver
2. 博客:https://www.jianshu.com/p/e13b459f73c8
加入你对应的数据库jar包
3.就成功了,输入密码,用户,测试连接
注意: 这边可能会出现 连接失败 时区问题
Server returns invalid timezone. Go to ‘Advanced’ tab and set 'serverTimezon
博客:https://blog.csdn.net/qq_43598138/article/details/103772854
在Database中输入你的数据库+?useSSL=false&serverTimezone=UTC
4.如果成功了却没有数据
记得在Schemas中选择你对应的数据库。

2.7 pojo

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data

@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
public User(String name, Integer age, String email) {
    this.name = name;
    this.age = age;
    this.email = email;
}

2.8 mapper

import cn.zjj.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springframework.stereotype.Repository;

// 对应的Mapper上面继承基本的类BaseMapper
@Repository//表示它是Dao层的 代表持久层的
public interface UserMapper extends BaseMapper<User> {
    //所有的CRUD操作都已经编写完成了
    //你不需要像以前的配置一大堆文件了!
}

2.9 xxxApplication

//扫描并识别
//在主启动类上去扫描我们的mapper包下的所有接口
@MapperScan("cn.zjj.mapper")
@SpringBootApplication
public class Mybatisplus0119Application {

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

}

2.10 xxxApplicationTests

import cn.zjj.mapper.UserMapper;
import cn.zjj.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 Mybatisplus0119ApplicationTests {
    //继承了BaseMapper,所有的方法都来自己父类
    //我们也可以编写自己的扩展方法!
    @Autowired
    private UserMapper userMapper;
    @Test
    void contextLoads() {
        //参数是一个Wrapper,条件构造器,这里我们先不用null
        //查询全部用户
        List<User> list = userMapper.selectList(null);
        list.forEach(System.out::println);
    }

}

结果:
在这里插入图片描述
注意到没有,我们不需要写xxxMapper.xml,和里面的sql语句,和xxxMapper里的查询方法
这些MyBatis-Plus都帮我们写好了。

2.11 优化》配置日志

我们所有的sql现在是不可见的,
我们希望知道它是怎么执行的,所以我们必须要看日志!
日志能体现具体的步骤.

开发时需要上线时去掉 不然会耗资源

aplication.yml

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

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

3.CRUD扩展

3.1 Insert插入

xxxApplicationTests

@Test
public void testIn(){
    User user = new User("asdf",3,"asdasdsaf@qq.com");
    int i = userMapper.insert(user);//帮我们自动生成id
    System.out.println(i);//受影响的行数
    System.out.println(user);//id会自动回填
}

在这里插入图片描述
Preparing:
INSERT INTO user ( id,name, age, email) VALUES ( ?, ?, ?, ? )

3.2 主键生成策略(题外话)

3.2.1 (默认)ID_WORKER全局唯一id

@TableId(type = IdType.ID_WORKER)
private Long id;

但为什么id会出现一长串数字 ,这边用了雪花算法

实体类中的id对应数据库中的主键
(uuid\自增id\雪花算法\redis\zookeeper)

博客: https://www.cnblogs.com/haoxinyue/p/5208136.html

注意: 本次数据库中的id没有设置自增长 ,下面设置了。

3.2.2 主键自增

我们需要配置主键自增:
1.实体类字段上@TableId(type = IdType.AUTO)
2.数据库字段一定要是自增!

不然只写注解会报错

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

3.2.3 其他的源码解释

public enum IdType {
    AUTO(0),//数据库id自增
    NONE(1),//未设置主键 }一旦手动输入id之后,就需要主键配置id了  6L
    INPUT(2),//手动输入
    ID_WORKER(3),//默认的全局唯一id
    UUID(4),//全局唯一id uuid
    ID_WORKER_STR(5);//ID——WORKER 字符串表示法
}

3.3 update更新

xxxApplicationTests

@Test
public void testUp(){
    User user = new User();
    //通过条件自动拼接动态sql
    user.setId(5L);
    user.setName("wang");

    //主要:updateById但是参数是一个对象
    int i = userMapper.updateById(user);
    System.out.println(i);
}

结果:
在这里插入图片描述
如果我再加 user.setAge(21);
在这里插入图片描述

所有的sql自动帮你动态配置的

4.自动填充

4.1 概念

创建时间、修改时间!
这些操作都是自动化完成的,我们不希望手动更新!

阿里巴巴开发手册:
所有的数据库表: gmt_create、gmt_modified几乎所有的表都要配置上!而且需要自动化!

4.2 方式一:数据库级别

(工作中不允许你修改数据库!)

1.在表中新增字段 create_time、update_time
默认值 改成 当前时间》 CURRENT_TIMESTAMP
更新操作 》更新时间需要勾上自动更新
在这里插入图片描述
注意: navicat 没有CURRENT_TIMESTAMP
只能重新写sql然后字段后面加
DEFAULT CURRENT_TIMESTAMP(0)

2.再次测试插入方法,我们需要先把实体类同步!

private Date createTime;
private Date updateTime;

再次进行更新
到时候所有的都有时间了,都是默认的
你更新的那个update_time(更新)也变成实时更新的

4.3 方式二:代码级别

1.先把前面设置的默认格式 和更新都删除

2.书体类字段属性加注解 Field(字段)fill 填充

//字段添加填充内容
@TableField(fill = FieldFill.INSERT)//插入的时候更新
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//插入和更新的时候更新 
private Date updateTime;

默认是FieldFill.default 》不操作

3.编写处理器来处理这个注解即可!

新建一个handler包 》
然后新建个类》原数据处理 MetaObjectHandler

MyMetaObjectHandler

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.util.Date;

@Slf4j//日志
@Component // 一定不要忘记把处理器加到IOC容器中!
public class MyMetaObjectHandler implements MetaObjectHandler {
    //插入时的填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill .....");//打印
        //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("start update fill .....");
        this.setFieldValByName("updateTime",new Date(),metaObject);
    }
}
//mybatis会自动处理该处理器
//执行插入的时候 通过反射自动的去读取你那边有对应注解的值,从而这段代码执行成功
//只要插入了,自动的帮你createTime 自动的填充new Date()的值

这样只要你插入和更新,那么对应的值都会实时更新。

注意 导的时间类型包 要和实体类保持一致

5.乐观锁

5.1 概念

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

乐观锁和version一起用
判断版本号是否更新了 来确定这个数据有没有更新

5.2 乐观锁实现方式

1.取出记录时,获取当前 version
2.更新时,带上这个 version
3.执行更新时, set version = newVersion where version = oldVersion
4.如果 version 不对,就更新失败
在这里插入图片描述

5.3 乐观锁实现详解(MP)

5.3.1 给数据库中增加version字段!

默认值为1 》 初始版本
在这里插入图片描述

5.3.2 我们实体类加对应的字段

@Version//乐观锁Version 注解 
private Integer version;

5.3.3 注册组件

1.写自己的配置,一般先建config包然后建MyBatisPlusConfig类

2.首先他要是配置类,加个注解@Configuration(Springboot里的 )

3.如果有事务控制的话,加个注解@EnableTransactionManagement
自动管理事务开启 默认是开启的

4.也可以把扫描包放在配置类(mybatis配置类要做的 让它去做扫描)
@MapperScan(“cn.zjj.mapper”)//扫描我们的mapper文件夹
不一定要放在启动函数

代码:

@MapperScan("cn.zjj.mapper")//扫描我们的mapper文件夹
@EnableTransactionManagement
@Configuration //配置类
public class MyBatisPlusConfig {
    //注册乐观锁插件
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor(){
        return new OptimisticLockerInterceptor();
    }
}

Interceptor拦截器在所有进行操作的时候自动进行拦截进行自动化的处理

5.3.4 测试

1.成功

//测试乐观锁成功! 单线程
@Test
public void testOptimisticLocker(){
    //1. 查询用户信息
    User user = userMapper.selectById(1L);
    //2.修改用户信息
    user.setName("happy");
    user.setEmail("131242526@qq.com");
    //3.执行更新操作
    userMapper.updateById(user);
}

在这里插入图片描述
Preparing:
SELECT id,name,age,email,version,create_time,update_time FROM user WHERE id=?

Preparing:
UPDATE user SET name=?, age=?, email=?, version=?, create_time=?, update_time=? WHERE id=? AND version=?

》version =2 变了 修改成功

2.失败

//测试 乐观锁失败! 多线程下
@Test
public void testOptimisticLockerNo(){
    //线程一
    User user = userMapper.selectById(1L);
    user.setName("happy111");
    user.setEmail("131242526@qq.com");
    //模拟另外一个线程执行了插队操作
    User user2 = userMapper.selectById(1L);
    user2.setName("happy222");
    user2.setEmail("131242526@qq.com");
    userMapper.updateById(user2);

    //如果想要解决 可以使用自旋锁来多次尝试提交!
    userMapper.updateById(user);//如果没有乐观锁就会覆盖插队线程的值!
    //线程一设置了值 但是还没有更新 另外个线程设置了值并抢先更新
    // 在并发情况下 被抢先 线程一的更新可能不会执行
}

Preparing:
UPDATE user SET name=?, age=?, email=?, version=?, create_time=?, update_time=? WHERE id=? AND version=?

》 version 为2

Preparing:
UPDATE user SET name=?, age=?, email=?, version=?, create_time=?, update_time=? WHERE id=? AND version=? AND deleted=0

》 version 为2
两个sql都是拿2去改 按道理第一个改完就变成三了
如果非要执行,可以使用自旋锁
在这里插入图片描述

6.查询操作

6.1 查询某段

@Test
public void testSelectById(){
    User user = userMapper.selectById(1L);
    System.out.println(user);
}

Preparing:
SELECT id,name,age,email,create_time,update_time FROM user WHERE id=?

6.2 查询多段 批量 用户

@Test
public void testSelectByBatchId(){
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
    users.forEach(System.out::println);
}

Preparing:
SELECT id,name,age,email,create_time,update_time FROM user WHERE id IN ( ? , ? , ? )

6.3 按条件查询之一 使用map操作

@Test
public void test01(){
    HashMap<String, Object> map = new HashMap<>();
    //自定义查询
    map.put("name","Tom");
    map.put("age",28);
    List<User> users = userMapper.selectByMap(map);
    users.forEach(System.out::println);
}

Preparing:
SELECT id,name,age,email,create_time,update_time FROM user WHERE name = ? AND age = ?

6.4 分页查询

6.4.1 主要有三种方式可以实现分页

  1. 原始的limit进行分页
  2. pageHelper 第三方插件
  3. MP其实也内置了分页插件!

6.4.2 如何使用

用拦截器配置的

1.配置拦截器组件即可
MyBatisPlusConfig

//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
    return new PaginationInterceptor();
}

2.直接使用Page对象即可!

//测试分页查询
@Test
public void testPage(){
    //当前页:第一页 页面大小:每页只有五个
	//使用了分页插件后,所有的分页操作也变得简单了

    Page<User> page = new Page<>(1, 5);
    userMapper.selectPage(page,null);
    // 记录 遍历 输出
    page.getRecords().forEach(System.out::println);
	System.out.println(page.getTotal());
}

Preparing:
SELECT COUNT(1) FROM user

Preparing:
SELECT id,name,age,email,create_time,update_time FROM user LIMIT 0,5

7.删除操作

7.1 删除某段

@Test
public void testDeleteById(){
    userMapper.deleteById(1484069334090285061L);
}

Preparing:
DELETE FROM user WHERE id=?

7.2 通过id批量删除

@Test
public void testDeleteBatchId(){
    userMapper.deleteBatchIds(Arrays.asList(1484069334090285059L,1484069334090285060L));
}

Preparing:
DELETE FROM user WHERE id IN ( ? , ? )

7.3 通过map删除

@Test
public void testDeleteMap(){
    HashMap<String, Object> map = new HashMap<>();
    map.put("name","asdf");
    userMapper.deleteByMap(map);
}

Preparing:
DELETE FROM user WHERE name = ?

我们在工组中会遇到一些问题:逻辑删除!

8.逻辑删除

8.1 对比

物理删除: 从数据库中直接移除

逻辑删除:
在数据库中没有被移除,而是通过一个变量来让他失效!
deleted = 0 => deleted = 1

管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!

8.2 测试

8.2.1 在数据库表中增加一个deleted字段

默认值为0 代表没有被删除掉
在这里插入图片描述

8.2.2 实体类添加

@TableLogic //逻辑删除
private Integer deleted;

8.2.3 配置逻辑删除组件

MyBatisPlusConfig

//逻辑删除组件!
@Bean
public ISqlInjector sqlInjector(){
    return new LogicSqlInjector();
}

application.yml
#配置逻辑删除

mybatis-plus:
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0

8.2.4 测试

//测试删除
@Test
public void testDeleteById(){
    userMapper.deleteById(1484069334090285062L);
}

》走的是更新操作,并不是删除操作

记录还在,但是该用户的deleted从0变成了1

再次查询该用户,那么你会查不到该用户
(查询时候 会自动 过滤 被逻辑删除的字段)
在这里插入图片描述

9.性能分析插件

9.1 概述

我们在平时的开发中,会遇到一些慢sq|,那怎么测试出来呢?

性能分析拦截器
用于输出每条SQL语句及其执行时间
》MP也提供性能分析插件,如果超过这个时间就停止运行! .

9.2 步骤详解

9.2.1 导入插件

MyBatisPlusConfig

//SQL执行效率插件
@Bean
@Profile({"dev","test"})//设置 dev  test 环境开启,保证我们的效率 只有在测试环境和开发环境开启
public PerformanceInterceptor performanceInterceptor(){
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    performanceInterceptor.setMaxTime(10);
    //ms毫秒 设置sql执行的最大时间,如果超过了则不执行
    performanceInterceptor.setFormat(true);//是否开启格式化支持
    return performanceInterceptor;
}

记住,要在SpringBoot中配置环境为dev或者test 环境!

》设置开发环境 自动识别到dev 然后那个插件就生效了
application.yml
spring.profiles.active=dev

9.2.2 测试使用!

@Test
void contextLoads() {
    //参数是一个Wrapper,条件构造器,这里我们先不用null
    //查询全部用户
    List<User> list = userMapper.selectList(null);
    list.forEach(System.out::println);
}

测试
》查询全部用户
》超过了规定时间就会报错 异常

结果:
在这里插入图片描述
上面的代码就是格式化,看的更明白。

注意:
这个sql语句执行了30毫秒
如果你设置sql执行的最大时间<30 那么运行时会报错
而我此时设置的是10毫秒,报异常

PersistenceException》连接异常
xxx.MybatisPlusException:
The SQL execution time is too large, please optimize !
》这个sql执行的时间太大了 请你修改验证

所以作用:
以后就是超过几毫秒 xxxms的sql语句都拿出来,进行优化

使用性能分析插件,可以帮助我们提高效率!

10.条件构造器(Wrapper)

10.1 查询name不为空和邮箱不为空的用户,年龄>=12

@SpringBootTest
public class WrapperTest {
    @Autowired
    private UserMapper userMapper;
    @Test
    void contextLoads() {
        //查询name不为空的用户,并且邮箱不为空的用户,年龄大于等于12
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.isNotNull("name").isNotNull("email").ge("age",20);//ge 大于等于
        userMapper.selectList(wrapper).forEach(System.out::println);
    }

Execute SQL:
SELECT id,name,age,email,deleted,create_time,update_time FROM user WHERE deleted=0 AND name IS NOT NULL AND email IS NOT NULL AND age >= 20

10.2 查询一个数据

@Test
void test02(){
    //查询名字
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.eq("name","Tom"); //查询一个数据,出现多个结果使用List或者Map
    //eq 》 =  》 name = Tom
    User user = userMapper.selectOne(wrapper);
    System.out.println(user);
}

Execute SQL:
SELECT id,name,age,email,deleted,create_time,update_time FROM user WHERE deleted=0 AND name = ‘Tom’

10.3 查询年龄在20~30岁之间的用户

@Test
void test03(){
    //查询年龄在20~30岁之间的用户
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    wrapper.between("age",20,30);
    Integer count = userMapper.selectCount(wrapper);
    System.out.println(count);
}

Execute SQL:
SELECT COUNT(1) FROM user WHERE deleted=0 AND age BETWEEN 20 AND 30

10.4 不包含e并且邮箱号是以t开头的

@Test
void test04(){
    //模糊查询 不包含e并且邮箱号是以t开头的
    QueryWrapper<User> wrapper = new QueryWrapper<>();
    //左 %x 和右 xx%
    wrapper.notLike("name","m")
            .likeRight("email","t");
    List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
    maps.forEach(System.out::println);
}

Execute SQL:
SELECT id,name,age,email,deleted,create_time,update_time FROM user WHERE deleted=0 AND name NOT LIKE ‘%m%’ AND email LIKE ‘t%’

10.5 id 在子查询中查出来

 @Test
    void test05(){
        //id 在子查询中查出来
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.inSql("id","select id from user where id < 3");
        List<Object> objects = userMapper.selectObjs(wrapper);
        objects.forEach(System.out::println);
    }

Execute SQL:
SELECT id,name,age,email,deleted,create_time,update_time FROM user WHERE deleted=0 AND id IN (select id from user where id < 3)

10.6 通过id来进行排序

   @Test
    void test06(){
        //通过id来进行排序
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<User> users = userMapper.selectList(wrapper);
        users.forEach(System.out::println);
    }
}

Execute SQL:
SELECT id,name,age,email,deleted,create_time,update_time FROM user WHERE deleted=0 ORDER BY id DESC

10.7 附注

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

11.代码自动生成器(省略)

12.完整版application.yml

#设置开发环境 自动识别到dev 然后那个插件就生效了
spring:
  profiles:
    active: dev
  datasource:
    username: root
    password: zjj
    url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&userUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    driver-class-name: com.mysql.cj.jdbc.Driver
#数据库 连接配置

#配置日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      logic-delete-value: 1
      logic-not-delete-value: 0
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值