本文主要是介绍Mybatis-Plus 5分钟快速上手,10分钟熟练使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
小伙伴们好,欢迎关注,一起学习,无限进步
以下为学习 mybatis-plus 过程中的笔记
mybatis-plus
官网地址:https://mp.baomidou.com/
文章目录
- 特性
- 快速开始
- mybatis-plus 配置
- 插入测试及雪花算法
- 主键生成策略
- 查询
- 更新
- 删除
- 查询指定字段
- 子查询
- 自动填充
- 乐观锁
- 通用枚举
- 代码自动生成器
- 方式一(新版)
- 方式二(旧版)
- 分页插件
- 测试分页
- 多数据源
- 简介
- 特性
- 约定
- 使用方法
- 添加相关依赖
- 修改配置
- 使用 **@DS** 切换数据源
- 相关代码
- 多数据源最全配置
特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 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.Driverurl: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8username: rootpassword: 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 {@Autowiredprivate UserMapper userMapper;@Testvoid 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# 枚举tdefault-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: truejdbc-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,PARTIALauto-mapping-behavior: partial# 全局配置global-config:# 是否显示 mybatis-plus LOGObanner: false# 数据库相关配置db-config:#主键类型 默认assign_id, AUTO:"数据库ID自增", INPUT:"用户输入ID",assign_id:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";id-type: auto# 字段验证策略之 insert,在 insert 的时候的字段验证策略, 默认值 NOT_NULLinsert-strategy: not_null# 字段验证策略之 update,在 update 的时候的字段验证策略, 默认值 NOT_NULLupdate-strategy: not_null# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件, 默认值 NOT_NULLwhere-strategy: not_null#数据库大写下划线转换 默认值 falsecapital-mode: true# 表名是否使用驼峰转下划线命名,只对表名生效 默认为 truetable-underline: false# 表前缀
# table-prefix: sys_# 配置逻辑删除规则 1代表删除 0代表未删除logic-delete-value: 1 # 默认是1logic-not-delete-value: 0 # 默认值0
常用配置
# MyBatis-plus配置
mybatis-plus:#实体扫描,多个package用逗号或者分号分隔typeAliasesPackage: com.ss.demo.entity# xml扫描,多个目录用逗号或者分号分隔(告诉 Mapper 所对应的 XML 文件位置)mapper-locations: classpath*:mapper/**/*Mapper.xmlconfiguration:# 是否开启自动驼峰命名规则映射:从数据库列名到Java属性驼峰命名的类似映射map-underscore-to-camel-case: true# 是否开启缓存cache-enabled: falsejdbc-type-for-null: 'null'# 如果查询结果中包含空值的列,则 MyBatis 在映射的时候,不会映射这个字段call-setters-on-nulls: true# 这个配置会将执行的sql打印出来,在开发或测试的时候可以用log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:# 主键类型 默认assign_id auto:"数据库ID自增"id-type: auto# 配置逻辑删除规则 1代表删除 0代表未删除logic-delete-value: 1logic-not-delete-value: 0
插入测试及雪花算法
添加(以下内容实在 springboot 测试类中测试)
@Test
void testInsert(){User user = new User();user.setName("我爱学习");user.setAge(11);user.setEmail("123@qq.com");// 此时没有设置id,会自动生成idint 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,会自动生成idint 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 {// 插入的时候填充策略@Overridepublic void insertFill(MetaObject metaObject) {// 方法1metaObject.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()); // 方法3this.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)}// 修改的时候填充策略@Overridepublic 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 {@Beanpublic 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() {// 线程 1User 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:# 枚举类 扫描路径,如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性 默认值 nulltype-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); // 是否开启swaggermpg.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 {// 旧版@Beanpublic PaginationInnerInterceptor paginationInnerInterceptor(){PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();//设置请求的页面大于最大页后操作,true调回到首页,false继续请求,默认为falsepaginationInnerInterceptor.setOverflow(true);//设置最大单页限制数量,默认500条,-1不受限制paginationInnerInterceptor.setMaxLimit(1000L);//数据库类型paginationInnerInterceptor.setDbType(DbType.MYSQL);return paginationInnerInterceptor;}// 最新版@Beanpublic 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的分布式事务方案。
- 提供 本地多数据源事务方案
约定
- 本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何CRUD。
- 配置文件所有以下划线
_
分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。 - 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。
- 默认的数据源名称为 master ,你可以通过
spring.datasource.dynamic.primary
修改。 - 方法上的注解优先于类上注解。
- 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:# 设置默认的数据源或者数据源组,默认值即为masterprimary: master# 严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源strict: falsedatasource: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%2B8username: rootpassword: rootslave_1:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/dtcms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: rootslave_2:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/renren?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: 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 {@Autowiredprivate UserService userService;@Autowiredprivate RoleService roleService;@Testvoid 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:# 设置默认的数据源或者数据源组,默认值即为masterprimary: master# 严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源strict: falsedatasource: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%2B8username: rootpassword: rootslave_1:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/dtcms?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: rootslave_2:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/renren?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8username: rootpassword: 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# 物理超时时间,默认:-1phy-timeout-millis: -1# 物理最大连接数,默认:-1(不建议配置)phy-max-use-count: -1# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙filters: stat,wall,slf4j,config# 是否启用web-stat-filter默认值falseweb-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# 枚举类 扫描路径,如果配置了该属性,会将路径下的枚举类进行注入,让实体类字段能够简单快捷的使用枚举属性 默认值 nulltype-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: truejdbc-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,PARTIALauto-mapping-behavior: partial# 全局配置global-config:# 是否显示 mybatis-plus LOGObanner: false# 数据库相关配置db-config:#主键类型 默认assign_id, AUTO:"数据库ID自增", INPUT:"用户输入ID",assign_id:"全局唯一ID (数字类型唯一ID)", UUID:"全局唯一ID UUID";id-type: auto# 字段验证策略之 insert,在 insert 的时候的字段验证策略, 默认值 NOT_NULLinsert-strategy: not_null# 字段验证策略之 update,在 update 的时候的字段验证策略, 默认值 NOT_NULLupdate-strategy: not_null# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件, 默认值 NOT_NULLwhere-strategy: not_null#数据库大写下划线转换 默认值 falsecapital-mode: false# 表名是否使用驼峰转下划线命名,只对表名生效 默认为 truetable-underline: false# 表前缀# table-prefix: sys_# 配置逻辑删除规则 1代表删除 0代表未删除logic-delete-value: 1 # 默认是1logic-not-delete-value: 0 # 默认值0
maven插件自动生成策略可参考
https://gitee.com/baomidou/mybatisplus-maven-plugin?_from=gitee_search
这篇关于Mybatis-Plus 5分钟快速上手,10分钟熟练使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!