官网地址: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、自定义处理器处理时间,官网地址
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的分布式事务方案。 -
提供 本地多数据源事务方案
约定
-
本框架只做 切换数据源 这件核心的事情,并不限制你的具体操作,切换了数据源可以做任何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:
# 设置默认的数据源或者数据源组,默认值即为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
以上内容是学习 MyBatis-Plus 过程中的一个记录:尚硅谷视频地址
maven插件自动生成策略可参考:地址
原文始发于微信公众号(师小师):一起学 Mybatis-Plus(三分钟上手,五分钟学会)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/226302.html