其他分享
首页 > 其他分享> > w3cschool-MyBatis-Plus 插件

w3cschool-MyBatis-Plus 插件

作者:互联网

https://www.w3cschool.cn/mybatis_plus/mybatis_plus-udwn3mgc.html

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

特性

支持数据库

任何能使用 ​MyBatis ​进行 ​CRUD​, 并且支持标准 ​SQL ​的数据库,具体支持情况如下:

MyBatis-Plus 快速入门-快速开始

2022-03-23 16:02 更新

我们将通过一个简单的 Demo 来阐述 MyBatis-Plus 的强大功能,在此之前,我们假设您已经:

现有一张 ​User ​表,其表结构如下:

 id  name  age email 
 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

其对应的数据库 ​Schema ​脚本如下:

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

其对应的数据库 ​Data ​脚本如下:

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

初始化工程

创建一个空的 Spring Boot 工程(工程将以 H2 作为默认数据库进行演示)

提示:可以使用 Spring Initializer快速初始化一个 Spring Boot 工程

添加依赖

引入 Spring Boot Starter 父工程:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.6.4</version>
    <relativePath/>
</parent>

引入 ​spring-boot-starter​、​spring-boot-starter-test​、​mybatis-plus-boot-starter​、​h2 ​依赖:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.5.1</version>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

配置

在 ​application.yml​ 配置文件中添加 ​H2 ​数据库的相关配置:

# DataSource Config
spring:
  datasource:
    driver-class-name: org.h2.Driver
    schema: classpath:db/schema-h2.sql
    data: classpath:db/data-h2.sql
    url: jdbc:h2:mem:test
    username: root
    password: test

在 Spring Boot 启动类中添加 ​@MapperScan​ 注解,扫描 Mapper 文件夹:

@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {

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

}

编码

编写实体类 ​User.java​(此处使用了Lombok简化代码)

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

编写 Mapper 包下的 ​UserMapper​接口

public interface UserMapper extends BaseMapper<User> {

}

开始使用

添加测试类,进行功能测试:

@SpringBootTest
public class SampleTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        Assert.assertEquals(5, userList.size());
        userList.forEach(System.out::println);
    }

}

提示:​UserMapper中的 ​selectList()​ 方法的参数为 ​MP ​内置的条件封装器 ​Wrapper​,所以不填写就是无任何条件

控制台输出:

User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)

小结

通过以上几个简单的步骤,我们就实现了 ​User ​表的 ​CRUD​ 功能,甚至连 ​XML ​文件都不用编写!
从以上步骤中,我们可以看到集成​MyBatis-Plus​非常的简单,只需要引入 ​starter ​工程,并配置 ​mapper ​扫描路径即可。
但​ MyBatis-Plus​ 的强大远不止这些功能,想要详细了解 ​MyBatis-Plus​ 的强大功能?那就继续往下看吧!

MyBatis-Plus 快速入门-安装

2022-03-23 16:02 更新 全新的 ​MyBatis-Plus​ 3.0 版本基于 JDK8,提供了 ​lambda ​形式的调用,所以安装集成 MP3.0 要求如下:

 

 

Release

Spring Boot

Maven:

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

Gradle:

compile group: 'com.baomidou', name: 'mybatis-plus-boot-starter', version: '3.5.1'

Spring

Maven:

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

Gradle:

compile group: 'com.baomidou', name: 'mybatis-plus', version: '3.5.1'

注意:引入 ​MyBatis-Plus​ 之后请不要再次引入 ​MyBatis ​以及 ​MyBatis-Spring​,以避免因版本差异导致的问题。

Snapshot

快照 SNAPSHOT 版本需要添加仓库,且版本号为快照版本 点击查看最新快照版本号

Maven:

<repository>
    <id>snapshots</id>
    <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</repository>

Gradle:

repositories {
    maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
}

MyBatis-Plus 快速入门-配置

2022-03-23 16:02 更新

MyBatis-Plus​ 的配置异常的简单,我们仅需要一些简单的配置即可使用 ​MyBatis-Plus​ 的强大功能!

Spring Boot 工程

 

 

@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {

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

}

Spring 工程

 

 

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="com.baomidou.mybatisplus.samples.quickstart.mapper"/>
</bean>

 

 

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
</bean>

通常来说,一般的简单工程,通过以上配置即可正常使用 ​MyBatis-Plus

MyBatis-Plus 快速入门-注解

2022-03-23 16:02 更新

本文将介绍 MybatisPlus 注解包相关类详解

@TableName

@TableName("sys_user")
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
 属性 类型  必须指定  默认值  描述 
 ​values  String  否  ""  表名
 ​schema  String  否  ""  schema
 ​keepGlobalPrefix  boolean  否  false  是否保持使用全局的 tablePrefix 的值(当全局 tablePrefix 生效时)
 ​resultMap  String  否  ""  xml 中 resultMap 的 id(用于满足特定类型的实体类对象绑定)
 ​autoResultMap  boolean  否  false  是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建与注入)
 ​excludeProperty  String[]  否  {}  需要排除的属性名

关于 ​autoResultMap​ 的说明:

MP 会自动构建一个 ​​resultMap​并注入到 ​MyBatis ​里(一般用不上),请注意以下内容:

因为 MP 底层是 MyBatis,所以 MP 只是帮您注入了常用 CRUD 到 MyBatis 里,注入之前是动态的(根据您的 Entity 字段以及注解变化而变化),但是注入之后是静态的(等于 XML 配置中的内容)。

而对于 ​typeHandler属性,MyBatis 只支持写在 2 个地方:

  1. 定义在 ​resultMap ​里,作用于查询结果的封装
  2. 定义在 ​insert ​和 ​update ​语句的 ​#{property}​ 中的 ​property ​后面(例:​#{property,typehandler=xxx.xxx.xxx}​),并且只作用于当前 设置值

除了以上两种直接指定 ​typeHandler ​的形式,MyBatis 有一个全局扫描自定义 ​typeHandler ​包的配置,原理是根据您的 ​property ​类型去找其对应的 ​typeHandler ​并使用。

@TableId

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
 属性 类型  必须指定  默认值  描述 
 value String  否  ""  主键字段名 
 type Enum  否   IdType.NONE  指定主键类型

IdType

 值 描述 
AUTO  数据库 ID 自增
NONE  无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUT  insert 前自行 set 主键值
ASSIGN_ID  分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口​IdentifierGenerator​的方法​nextId​(默认实现类为​DefaultIdentifierGenerator​雪花算法)
ASSIGN_UUID  分配 UUID,主键类型为 String(since 3.3.0),使用接口​IdentifierGenerator​的方法​nextUUID​(默认 default 方法)
ID_WORKER  分布式全局唯一 ID 长整型类型(please use ​ASSIGN_ID​)
UUID  32 位 UUID 字符串(please use ​ASSIGN_UUID​)
ID_WORKER_STR  分布式全局唯一 ID 字符串类型(please use ​ASSIGN_ID​)

@TableField

描述:字段注解(非主键)

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname")
    private String name;
    private Integer age;
    private String email;
}
 属性 类型  必须指定  默认值  描述 
value  String  否  "" 数据库字段名
exist  boolean  否  true 是否为数据库表字段
ondition  String  否  "" 字段​where​实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的​%s=#{%s}
update  String  否  "" 字段 ​update set​ 部分注入,例如:当在version字段上注解​update="%s+1"​ 表示更新时会 ​set version=version+1​ (该属性优先级高于 ​el​ 属性)
insertStrategy  Enum  否  FieldStrategy.DEFAULT 举例:NOT_NULL
insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>)
updataStrategy  Enum  否  FieldStrategy.DEFAULT 举例:IGNORED
update table_a set column=#{columnProperty}
whereStrategy  Enum  否  FieldStrategy.DEFAULT 举例:NOT_EMPTY
where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if>
fill  Enum  否  FieldFill.DEFAULT 字段自动填充策略
select  boolean  否  true 是否进行select查询
keepGlobalFormat  boolean  否  false 是否保持使用全局的format进行处理
jabcType  jabcType  否  JdbcType.UNDEFINED JDBC类型(该默认值不代表会按照该值生效)
typeHandler  Class<?extends TypeHandler>  否  UnknownTypeHandler.class 类型处理器(该默认值不代表会按照该值生效)
numericScale  String  否  "" 指定小数点后保留的位数

关于​jdbcType​和​typeHandler​以及​numericScale​的说明:
numericScale​只生效于 update 的 sql. ​jdbcType​和​typeHandler​如果不配合​@TableName#autoResultMap = true​一起使用,也只生效于 update 的 sql. 对于​typeHandler​如果你的字段类型和 set 进去的类型为​equals​关系,则只需要让你的​typeHandler​让 Mybatis 加载到即可,不需要使用注解

FieldStrategy

 值 描述 
IGNORED 忽略判断
NOT_NULL 非 NULL 判断
NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非 NULL 判断)
DEFAULT 追随全局配置

FieldFill

 值  描述
DEFAULT 默认不处理
INSERT 插入时填充字段
UPDATE 更新时填充字段
INSERT_UPDATE 插入和更新时填充字段

@Version

@EnumValue

@TableLogic

 属性 类型  必须指定  默认值  描述 
value  String  否  ""  逻辑未删除值
delval  String  否  ""  逻辑删除值

@KeySequence

 属性 类型  必须指定  默认值  描述 
value String  否  ""  序列名 
clazz Class  否  Long.class   id 的类型, 可以指定 String.class,这样返回的 Sequence 值是字符串"1"

@OrderBy

 

 

 属性 类型  必须指定  默认值  描述 
 isDesc  boolean  否  true  是否倒序查询
 sort short   否  Short.MAX_VALUE  数字越小越靠前

MyBatis-Plus 核心功能-代码生成器(新)

2022-03-23 16:06 更新

注意:适用版本:mybatis-plus-generator 3.5.1 及其以上版本,对历史版本不兼容!

快速入门

安装

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

当前包未传递依赖 MP 包,需要自己引入!

使用

快速生成

FastAutoGenerator.create("url", "username", "password")
    .globalConfig(builder -> {
        builder.author("baomidou") // 设置作者
            .enableSwagger() // 开启 swagger 模式
            .fileOverride() // 覆盖已生成文件
            .outputDir("D://"); // 指定输出目录
    })
    .packageConfig(builder -> {
        builder.parent("com.baomidou.mybatisplus.samples.generator") // 设置父包名
            .moduleName("system") // 设置父包模块名
            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, "D://")); // 设置mapperXml生成路径
    })
    .strategyConfig(builder -> {
        builder.addInclude("t_simple") // 设置需要生成的表名
            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
    })
    .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
    .execute();

交互式生成

FastAutoGenerator.create(DATA_SOURCE_CONFIG)
    // 全局配置
    .globalConfig((scanner, builder) -> builder.author(scanner.apply("请输入作者名称?")).fileOverride())
    // 包配置
    .packageConfig((scanner, builder) -> builder.parent(scanner.apply("请输入包名?")))
    // 策略配置
    .strategyConfig((scanner, builder) -> builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
                        .controllerBuilder().enableRestStyle().enableHyphenStyle()
                        .entityBuilder().enableLombok().addTableFills(
                                new Column("create_time", FieldFill.INSERT)
                        ).build())
    /*
        模板引擎配置,默认 Velocity 可选模板引擎 Beetl 或 Freemarker
       .templateEngine(new BeetlTemplateEngine())
       .templateEngine(new FreemarkerTemplateEngine())
     */
    .execute();


// 处理 all 情况
protected static List<String> getTables(String tables) {
    return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}

 

MyBatis-Plus CRUD接口-Service CRUD 接口

2022-04-02 11:57 更新

Save

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

参数说明

 参数名 类型  描述 
 ​entity  T  实体对象
 ​entityList  Collection<T>  实体对象集合
 ​batchSize  int  插入批次数量

SaveOrUpdate

// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

参数说明

 参数名  类型  描述
 ​entity  T  实体对象
 ​updateWrapper  Wrapper<T>  实体对象封装操作类 UpdateWrapper
 ​entityList  Collection<T>  实体对象集合
 ​batchSize  int  插入批次数量

Remove

// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

参数说明

 参数名  类型  描述 
 ​queryWrapper  Wrapper<T>  实体包装类 QueryWrapper
 ​id  Serializable  主键 ID
 ​columnMap  Map<String, Object>  表字段 map 对象
 ​idList  Collection<? extends Serializable>  主键 ID 列表

Update

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

参数说明

 参数名  类型   描述 
 ​updateWrapper  Wrapper<T>  实体对象封装操作类 UpdateWrapper
 ​entity  T  实体对象
 ​entityList  Collection<T>  实体对象集合
 ​batchSize  int  更新批次数量

Get

// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

参数说明

 参数名  类型  描述
 ​id  Serializable  主键 ID
 ​queryWrapper  Wrapper<T>  实体对象封装操作类 QueryWrapper
 ​throwEx  boolean  有多个 result 是否抛出异常
 ​entity  T  实体对象
 ​mapper  Function<? super Object, V>  转换函数

List

// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

参数说明

 参数名  类型  描述
 ​queryWrapper  Wrapper<T>  实体对象封装操作类 QueryWrapper
 ​idList  Collection<? extends Serializable>  主键 ID 列表
 ​columnMap  Map<String, Object>  表字段 map 对象
 ​mapper  Function<? super Object, V>  转换函数

Page

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

参数说明

 参数名  类型  描述 
 ​page  IPage<T>  翻页对象
 ​queryWrapper  Wrapper<T>  实体对象封装操作类 QueryWrapper

Count

// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);

参数说明

 参数名  类型  描述
 queryWrapper  Wrapper<T>  实体对象封装操作类 QueryWrapper

Chain

query

// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();

// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();

update

// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();

// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);
 

MyBatis-Plus CRUD接口-Mapper CRUD 接口

2022-03-23 17:08 更新

Insert

// 插入一条记录
int insert(T entity);

参数说明

 参数名  类型  描述
 entity  T  实体对象

Delete

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

参数说明

 参数名  类型  描述
 ​wrapper  Wrapper<T>  实体对象封装操作类(可以为 null)
 ​idList  Collection<? extends Serializable>  主键 ID 列表(不能为 null 以及 empty)
 ​id  Serializable  主键 ID
 ​columnMap  Map<String, Object>  表字段 map 对象

Update

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);

参数说明

 参数名  类型  描述
 ​entity  T  实体对象 (set 条件值,可为 null)
 ​updateWrapper  Wrapper<T>  实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)

Select

// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

参数说明

 参数名  类型  描述
 ​id  Serializable  主键 ID
 ​queryWrapper  Wrapper<T>  实体对象封装操作类(可以为 null)
 ​idList  Collection<? extends Serializable>  主键 ID 列表(不能为 null 以及 empty)
 ​columnMap  Map<String, Object>  表字段 map 对象
 ​page  IPage<T>  分页查询条件(可以为 RowBounds.DEFAULT)

MyBatis-Plus CRUD接口-SimpleQuery 工具类

2022-03-24 14:52 更新

keyMap

// 查询表内记录,封装返回为Map<属性,实体>
Map<A, E> keyMap(LambdaQueryWrapper<E> wrapper, SFunction<E, A> sFunction, Consumer<E>... peeks);
// 查询表内记录,封装返回为Map<属性,实体>,考虑了并行流的情况
Map<A, E> keyMap(LambdaQueryWrapper<E> wrapper, SFunction<E, A> sFunction, boolean isParallel, Consumer<E>... peeks);

参数说明

 参数名  类型  描述
 ​entity  E  实体对象
 ​attribute  A  实体属性类型,也是map中key的类型
 ​wrapper  LambdaQueryWrapper<E>  支持lambda的条件构造器
 ​sFunction  SFunction<E, A>  实体中属性的getter,用于封装后map中作为key的条件
 ​isParallel  boolean  为true时底层使用并行流执行
 ​peeks  Consumer<E>...  可叠加的后续操作

map

// 查询表内记录,封装返回为Map<属性,属性>
Map<A, P> map(LambdaQueryWrapper<E> wrapper, SFunction<E, A> keyFunc, SFunction<E, P> valueFunc, Consumer<E>... peeks);
// 查询表内记录,封装返回为Map<属性,属性>,考虑了并行流的情况
Map<A, P> map(LambdaQueryWrapper<E> wrapper, SFunction<E, A> keyFunc, SFunction<E, P> valueFunc, boolean isParallel, Consumer<E>... peeks);

参数说明

 参数名  类型  描述
 ​entity  E  实体对象
 ​attribute  A  实体属性类型,也是map中key的类型 
 ​attribute  P  实体属性类型,也是map中value的类型
 ​wrapper  LambdaQueryWrapper<E>  支持lambda的条件构造器
 ​keyFunc  SFunction<E, A>  封装后map中作为key的条件
 ​valueFunc  SFunction<E, P>  封装后map中作为value的条件
 ​isParallel  boolean  为true时底层使用并行流执行
 ​peeks  Consumer<E>...  可叠加的后续操作

group

// 查询表内记录,封装返回为Map<属性,List<实体>>
Map<K, List<T>> group(LambdaQueryWrapper<T> wrapper, SFunction<T, A> sFunction, Consumer<T>... peeks);
// 查询表内记录,封装返回为Map<属性,List<实体>>,考虑了并行流的情况
Map<K, List<T>> group(LambdaQueryWrapper<T> wrapper, SFunction<T, K> sFunction, boolean isParallel, Consumer<T>... peeks);
// 查询表内记录,封装返回为Map<属性,分组后对集合进行的下游收集器>
M group(LambdaQueryWrapper<T> wrapper, SFunction<T, K> sFunction, Collector<? super T, A, D> downstream, Consumer<T>... peeks);
// 查询表内记录,封装返回为Map<属性,分组后对集合进行的下游收集器>,考虑了并行流的情况
M group(LambdaQueryWrapper<T> wrapper, SFunction<T, K> sFunction, Collector<? super T, A, D> downstream, boolean isParallel, Consumer<T>... peeks);

参数说明

 参数名  类型  描述
 ​entity  T  实体对象
 ​attribute  K  实体属性类型,也是map中key的类型
 ​-  D  下游收集器返回类型,也是map中value的类型
 ​-  A  下游操作中间类型
 ​-  M  最终结束返回的Map<K, D>
 ​wrapper  LambdaQueryWrapper<E>  支持lambda的条件构造器
 ​sFunction  SFunction<E, A>  分组依据,封装后map中作为key的条件
 ​downstream  Collector<T, A, D>  下游收集器
 ​isParallel  boolean  为true时底层使用并行流执行
 ​peeks  Consumer<T>...  可叠加的后续操作

list

// 查询表内记录,封装返回为List<属性>
List<A> list(LambdaQueryWrapper<E> wrapper, SFunction<E, A> sFunction, Consumer<E>... peeks);
// 查询表内记录,封装返回为List<属性>,考虑了并行流的情况
List<A> list(LambdaQueryWrapper<E> wrapper, SFunction<E, A> sFunction, boolean isParallel, Consumer<E>... peeks);

参数说明

 参数名  类型  描述
 ​entity  E  实体对象
 ​attribute  A  实体属性类型,也是list中元素的类型
 ​wrapper  LambdaQueryWrapper<E>  支持lambda的条件构造器
 ​sFunction  SFunction<E, A>  封装后list中的元素
 ​isParallel  boolean  为true时底层使用并行流执行
 ​peeks  Consumer<E>...  可叠加的后续操作

MyBatis-Plus 条件构造器-AbstractWrapper

2022-03-24 16:27 更新

说明

QueryWrapper​(LambdaQueryWrapper) 和 ​UpdateWrapper​(LambdaUpdateWrapper) 的父类

用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件

注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

 allEq  eq  ne
 gt  ge  lt
 le  between  notBetween
 like  notLike  likeLeft
 likeRight  isNull  isNotNull
 in  notIn  inSql
 notInSql  groupBy  orderByAsc
 orderByDesc  orderBy  having
 func  or  and
 nested  apply  last
 exists  notExists  

MyBatis-Plus 条件构造器-QueryWrapper

2022-03-24 16:03 更新

说明:

继承自 ​AbstractWrapper ​,自身的内部属性 ​entity​也用于生成 ​where ​条件

及 ​LambdaQueryWrapper​, 可以通过 ​new QueryWrapper().lambda()​ 方法获取

select

select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)

说明:

以上方法分为两类.

第二类方法为:过滤查询字段(主键除外),入参不包含 ​class ​的调用前需要​wrapper​内的​entity​属性有值! 这两类方法重复调用以最后一次为准

MyBatis-Plus 条件构造器-UpdateWrapper

2022-05-11 17:19 更新

说明:

继承自 ​AbstractWrapper,自身的内部属性 ​entity也用于生成 ​where条件

及 ​LambdaUpdateWrapper​, 可以通过 ​new UpdateWrapper().lambda()​ 方法获取!

set

set(String column, Object val)
set(boolean condition, String column, Object val)

setSql

setSql(String sql) 

lambda 

MyBatis-Plus 条件构造器-使用 Wrapper 自定义SQL

2022-03-24 16:27 更新

注意事项

需要​mybatis-plus​版本 >= ​3.0.7

param ​参数名要么叫​ew​,要么加上注解​@Param(Constants.WRAPPER)​ 

使用​${ew.customSqlSegment}​ 不支持 ​Wrapper内的entity生成where语句

kotlin持久化对象定义最佳实践

由于​kotlin​相比于​java​多了数据对象(​data class​),在未说明情况下可能会混用。建议按照以下形式定义持久化对象

@TableName("sys_user")
class User {
		@TableId(type = IdType.AUTO)
    var id: Int? = null

    @TableField("username")
    var name: String? = null

    var roleId: Int? = null
}

注意:这里的​TableId​及​TableField​并非必要,只是为了展示​Mybatis-Plus​中的​annotation​使用

这里所有成员都需要定义为可空类型(​?​),并赋予​null​的初始值,方便我们在以下场景中使用(类似java中的​updateSelective​)

val wrapper = KtUpdateWrapper(User::class.java).eq(User::id, 2)
val newRecord = User()
newRecord.name = "newName"
userMapper!!.update(newRecord, wrapper)

不建议使用​data class​及全参数构造方法,这样我们会写很多不必要的​null​来构造一个空对象

用注解

@Select("select * from mysql_data ${ew.customSqlSegment}")
List<MysqlData> getAll(@Param(Constants.WRAPPER) Wrapper wrapper);

用XML

List<MysqlData> getAll(Wrapper ew);
<select id="getAll" resultType="MysqlData">
	SELECT * FROM mysql_data ${ew.customSqlSegment}
</select>

kotlin使用wrapper

kotlin 可以使用 ​QueryWrapper和 ​UpdateWrapper但无法使用 ​LambdaQueryWrapper和 ​LambdaUpdateWrapper

如果想使用 lambda 方式的 wrapper 请使用 ​KtQueryWrapper和 ​KtUpdateWrapper

val queryWrapper = KtQueryWrapper(User()).eq(User::name, "sss").eq(User::roleId, "sss2")
userMapper!!.selectList(queryWrapper)

val updateConditionWrapper = KtUpdateWrapper(User()).eq(User::name, "sss").eq(User::roleId, "sss2")
val updateRecord = User()
updateRecord.name = "newName"
userMapper!!.update(updateRecord, updateConditionWrapper)

val updateRecord = User()
updateRecord.id = 2
updateRecord.name = "haha"
userMapper.updateById(updateRecord)

链式调用 lambda 式

// 区分:
// 链式调用 普通
UpdateChainWrapper<T> update();
// 链式调用 lambda 式。注意:不支持 Kotlin 
LambdaUpdateChainWrapper<T> lambdaUpdate();

// 等价示例:
query().eq("id", value).one();
lambdaQuery().eq(Entity::getId, value).one();

// 等价示例:
update().eq("id", value).remove();
lambdaUpdate().eq(Entity::getId, value).remove();

MyBatis-Plus 核心功能-主键策略

2022-03-24 16:31 更新

提示

主键生成策略必须使用 ​INPUT

支持父类定义 ​@KeySequence​ 子类继承使用

支持主键类型指定(3.3.0 开始自动识别主键类型)

内置支持:

 

 

如果内置支持不满足你的需求,可实现 ​IKeyGenerator​接口来进行扩展.

举个例子:

@KeySequence(value = "SEQ_ORACLE_STRING_KEY", clazz = String.class)
public class YourEntity {

    @TableId(value = "ID_STR", type = IdType.INPUT)
    private String idStr;

}

Spring-Boot

方式一:使用配置类

@Bean
public IKeyGenerator keyGenerator() {
    return new H2KeyGenerator();
}

方式二:通过 MybatisPlusPropertiesCustomizer 自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().getDbConfig().setKeyGenerator(new H2KeyGenerator());
}

Spring

方式一: XML 配置

<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
   <property name="dbConfig" ref="dbConfig"/>
</bean>

<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig">
   <property name="keyGenerator" ref="keyGenerator"/>
</bean>

<bean id="keyGenerator" class="com.baomidou.mybatisplus.extension.incrementer.H2KeyGenerator"/>

方式二:注解配置

@Bean
public GlobalConfig globalConfig() {
	GlobalConfig conf = new GlobalConfig();
	conf.setDbConfig(new GlobalConfig.DbConfig().setKeyGenerator(new H2KeyGenerator()));
	return conf;
}

MyBatis-Plus 核心功能-自定义ID生成器

2022-03-24 17:15 更新

提示

自 3.3.0 开始,默认使用雪花算法+​UUID​(不含中划线)

自定义示例工程:

 方法  主键生成策略  主键类型  说明
nextId ASSIGN_ID,
ID_WORKER,
ID_WORKER_STR
Long,
Integer,
String
支持自动转换为 String 类型,但数值类型不支持自动转换,需精准匹配,例如返回 Long,实体主键就不支持定义为 Integer
nextUUID ASSIGN_UUID,UUID String 默认不含中划线的 UUID 生成

Spring-Boot

方式一:声明为 Bean 供 Spring 扫描注入

@Component
public class CustomIdGenerator implements IdentifierGenerator {
    @Override
    public Long nextId(Object entity) {
      	//可以将当前传入的class全类名来作为bizKey,或者提取参数来生成bizKey进行分布式Id调用生成.
      	String bizKey = entity.getClass().getName();
        //根据bizKey调用分布式ID生成
        long id = ....;
      	//返回生成的id值即可.
        return id;
    }
}

方式二:使用配置类

@Bean
public IdentifierGenerator idGenerator() {
    return new CustomIdGenerator();
}

方式三:通过 MybatisPlusPropertiesCustomizer 自定义

@Bean
public MybatisPlusPropertiesCustomizer plusPropertiesCustomizer() {
    return plusProperties -> plusProperties.getGlobalConfig().setIdentifierGenerator(new CustomIdGenerator());
}

Spring

方式一: XML 配置

<bean name="customIdGenerator" class="com.baomidou.samples.incrementer.CustomIdGenerator"/>

<bean id="globalConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
		<property name="identifierGenerator" ref="customIdGenerator"/>
</bean>

方式二:注解配置

@Bean
public GlobalConfig globalConfig() {
	GlobalConfig conf = new GlobalConfig();
	conf.setIdentifierGenerator(new CustomIdGenerator());
	return conf;
}

MyBatis-Plus 扩展-逻辑删除

2022-03-25 13:48 更新

说明:

只对自动注入的 sql 起效:

例如:

字段类型支持说明:

附录:

使用方法

步骤 1

例如: ​application.yml

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: flag # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

步骤 2

@TableLogic
private Integer deleted;

常见问题

1. 如何 insert ?

2. 删除接口自动填充功能失效

MyBatis-Plus 扩展-通用枚举

2022-03-25 13:48 更新

解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!

自3.1.0开始,如果你无需使用原生枚举,可配置默认枚举来省略扫描通用枚举配置

 

 

3.1.0 以下版本改变了原生默认行为,升级时请将默认枚举设置为​EnumOrdinalTypeHandler

 

 

实体中使用原生枚举

 

 

配置枚举包扫描的时候能提前注册使用注解枚举的缓存

1、声明通用枚举属性

 

 

public enum GradeEnum {

    PRIMARY(1, "小学"),  SECONDORY(2, "中学"),  HIGH(3, "高中");

    GradeEnum(int code, String descp) {
        this.code = code;
        this.descp = descp;
    }

    @EnumValue//标记数据库存的值是code
    private final int code;
    //。。。
}

 

 

public enum AgeEnum implements IEnum<Integer> {
    ONE(1, "一岁"),
    TWO(2, "二岁"),
    THREE(3, "三岁");

    private int value;
    private String desc;

    @Override
    public Integer getValue() {
        return this.value;
    }
}

 

 

public class User {
    /**
     * 名字
     * 数据库字段: name varchar(20)
     */
    private String name;

    /**
     * 年龄,IEnum接口的枚举处理
     * 数据库字段:age INT(3)
     */
    private AgeEnum age;


    /**
     * 年级,原生枚举(带{@link com.baomidou.mybatisplus.annotation.EnumValue}):
     * 数据库字段:grade INT(2)
     */
    private GradeEnum grade;
}

2、配置扫描通用枚举

mybatis-plus:
    # 支持统配符 * 或者 ; 分割
    typeEnumsPackage: com.baomidou.springboot.entity.enums
  ....
@Configuration
public class MybatisPlusAutoConfiguration {

    @Bean
    public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {
        return properties -> {
            GlobalConfig globalConfig = properties.getGlobalConfig();
            globalConfig.setBanner(false);
            MybatisConfiguration configuration = new MybatisConfiguration();
            configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);
            properties.setConfiguration(configuration);
        };
    }
}

如何序列化枚举值为数据库存储值?

Jackson

springboot:

    @Bean
    public Jackson2ObjectMapperBuilderCustomizer customizer(){
        return builder -> builder.featuresToEnable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
    }

jackson:

    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);

以上两种方式任选其一,然后在枚举中复写 ​toString方法即可。

public enum GradeEnum {

    PRIMARY(1, "小学"),  SECONDORY(2, "中学"),  HIGH(3, "高中");

    GradeEnum(int code, String descp) {
        this.code = code;
        this.descp = descp;
    }

    @EnumValue
  	@JsonValue	//标记响应json值
    private final int code;
}

Fastjson 

全局处理方式

    FastJsonConfig config = new FastJsonConfig();
    config.setSerializerFeatures(SerializerFeature.WriteEnumUsingToString);

局部处理方式

    @JSONField(serialzeFeatures= SerializerFeature.WriteEnumUsingToString)
    private UserStatus status;

以上两种方式任选其一,然后在枚举中复写 ​toString方法即可。

 

MyBatis-Plus 扩展-字段类型处理器

2022-03-25 13:48 更新

类型处理器,用于 JavaType 与 JdbcType 之间的转换,用于 ​PreparedStatement设置参数值和从 ​ResultSet或 ​CallableStatement中取出一个值,本文讲解 mybaits-plus 内置常用类型处理器如何通过TableField注解快速注入到 mybatis 容器中。

 

 

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {
    private Long id;

    ...


    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     *
     * 以下两种类型处理器,二选一 也可以同时存在
     *
     * 注意!!选择对应的 JSON 处理器也必须存在对应 JSON 解析依赖包
     */
    @TableField(typeHandler = JacksonTypeHandler.class)
    // @TableField(typeHandler = FastjsonTypeHandler.class)
    private OtherInfo otherInfo;

}

该注解对应了 XML 中写法为

<result column="other_info" jdbcType="VARCHAR" property="otherInfo" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />

MyBatis-Plus 扩展-自动填充功能

2022-03-25 13:47 更新

原理: 

public class User {

    // 注意!这里需要标记为填充字段
    @TableField(.. fill = FieldFill.INSERT)
    private String fillField;

    ....
}
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        log.info("start insert fill ....");
        this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐使用)
        // 或者
        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) {
        log.info("start update fill ....");
        this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 起始版本 3.3.0(推荐)
        // 或者
        this.strictUpdateFill(metaObject, "updateTime", () -> LocalDateTime.now(), LocalDateTime.class); // 起始版本 3.3.3(推荐)
        // 或者
        this.fillStrategy(metaObject, "updateTime", LocalDateTime.now()); // 也可以使用(3.3.0 该方法有bug)
    }
}

注意事项:

public enum FieldFill {
    /**
     * 默认不处理
     */
    DEFAULT,
    /**
     * 插入填充字段
     */
    INSERT,
    /**
     * 更新填充字段
     */
    UPDATE,
    /**
     * 插入和更新填充字段
     */
    INSERT_UPDATE
}

MyBatis-Plus 扩展-SQL注入器

2022-03-25 13:47 更新

注入器配置

全局配置 ​sqlInjector用于注入 ​ISqlInjector​接口的子类,实现自定义方法注入。

参考默认注入器 DefaultSqlInjector

public interface ISqlInjector {

    /**
     * <p>
     * 检查SQL是否注入(已经注入过不再注入)
     * </p>
     *
     * @param builderAssistant mapper 信息
     * @param mapperClass      mapper 接口的 class 对象
     */
    void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass);
}

自定义自己的通用方法可以实现接口 ​ISqlInjector也可以继承抽象类 ​AbstractSqlInjector注入通用方法 SQL 语句 然后继承 ​BaseMapper添加自定义方法,全局配置 ​sqlInjector注入 ​MP​ 会自动将类所有方法注入到 ​mybatis容器中。

 

MyBatis-Plus 扩展-执行SQL分析打印

2022-03-25 13:47 更新

该功能依赖 ​p6spy组件,完美的输出打印 SQL 及执行时长 3.1.0 以上版本

示例工程:

mybatis-plus-sample-crud

Maven:

<dependency>
  <groupId>p6spy</groupId>
  <artifactId>p6spy</artifactId>
  <version>最新版本</version>
</dependency>

Gradle:

compile group: 'p6spy', name: 'p6spy', version: '最新版本'
spring:
  datasource:
    driver-class-name: com.p6spy.engine.spy.P6SpyDriver
    url: jdbc:p6spy:h2:mem:test
    ...
#3.2.1以上使用
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2

注意!

MyBatis-Plus 扩展-数据安全保护

2022-03-25 13:47 更新

该功能为了保护数据库配置及数据安全,在一定的程度上控制开发人员流动导致敏感信息泄露。

YML 配置:

// 加密配置 mpw: 开头紧接加密内容( 非数据库配置专用 YML 中其它配置也是可以使用的 )
spring:
  datasource:
    url: mpw:qRhvCwF4GOqjessEB3G+a5okP+uXXr96wcucn2Pev6Bf1oEMZ1gVpPPhdDmjQqoM
    password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
    username: mpw:Xb+EgsyuYRXw7U7sBJjBpA==

密钥加密:

// 生成 16 位随机 AES 密钥
String randomKey = AES.generateRandomKey();

// 随机密钥加密
String result = AES.encrypt(data, randomKey);

如何使用:

// Jar 启动参数( idea 设置 Program arguments , 服务器可以设置为启动环境变量 )
--mpw.key=d1104d7c3b616f0b

注意!

MyBatis-Plus 扩展-多数据源

2022-03-25 13:47 更新

简介

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

其支持 ​Jdk 1.7+​, ​SpringBoot 1.4.x 1.5.x 2.x.x

文档

详细文档

特性

 

 

约定

 

 

使用方法

 

 

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
  <version>${version}</version>
</dependency>

 

 

spring:
  datasource:
    dynamic:
      primary: master #设置默认的数据源或者数据源组,默认值即为master
      strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      datasource:
        master:
          url: jdbc:mysql://xx.xx.xx.xx:3306/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver # 3.2.0开始支持SPI可省略此配置
        slave_1:
          url: jdbc:mysql://xx.xx.xx.xx:3307/dynamic
          username: root
          password: 123456
          driver-class-name: com.mysql.jdbc.Driver
        slave_2:
          url: ENC(xxxxx) # 内置加密,使用请查看详细文档
          username: ENC(xxxxx)
          password: ENC(xxxxx)
          driver-class-name: com.mysql.jdbc.Driver
       #......省略
       #以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2
# 多主多从                      纯粹多库(记得设置primary)                   混合配置
spring:                               spring:                               spring:
  datasource:                           datasource:                           datasource:
    dynamic:                              dynamic:                              dynamic:
      datasource:                           datasource:                           datasource:
        master_1:                             mysql:                                master:
        master_2:                             oracle:                               slave_1:
        slave_1:                              sqlserver:                            slave_2:
        slave_2:                              postgresql:                           oracle_1:
        slave_3:                              h2:                                   oracle_2:

 

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

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

 

@Service
@DS("slave")
public class UserServiceImpl implements UserService {

  @Autowired
  private JdbcTemplate jdbcTemplate;

  public List selectAll() {
    return  jdbcTemplate.queryForList("select * from user");
  }
  
  @Override
  @DS("slave_1")
  public List selectByCondition() {
    return  jdbcTemplate.queryForList("select * from user where age >10");
  }
}

MyBatis-Plus 插件-插件主体

2022-03-25 14:24 更新

注意

MybatisPlusInterceptor

该插件是核心插件,目前代理了 ​Executor#query​ 和 ​Executor#update​ 和 ​StatementHandler#prepare​ 方法

属性

InnerInterceptor

我们提供的插件都将基于此接口来实现功能

目前已有的功能:

注意:

使用多个功能需要注意顺序关系,建议使用如下顺序

总结: 对 sql 进行单次改造的优先放入,不对 sql 进行改造的最后放入

使用方式(以分页插件举例)

spring

<bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
    <!-- 其他属性 略 -->
    <property name="configuration" ref="configuration"/>
    <property name="plugins">
        <array>
            <ref bean="mybatisPlusInterceptor"/>
        </array>
    </property>
</bean>

<bean id="configuration" class="com.baomidou.mybatisplus.core.MybatisConfiguration">
    <!-- 需配置该值为false,避免1或2级缓存可能出现问题,该属性会在旧插件移除后一同移除 -->
    <property name="useDeprecatedExecutor" value="false"/>
</bean>

<bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
    <property name="interceptors">
        <list>
            <ref bean="paginationInnerInterceptor"/>
        </list>
    </property>
</bean>

<bean id="paginationInnerInterceptor" class="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor">
    <!-- 对于单一数据库类型来说,都建议配置该值,避免每次分页都去抓取数据库类型 -->
    <constructor-arg name="dbType" value="H2"/>
</bean>

spring-boot

@Configuration
@MapperScan("scan.your.mapper.package")
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
        return interceptor;
    }

    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
}

mybatis-config.xml

<plugins>
  <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
    <property name="@page" value="com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor"/>
    <property name="page:dbType" value="h2"/>
  </plugin>
</plugins>

property的配置说明详见 ​MybatisPlusInterceptor#setProperties​ 的源码方法注释

拦截忽略注解 @InterceptorIgnore

 属性名  类型  默认值  描述
 tenantLine  String  ""  行级租户
 dynamicTableName  String  ""  动态表名
 blockAttack  String  ""  攻击 SQL 阻断解析器,防止全表更新与删除
 illegalSql  String  ""  垃圾 SQL 拦截

该注解作用于 ​xxMapper.java​ 方法之上 各属性代表对应的插件 各属性不给值则默认为 ​false设置为 ​true忽略拦截 更多说明详见源码注释

MyBatis-Plus 插件-分页插件

2022-03-25 14:30 更新

PaginationInnerInterceptor

支持的数据库

属性介绍

 属性名  类型  默认值  描述
 overflow  boolean  false  溢出总页数后是否进行处理,默认不处理
 maxLimit  Long    单页分页条数限制,默认无限制
 dbType  DbType    数据库类型,根据类型获取应使用的分页方言
 dialect  IDialect    方言实现类

建议单一数据库类型的均设置 ​dbType

自定义的 mapper#method 使用分页

IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
// or (class MyPage extends Ipage<UserVo>{ private Integer state; })
MyPage selectPageVo(MyPage page);
// or
List<UserVo> selectPageVo(IPage<UserVo> page, Integer state);
<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo">
    SELECT id,name FROM user WHERE state=#{state}
</select>

 

其他:

MyBatis-Plus 插件-乐观锁插件

2022-03-25 14:35 更新

OptimisticLockerInnerInterceptor

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

乐观锁实现方式:

乐观锁配置需要两步

1、配置插件

<bean class="com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor" id="optimisticLockerInnerInterceptor"/>

<bean id="mybatisPlusInterceptor" class="com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor">
    <property name="interceptors">
        <list>
            <ref bean="optimisticLockerInnerInterceptor"/>
        </list>
    </property>
</bean>

 

 

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
    return interceptor;
}

2、在实体类的字段上加上@Version注解

@Version
private Integer version;

说明:

 

 

示例:

// Spring Boot 方式
@Configuration
@MapperScan("按需修改")
public class MybatisPlusConfig {
    /**
     * 旧版
     */
    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }

    /**
     * 新版
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mybatisPlusInterceptor;
    }
}

MyBatis-Plus 插件-多租户插件

2022-03-25 14:38 更新

TenantLineInnerInterceptor

示例工程:mybatis-plus-sample-tenant

属性介绍

 属性名  类型  默认值  描述
 ​tenantLineHandler  TenantLineHandler    租户处理器( TenantId 行级 )
public interface TenantLineHandler {

    /**
     * 获取租户 ID 值表达式,只支持单个 ID 值
     * <p>
     *
     * @return 租户 ID 值表达式
     */
    Expression getTenantId();

    /**
     * 获取租户字段名
     * <p>
     * 默认字段名叫: tenant_id
     *
     * @return 租户字段名
     */
    default String getTenantIdColumn() {
        return "tenant_id";
    }

    /**
     * 根据表名判断是否忽略拼接多租户条件
     * <p>
     * 默认都要进行解析并拼接多租户条件
     *
     * @param tableName 表名
     * @return 是否忽略, true:表示忽略,false:需要解析并拼接多租户条件
     */
    default boolean ignoreTable(String tableName) {
        return false;
    }
}

说明:

MyBatis-Plus 插件-防全表更新与删除插件

2022-03-25 14:40 更新

BlockAttackInnerInterceptor

针对 ​update和 ​delete语句,作用: 阻止恶意的全表更新删除

注入​MybatisPlusInterceptor​类,并配置​BlockAttackInnerInterceptor​拦截器

@Configuration
public class MybatisPlusConfig {
  @Bean
  public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor());
    return interceptor;
  }
}

测试示例(全表更新)

@SpringBootTest
public class QueryWrapperTest {

  @Autowired
  private UserService userService;

  /**
  + SQL:UPDATE user  SET name=?,email=?;
  */
  @Test
  public void test() {
    User user = new User();
    user.setId(999L);
    user.setName("custom_name");
    user.setEmail("xxx@mail.com");
    // com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation
    userService.saveOrUpdate(user, null);
  }
}

测试示例(部分更新)

@SpringBootTest
public class QueryWrapperTest {

  @Autowired
  private UserService userService;

  /**
  + SQL:UPDATE user  SET name=?, email=? WHERE id = ?;
  */
  @Test
  public void test() {
    LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
    wrapper.eq(User::getId, 1);
    User user = new User();
    user.setId(10L);
    user.setName("custom_name");
    user.setEmail("xxx@mail.com");
    userService.saveOrUpdate(user, wrapper);
  }}

MyBatis-Plus 插件-动态表名插件

2022-03-25 14:43 更新

DynamicTableNameInnerInterceptor

简单示例:mybatis-plus-sample-dynamic-tablename

注意事项:

 

标签:插件,String,Wrapper,class,Plus,MyBatis,public
来源: https://www.cnblogs.com/hanease/p/16392954.html