Mybatis-Plus 5分钟快速上手,10分钟熟练使用

小伙伴们好,欢迎关注,一起学习,无限进步
以下为学习 mybatis-plus 过程中的笔记

mybatis-plus 官网地址:https://mp.baomidou.com/

特性

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

快速开始

1、创建数据库 mybatisplus

2、创建表、添加数据

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

3、使用 SpringBoor 初始化项目,导入依赖

<!-- MySQL 连接驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mybatis-plus 依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.1</version>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

注意:不要同时导入 mybatis 和 mybatis-plus

4、配置连接数据库

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

5、依次创建实体、DAO层接口

实体

package com.ss.entity;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Long id; // 注意:mybatis-plus 默认识别的是id, 如果不是id的名称,需要加上@TableId注解
    private String name;
    private Integer age;
    private String email;
}

mapper 接口

package com.ss.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ss.entity.User;
import org.apache.ibatis.annotations.Mapper;

public interface UserMapper extends BaseMapper<User> {
}

启动添加扫描所有 Mapper 文件夹

@MapperScan("com.ss.mapper")

7、使用 junit 测试

package com.ss;

import com.ss.entity.User;
import com.ss.mapper.UserMapper;
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
    void contextLoads() {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }

}

mybatis-plus 配置

#mybatis-plus 配置
mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  #实体扫描,多个package用逗号或者分号分隔,类型对应的别名
  type-aliases-package: com.ss.mybatisplus.entity
  # 枚举类 扫描路径,如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性 默认值 null
#  type-enums-package: com.baomidou.springboot.entity.enums
  # 原生配置
  configuration:
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 枚举t
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
    # 全局映射是否开启缓存
    cache-enabled: false
    # 查询时,关闭关联对象即时加载以提高性能
    lazy-loading-enabled: false
    # Mybatis 一级缓存,默认为 SESSION,同一个 session 相同查询语句不会再次查询数据库,STATEMENT 关闭一级缓存
    local-cache-scope: session
    # 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果
    multiple-result-sets-enabled: true
    # 允许使用列标签代替列名
    use-column-label: true
    jdbc-type-for-null: 'null'
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 不允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖
    use-generated-keys: false
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 给予被嵌套的resultMap以字段-属性的映射支持 NONE,FULL,PARTIAL
    auto-mapping-behavior: partial
  # 全局配置
  global-config:
    # 是否显示 mybatis-plus LOGO
    banner: false
    # 数据库相关配置
    db-config:
      #主键类型 默认assign_id, AUTO:"数据库ID自增", INPUT:"用户输入ID",assign_id:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: auto
      # 字段验证策略之 insert,在 insert 的时候的字段验证策略, 默认值 NOT_NULL
      insert-strategy: not_null
      # 字段验证策略之 update,在 update 的时候的字段验证策略, 默认值 NOT_NULL
      update-strategy: not_null
      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件, 默认值 NOT_NULL
      where-strategy: not_null
      #数据库大写下划线转换 默认值 false
      capital-mode: true
      # 表名是否使用驼峰转下划线命名,只对表名生效 默认为 true
      table-underline: false
      # 表前缀
#      table-prefix: sys_
      # 配置逻辑删除规则 1代表删除 0代表未删除
      logic-delete-value: 1  # 默认是1
      logic-not-delete-value: 0 # 默认值0

常用配置

# MyBatis-plus配置
mybatis-plus:
  #实体扫描,多个package用逗号或者分号分隔
  typeAliasesPackage: com.ss.demo.entity
  # xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)
  mapper-locations: classpath*:mapper/**/*Mapper.xml
  configuration:
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 是否开启缓存
    cache-enabled: false
    jdbc-type-for-null: 'null'
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    db-config:
      # 主键类型 默认assign_id auto:"数据库ID自增"
      id-type: auto
      # 配置逻辑删除规则 1代表删除 0代表未删除
      logic-delete-value: 1
      logic-not-delete-value: 0

插入测试及雪花算法

添加(以下内容实在 springboot 测试类中测试)

@Test
void  testInsert(){
    User user = new User();
    user.setName("我爱学习");
    user.setAge(11);
    user.setEmail("123@qq.com");
    // 此时没有设置id,会自动生成id
    int insert = userMapper.insert(user);
    System.out.println(insert);
    System.out.println(user);
}

主键生成策略

  • 默认 ASSIGN_ID 全局唯一id,@TableId(type = IdType.ASSIGN_ID)主键生成策略使用雪花算法(默认策略)
  • 主键自增 @TableId(type = IdType.AUTO),数据库中的 id 字段必须设置为自增
  • @TableId(type = IdType.NONE) 未设置主键
  • @TableId(type = IdType.INPUT) 手动输入,设置完后需要手动设置 id
  • @TableId(type = IdType.ASSIGN_ID) 雪花算法生成全局唯一id
  • @TableId(type = IdType.ASSIGN_UUID) UUID 生成策略

对应的源码为

public enum IdType {
    AUTO(0),
    NONE(1),
    INPUT(2),
    ASSIGN_ID(3),
    ASSIGN_UUID(4);

    private final int key;

    private IdType(int key) {
        this.key = key;
    }

    public int getKey() {
        return this.key;
    }
}
查询
// 使用 Condition,先判断条件是否满足 
@Test
void testCondition(){
    String name = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like(StringUtils.isNotBlank(name),"name",name) // 先判断条件是否满足条件
        .ge(ageBegin!= null,"age",ageBegin)
        .le(ageEnd!= null,"age",ageEnd);
    final List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}

// Lambda查询,通过实体属性获取映射字段名
@Test
void testLambdaQuery(){
    String name = "a";
    Integer ageBegin = null;
    Integer ageEnd = 30;
    LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
    queryWrapper.like(StringUtils.isNotBlank(name),User::getName,name)
        .ge(ageBegin!= null,User::getAge,ageBegin)
        .le(ageEnd!= null,User::getAge,ageEnd);
    final List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}
更新
// 更新
@Test
void  testUpdate(){
    User user = new User();
    user.setId(6L);
    user.setName("我爱学习11111 ");
    // 此时没有设置id,会自动生成id
    int count = userMapper.updateById(user);
    System.out.println(count);
}

// 根据指定条件修改
@Test
void testUpdate2() {
    // 将年两大于20并且用户中包含a 或者邮箱为 null 的用户信息修改
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.gt("age", 20)
        .like("name", "a")
        .or()  // 默认是用 and 连接
        .isNull("email");
    User user = new User();
    user.setName("张三");
    final int update = userMapper.update(user, queryWrapper);
    System.out.println("count:" + update);
}

// 通过 UpdateWrapper 修改
@Test
void testUpdateWrapper() {
    // 将年两大于20并且用户中包含a 或者邮箱为 null 的用户信息修改
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.like("name", "a")
        .and(i -> i.gt("age", "20").or().isNull("email")); // lambada 会优先执行
    updateWrapper.set("name", "老王")
        .set("email", "123@qq.com");
    final int update = userMapper.update(null, updateWrapper);
    System.out.println("count:" + update);
}

// 使用 LambdaUpdateWrapper 修改
@Test
void testLambdaUpdate() {
    // 将年两大于20并且用户中包含a 或者邮箱为 null 的用户信息修改
    LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
    updateWrapper.like(User::getName, "a")
        .and(i -> i.gt(User::getAge, "20").or().isNull(User::getEmail)); // lambada 会优先执行
    updateWrapper.set(User::getName, "老王")
        .set(User::getEmail, "123@qq.com");
    final int update = userMapper.update(null, updateWrapper);
    System.out.println("count:" + update);
}
删除
@Test
void testDelete() {
    // 删除邮箱的地址为 null的用户信息
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.isNull("email");
    final int delete = userMapper.delete(queryWrapper);
    System.out.println("count:" + delete);
}
查询指定字段
@Test
void testFields(){
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.select("name","name","email");
    final List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
    maps.forEach(System.out::println);
}
子查询
@Test
void testChildrenSelect(){
    // 查询id小于等于100的用户信息
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.inSql("id","select id from user where id <= 100");
    final List<User> list = userMapper.selectList(queryWrapper);
    list.forEach(System.out::println);
}

自动填充

1、修改表结构

ALTER TABLE `mybatisplus`.`user` 
ADD COLUMN `create_time` datetime NULL COMMENT '创建时间' AFTER `email`,
ADD COLUMN `update_time` datetime NULL COMMENT '修改时间' AFTER `create_time`;

2、实体添加对应的字段

// 添加是填充时间
@TableField(fill = FieldFill.INSERT)
private Date updateTime;

// 添加和修改时都填充时间
@TableField(fill = FieldFill.INSERT)
private Date createTime;

3、自定义处理器处理时间,官网地址:https://mp.baomidou.com/guide/auto-fill-metainfo.html

package com.ss.handler;

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * mybatis-plus 自动填充设置
 */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    // 插入的时候填充策略
    @Override
    public void insertFill(MetaObject metaObject) {
        // 方法1
        metaObject.setValue("createDate", LocalDateTime.now());
        metaObject.setValue("createBy", LocalDateTime.now());
        // 方法2 使用 时间格式或者使用以下时间戳
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date()); 
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date()); 
        // 方法3
        this.setFieldValByName("createBy", "admin", metaObject);
        // 起始版本 3.3.0(推荐使用)
        // this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
        // 或者
//        this.strictInsertFill(metaObject, "createTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
        // 或者
//        this.fillStrategy(metaObject, "createTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
    }

    // 修改的时候填充策略
    @Override
    public void updateFill(MetaObject metaObject) {
        // 起始版本 3.3.0(推荐)
        this.strictUpdateFill(metaObject, "updateTime",Date.class,new Date()); 
        this.setFieldValByName("lastModifiedBy", "admin", metaObject);
        // 或者
//        this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
        // 或者
//        this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
    }
}

配置完成,测执行以上添加、更新即可

乐观锁

乐观锁:非常乐观,总是认为没有问题,无论干什么都不会上锁

悲观锁:非常悲观,总是认为会出问题,无论干什么搜索加锁

当要更新一条记录的时候,希望这条记录没有被别人更新

乐观锁实现方式:

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

测试 mybatis-plus 乐观锁

1、给数据库添加字段

ALTER TABLE `mybatisplus`.`user` 
ADD COLUMN `version` int(10) NOT NULL DEFAULT 1 COMMENT '乐观锁' AFTER `email`;

2、实体类添加对应的字段

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

说明:

  • 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
  • 整数类型下 newVersion = oldVersion + 1
  • newVersion 会回写到 entity
  • 仅支持 updateById(id)update(entity, wrapper) 方法
  • update(entity, wrapper) 方法下, wrapper 不能复用!!!

3、添加 MybatisPlusConfig 配置类

package com.ss.config;

import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * mybatis-plus 配置类
 */
@EnableTransactionManagement
@Configuration
public class MyBatisConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }
}

测试乐观锁

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

// 测试乐观锁失败,模拟多线程下,注意版本号开始一定要存在
@Test
public void testOptimisticLocker2() {
    // 线程 1
    User user = userMapper.selectById(6L);
    user.setName("11111");
    user.setEmail("111@qq.com");
    // 模拟另外一个线程执行了插队操作
    User user2 = userMapper.selectById(6L);
    user2.setName("22222");
    user2.setEmail("22222@qq.com");
    userMapper.updateById(user2);
    // 如果没有乐观锁就会覆盖插队线程的值
    userMapper.updateById(user);
}

通用枚举

数据库表添加字段

ALTER TABLE `mybatisplus`.`user` 
ADD COLUMN `sex` int(2) NULL COMMENT '性别' AFTER `email`;

枚举类添加性别

import com.baomidou.mybatisplus.annotation.EnumValue;
import lombok.Getter;

@Getter
public enum SexEnum {
    MALE(1,"男"),
    FEMALE(1,"女");

    @EnumValue  // 将注解所表示的属性的值存储在数据库中
    private Integer sex;
    private String sexName;

    SexEnum(Integer sex, String sexName) {
        this.sex = sex;
        this.sexName = sexName;
    }
}

实体添加对应的性别枚举

private SexEnum sex;

配置文件添加枚举包扫描

#mybatis-plus 配置
mybatis-plus:
  # 枚举类 扫描路径,如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性 默认值 null
  type-enums-package: com.ss.mybatisplus.enums

测试代码,添加数据

@Test
public void testEnum() {
    User user = new User();
    user.setName("admin");
    user.setAge(23);
    user.setSex(SexEnum.MALE);
    final int result = userMapper.insert(user);
    System.out.println("result:" + result);
}

代码自动生成器

方式一(新版)

1、引入依赖

注意:MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.5.1</version>
</dependency>
<!-- 使用 freemarker 模板引擎 -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.31</version>
</dependency>

2、相关代码

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;

public class GeneratorTest {
    public static void main(String[] args) {
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8","root","root")
                .globalConfig(builder -> {
                    builder.author("ss")  //设置作者
//                    .enableSwagger() //开启swagger
                    .fileOverride() //覆盖已生成的文件
                    .outputDir("D://mybatis_plus"); //指定输出目录
                }).packageConfig(builder -> {
                    builder.parent("com.ss") // 设置父报名
                            .moduleName("mybatisplus") //设置父包模块名
//                            .entity("entity")  // 设置包名
//                            .mapper("mapper")
//                            .service("service")
//                            .controller("controller")
//                            .serviceImpl("impl")
                            .pathInfo(Collections.singletonMap(OutputFile.mapper,"D://mybatis_plus")); // 设置Mapper.xml生成路径
        }).strategyConfig(builder -> {
            builder.addInclude("user")  // 设置需要生成的表名,可以是一个集合
                   .addTablePrefix("t_","sys_"); // 设置过滤表前缀
        }).templateEngine(new FreemarkerTemplateEngine()) // 使用 Freemarker
        .execute();
    }
}

方式二(旧版)

1、引入依赖

注意:MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>3.4.1</version>
</dependency>

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>2.3</version>
</dependency>

2、编写代码生成类

官网地址:链接

mport com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import java.util.ArrayList;
// 代码自动生成器
public class GeneratorCodeTest {
    public static void main(String[] args) {
        // 需要构建一个 代码自动生成器 对象
        AutoGenerator mpg = new AutoGenerator();
        // 配置策略
        // 1、全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir"); // 项目所在路径
        gc.setOutputDir(projectPath+"/mybatisplus-demo/src/main/java"); //完整路径
        gc.setAuthor("ss");
        gc.setOpen(false);
        gc.setFileOverride(false); // 是否覆盖
        gc.setServiceName("%sService"); // 去Service的I前缀
        gc.setIdType(IdType.AUTO); // id生成策略
        gc.setDateType(DateType.ONLY_DATE);  // 时间策略
        gc.setSwagger2(true);  // 是否开启swagger
        mpg.setGlobalConfig(gc);
        //2、设置数据源
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/gulimall_pms?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        dsc.setDbType(DbType.MYSQL); // 数据库类型
        mpg.setDataSource(dsc);
        //3、包的配置
        PackageConfig pc = new PackageConfig();
//        pc.setModuleName("blog");  // 模块名 默认 ""
        pc.setParent("com.ss");  // 对应的包名
        pc.setEntity("entity");
        pc.setMapper("mapper");
        pc.setService("service");
        pc.setController("controller");
        mpg.setPackageInfo(pc);
        //4、策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setInclude("pms_attr"); // 设置要映射的表名 支持多个表名
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true); // 自动lombok;
        strategy.setLogicDeleteFieldName("deleted");
        // 自动填充配置
        TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
        TableFill gmtModified = new TableFill("gmt_modified",
                FieldFill.INSERT_UPDATE);
        ArrayList<TableFill> tableFills = new ArrayList<>();
        tableFills.add(gmtCreate);
        tableFills.add(gmtModified);
        strategy.setTableFillList(tableFills);
        // 乐观锁
        strategy.setVersionFieldName("version");
        strategy.setRestControllerStyle(true);
        strategy.setControllerMappingHyphenStyle(true); //
        mpg.setStrategy(strategy);
        mpg.execute(); //执行
    }
}

分页插件

@Configuration
@EnableTransactionManagement //开启事务
public class MyBatisPlusConfig {

    // 旧版
    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor(){
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        //设置请求的页面大于最大页后操作,true调回到首页,false继续请求,默认为false
        paginationInnerInterceptor.setOverflow(true);
        //设置最大单页限制数量,默认500条,-1不受限制
        paginationInnerInterceptor.setMaxLimit(1000L);
        //数据库类型
        paginationInnerInterceptor.setDbType(DbType.MYSQL);

        return paginationInnerInterceptor;
    }

    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

测试分页

// MyBatisPlus 插件分页,首先配置分页相关信息
@Test
void testPage(){
    Page<User> page = new Page<>(1,3);
    userMapper.selectPage(page, null);
    System.out.println(page.getRecords()); //记录
    System.out.println(page.getPages()); // 几页
    System.out.println(page.getTotal()); // 总条数
    System.out.println(page.hasNext()); // 是否有下一页
    System.out.println(page.hasPrevious());  // 是否有上一页
}

自定义分页

1、Mapper 接口

/**
* 通过年龄查询用户信息并分页
* @param page Mybatis-Plus 提供的分页对象,必须位于第一个参数的位置
* @param age
* @return
*/
Page<User> selectPageVO(@Param("page") Page<User> page,@Param("age") Integer age);

2、UserMapper.xml 对应的sql

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ss.mybatisplus.mapper.UserMapper">

    <select id="selectPageVO" resultType="User">
        select * from user where age >= #{age}
    </select>
</mapper>

3、测试查询

@Test
void testPageVO(){
    Page<User> page = new Page<>(1,3);
    userMapper.selectPageVO(page, 30);
    System.out.println(page.getRecords());
    System.out.println(page.getPages());
    System.out.println(page.getTotal());
    System.out.println(page.hasNext());
    System.out.println(page.hasPrevious());
}

多数据源

简介

介绍:dynamic-datasource-spring-boot-starter 是一个基于 springboot 的快速集成多数据源的启动器。

特性

  • 支持 数据源分组 ,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
  • 支持数据库敏感配置信息 加密 ENC()。
  • 支持每个数据库独立初始化表结构schema和数据库database。
  • 支持无数据源启动,支持懒加载数据源(需要的时候再创建连接)。
  • 支持 自定义注解 ,需继承DS(3.2.0+)。
  • 提供并简化对Druid,HikariCp,BeeCp,Dbcp2的快速集成。
  • 提供对Mybatis-Plus,Quartz,ShardingJdbc,P6sy,Jndi等组件的集成方案。
  • 提供 自定义数据源来源 方案(如全从数据库加载)。
  • 提供项目启动后 动态增加移除数据源 方案。
  • 提供Mybatis环境下的 纯读写分离 方案。
  • 提供使用 spel动态参数 解析数据源方案。内置spel,session,header,支持自定义。
  • 支持 多层数据源嵌套切换 。(ServiceA >>> ServiceB >>> ServiceC)。
  • 提供 基于seata的分布式事务方案。
  • 提供 本地多数据源事务方案

约定

  1. 本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
  2. 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
  3. 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。
  4. 默认的数据源名称为 master ,你可以通过 spring.datasource.dynamic.primary 修改。
  5. 方法上的注解优先于类上注解。
  6. DS支持继承抽象类上的DS,暂不支持继承接口上的DS。

使用方法

添加相关依赖
<!-- Mysql驱动包 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- Mybatis-plus 依赖 -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.8</version>
</dependency>

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>
修改配置
spring:
  datasource:
    dynamic:
      # 设置默认的数据源或者数据源组,默认值即为master
      primary: master
      # 严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
          url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
        slave_1:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/dtcms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
        slave_2:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/renren?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
使用 @DS 切换数据源

@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

注解结果
没有@DS默认数据源
@DS(“dsName”)dsName可以为组名也可以为具体某个库的名称
相关代码

实体

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

    private Integer sex;

    private Integer version;
}
@Data
@TableName("sys_role")
public class Role {

    private Long id;
    private String name;
    private String remark;
}

Mapper接口

@Mapper
@DS("master")
public interface UserMapper extends BaseMapper<User> {}
@Mapper
@DS("slave_1")
public interface RoleMapper extends BaseMapper<Role> {}

Service接口

public interface UserService extends IService<User> {}
public interface RoleService extends IService<Role> {}

ServiceImpl实现类

@DS("master")
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {}
@Service
@DS("slave_1")
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements RoleService {}

测试

@SpringBootTest
class DemoApplicationTests {
    @Autowired
    private UserService userService;
    @Autowired
    private RoleService roleService;
    
    @Test
    void contextLoads() {
        // 直接使用 service方法
//        System.out.println(userService.getById(1L));
//        System.out.println(roleService.getById(9L));
        // Mapper方法
        final List<Role> roleList = roleService.getBaseMapper().selectList(null);
        roleList.forEach(System.out::println);
        System.out.println("=======================");
        final List<User> userList = userService.getBaseMapper().selectList(null);
        userList.forEach(System.out::println);
    }
}
多数据源最全配置

使用 druid 连接池,选择添加必要的配置即可(不必都配置)

spring:
  datasource:
    dynamic:
      # 设置默认的数据源或者数据源组,默认值即为master
      primary: master
      # 严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        master:
          driver-class-name: com.mysql.cj.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
          url: jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
        slave_1:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/dtcms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
        slave_2:
          driver-class-name: com.mysql.cj.jdbc.Driver
          url: jdbc:mysql://localhost:3306/renren?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
          username: root
          password: root
    # 使用druid数据库连接池
    type: com.alibaba.druid.pool.DruidDataSource
    # druid 全局配置
    druid:
      # 初始连接数
      initial-size: 5
      # 最小连接池数量
      min-idle: 10
      # 最大连接池数量
      max-active: 20
      # 获取配置连接等待超时时间
      max-wait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      time-between-connect-error-millis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      min-evictable-idle-time-millis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      max-evictable-idle-time-millis: 900000
      # 配置检测连接是否有效
      validation-query: SELECT * FROM DUAL
      # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效
      test-while-idle: true
      # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      test-on-borrow: false
      # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
      test-on-return: false
      # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。
      keep-alive: true
      # 物理超时时间,默认:-1
      phy-timeout-millis: -1
      # 物理最大连接数,默认:-1(不建议配置)
      phy-max-use-count: -1
      # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
      filters: stat,wall,slf4j,config
      # 是否启用web-stat-filter默认值false
      web-stat-filter:
        enabled: true
      # 是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
      stat-view-servlet:
        enabled: true
        # 设置白名单,不填则允许所有访问
        allow: /druid/*
        login-username:
        login-password:

#mybatis-plus 配置
mybatis-plus:
  mapper-locations: classpath:/mapper/*Mapper.xml
  #实体扫描,多个package用逗号或者分号分隔
  type-aliases-package: com.example.demo.entity
  # 枚举类 扫描路径,如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性 默认值 null
  type-enums-package: com.example.demo.enums
  # 原生配置
  configuration:
    # 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射
    map-underscore-to-camel-case: true
    # 全局映射是否开启缓存
    cache-enabled: false
    # 查询时,关闭关联对象即时加载以提高性能
    lazy-loading-enabled: false
    # Mybatis 一级缓存,默认为 SESSION,同一个 session 相同查询语句不会再次查询数据库,STATEMENT 关闭一级缓存
    local-cache-scope: session
    # 对于未知的SQL查询,允许返回不同的结果集以达到通用的效果
    multiple-result-sets-enabled: true
    # 允许使用列标签代替列名
    use-column-label: true
    jdbc-type-for-null: 'null'
    # 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段
    call-setters-on-nulls: true
    # 不允许使用自定义的主键值(比如由程序生成的UUID 32位编码作为键值),数据表的PK生成策略将被覆盖
    use-generated-keys: false
    # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 给予被嵌套的resultMap以字段-属性的映射支持 NONE,FULL,PARTIAL
    auto-mapping-behavior: partial
  # 全局配置
  global-config:
    # 是否显示 mybatis-plus LOGO
    banner: false
    # 数据库相关配置
    db-config:
      #主键类型 默认assign_id, AUTO:"数据库ID自增", INPUT:"用户输入ID",assign_id:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";
      id-type: auto
      # 字段验证策略之 insert,在 insert 的时候的字段验证策略, 默认值 NOT_NULL
      insert-strategy: not_null
      # 字段验证策略之 update,在 update 的时候的字段验证策略, 默认值 NOT_NULL
      update-strategy: not_null
      # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件, 默认值 NOT_NULL
      where-strategy: not_null
      #数据库大写下划线转换 默认值 false
      capital-mode: false
      # 表名是否使用驼峰转下划线命名,只对表名生效 默认为 true
      table-underline: false
      # 表前缀
      #      table-prefix: sys_
      # 配置逻辑删除规则 1代表删除 0代表未删除
      logic-delete-value: 1  # 默认是1
      logic-not-delete-value: 0 # 默认值0

maven插件自动生成策略可参考

https://gitee.com/baomidou/mybatisplus-maven-plugin?_from=gitee_search
  • 32
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

师小师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值