zoukankan      html  css  js  c++  java
  • MyBatisPlus使用

    简介

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

    特性

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

    准备工作

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

    • 拥有 Java 开发环境以及相应 IDE
    • 熟悉 Spring Boot
    • 熟悉 Maven

    现有一张 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)
    );
    
    
    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');
    

    使用MyBatis-Plus

    官网:简介 | MyBatis-Plus (baomidou.com)

    引入

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.3.4</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.27</version>
    </dependency>
    

    配置

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

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&useSSL=false
        username: root
        password: 123456
        driver-class-name: "com.mysql.cj.jdbc.Driver"
    

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

    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import springfox.documentation.oas.annotations.EnableOpenApi;
    
    @SpringBootApplication
    @EnableOpenApi
    @MapperScan("com.example.demo.mapper")
    public class DemoApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(DemoApplication.class, args);
    	}
    
    }
    
    

    编码

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

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

    编写 Mapper 类 UserMapper.java并继承自BaseMapper<T>

    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.example.demo.entity.User;
    
    public interface UserMapper extends BaseMapper<User> {
    }
    

    开始使用

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

    import com.example.demo.entity.User;
    import com.example.demo.mapper.UserMapper;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.Test;
    import org.springframework.boot.test.context.SpringBootTest;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    @SpringBootTest
    public class SampleTest {
        @Resource
        private UserMapper userMapper;
    
        @Test
        public void testSelect() {
            System.out.println(("----- selectAll method test ------"));
            List<User> userList = userMapper.selectList(null);
            Assertions.assertEquals(5, userList.size());
            userList.forEach(System.out::println);
        }
    
    }
    

    输出如下

    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 文件都不用编写!

    注解

    @TableName

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

    关于 autoResultMap 的说明:

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

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

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

    1. 定义在 resultMap 里,作用于查询结果的封装
    2. 定义在 insertupdate 语句的 #{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

    • 描述:字段注解(非主键)
    属性 类型 必须指定 默认值 描述
    value String "" 数据库字段名
    exist boolean true 是否为数据库表字段
    condition String "" 字段 where 实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的 %s=#{%s}参考(opens new window)
    update String "" 字段 update set 部分注入,例如: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>)
    updateStrategy 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 进行处理
    jdbcType JdbcType JdbcType.UNDEFINED JDBC 类型 (该默认值不代表会按照该值生效)
    typeHandler Class<? extends TypeHandler> UnknownTypeHandler.class 类型处理器 (该默认值不代表会按照该值生效)
    numericScale String "" 指定小数点后保留的位数

    关于jdbcTypetypeHandler以及numericScale的说明:

    numericScale只生效于 update 的 sql. jdbcTypetypeHandler如果不配合@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

    • 描述:乐观锁注解、标记 @Verison 在字段上

    @EnumValue

    • 描述:通枚举类注解(注解在枚举字段上)

    @TableLogic

    • 描述:表字段逻辑处理注解(逻辑删除)
    属性 类型 必须指定 默认值 描述
    value String "" 逻辑未删除值
    delval String "" 逻辑删除值

    @SqlParser

    see @InterceptorIgnore

    @KeySequence

    • 描述:序列主键策略 oracle
    • 属性:value、resultMap
    属性 类型 必须指定 默认值 描述
    value String "" 序列名
    clazz Class Long.class id 的类型, 可以指定 String.class,这样返回的 Sequence 值是字符串"1"

    @InterceptorIgnore

    see 插件主体

    @OrderBy

    • 描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
    属性 类型 必须指定 默认值 描述
    isDesc boolean true 是否倒序查询
    sort short Short.MAX_VALUE 数字越小越靠前

    Mapper CRUD 接口

    说明:

    • 通用 CRUD 封装BaseMapper接口,为 Mybatis-Plus 启动时自动解析实体表关系映射转换为 Mybatis 内部对象注入容器
    • 泛型 T 为任意实体对象
    • 参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键
    • 对象 Wrapper条件构造器

    Insert

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

    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 实体对象封装操作类(可以为 null)
    Collection<? extends Serializable> idList 主键 ID 列表(不能为 null 以及 empty)
    Serializable id 主键 ID
    Map<String, Object> columnMap 表字段 map 对象

    Update

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

    参数说明

    类型 参数名 描述
    T entity 实体对象 (set 条件值,可为 null)
    Wrapper updateWrapper 实体对象封装操作类(可以为 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);
    
    

    参数说明

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

    Service CRUD 接口

    说明:

    • 通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆,
    • 泛型 T 为任意实体对象
    • 建议如果存在自定义通用 Service 方法的可能,请创建自己的 IBaseService 继承 Mybatis-Plus 提供的基类
    • 对象 Wrapper条件构造器

    Save

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

    参数说明

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

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

    参数说明

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

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

    参数说明

    类型 参数名 描述
    Wrapper queryWrapper 实体包装类 QueryWrapper
    Serializable id 主键 ID
    Map<String, Object> columnMap 表字段 map 对象
    Collection<? extends Serializable> idList 主键 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);
    

    参数说明

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

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

    参数说明

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

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

    参数说明

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

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

    参数说明

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

    Count

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

    参数说明

    类型 参数名 描述
    Wrapper queryWrapper 实体对象封装操作类 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);
    

    使用方式

    Mapper

    import com.baomidou.mybatisplus.core.mapper.BaseMapper;
    import com.qingshan.brioso.entity.User;
    
    public interface UserMapper extends BaseMapper<User> {
    }
    

    ServiceImpl

    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.qingshan.brioso.entity.User;
    import com.qingshan.brioso.mapper.UserMapper;
    import com.qingshan.brioso.service.IUserService;
    public class UserService extends ServiceImpl<UserMapper,User> implements IUserService{
    
    }
    

    IUserService

    import com.baomidou.mybatisplus.extension.service.IService;
    import com.qingshan.brioso.entity.User;
    
    public interface IUserService extends IService<User> {
    }
    
    

    条件构造器

    说明:

    • 以下出现的第一个入参boolean condition表示该条件是否加入最后生成的sql中,例如:query.like(StringUtils.isNotBlank(name), Entity::getName, name) .eq(age!=null && age >= 0, Entity::getAge, age)
    • 以下代码块内的多个方法均为从上往下补全个别boolean类型的入参,默认为true
    • 以下出现的泛型Param均为Wrapper的子类实例(均具有AbstractWrapper的所有方法)
    • 以下方法在入参中出现的R为泛型,在普通wrapper中是String,在LambdaWrapper中是函数(例:Entity::getId,Entity为实体类,getId为字段idgetMethod)
    • 以下方法入参中的R column均表示数据库字段,当R具体类型为String时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)!而不是实体类数据字段名!!!,另当R具体类型为SFunction时项目runtime不支持eclipse自家的编译器!!!
    • 以下举例均为使用普通wrapper,入参为MapList的均以json形式表现!
    • 使用中如果入参的Map或者List,则不会加入最后生成的sql中!!!
    • 有任何疑问就点开源码看,看不懂函数点击我学习新知识

    AbstractWrapper

    说明:

    QueryWrapper(LambdaQueryWrapper) 和 UpdateWrapper(LambdaUpdateWrapper) 的父类
    用于生成 sql 的 where 条件, entity 属性也用于生成 sql 的 where 条件
    注意: entity 生成的 where 条件与 使用各个 api 生成的 where 条件没有任何关联行为

    allEq -------- (全部等于)

    allEq(Map<R, V> params)
    allEq(Map<R, V> params, boolean null2IsNull)
    allEq(boolean condition, Map<R, V> params, boolean null2IsNull)
    

    个别参数说明:

    params : key为数据库字段名,value为字段值
    null2IsNull : 为true则在mapvaluenull时调用 isNull 方法,为false时则忽略valuenull

    • 例1: allEq({id:1,name:"老王",age:null})--->id = 1 and name = '老王' and age is null
    • 例2: allEq({id:1,name:"老王",age:null}, false)--->id = 1 and name = '老王'
    allEq(BiPredicate<R, V> filter, Map<R, V> params)
    allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull)
    allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) 
    

    个别参数说明:

    filter : 过滤函数,是否允许字段传入比对条件中
    paramsnull2IsNull : 同上

    • 例1: allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null})--->name = '老王' and age is null
    • 例2: allEq((k,v) -> k.indexOf("a") >= 0, {id:1,name:"老王",age:null}, false)--->name = '老王'

    eq (等于 = )

    eq(R column, Object val)
    eq(boolean condition, R column, Object val)
    
    • 等于 =
    • 例: eq("name", "老王")--->name = '老王'

    ne(不等于<>)

    ne(R column, Object val)
    ne(boolean condition, R column, Object val)
    
    • 不等于 <>
    • 例: ne("name", "老王")--->name <> '老王'

    gt (大于 > )

    gt(R column, Object val)
    gt(boolean condition, R column, Object val)
    
    • 大于 >
    • 例: gt("age", 18)--->age > 18

    ge (大于等于 >=)

    ge(R column, Object val)
    ge(boolean condition, R column, Object val)
    
    • 大于等于 >=
    • 例: ge("age", 18)--->age >= 18

    lt (小于<)

    lt(R column, Object val)
    lt(boolean condition, R column, Object val)
    
    • 小于 <
    • 例: lt("age", 18)--->age < 18

    le (小于等于<=)

    le(R column, Object val)
    le(boolean condition, R column, Object val)
    
    • 小于等于 <=
    • 例: le("age", 18)--->age <= 18

    between (BETWEEN 值1 AND 值2)

    between(R column, Object val1, Object val2)
    between(boolean condition, R column, Object val1, Object val2)
    
    • BETWEEN 值1 AND 值2
    • 例: between("age", 18, 30)--->age between 18 and 30

    notBetween (NOT BETWEEN 值1 AND 值2)

    notBetween(R column, Object val1, Object val2)
    notBetween(boolean condition, R column, Object val1, Object val2)
    
    • NOT BETWEEN 值1 AND 值2

    • 例: notBetween("age", 18, 30)--->age not between 18 and 30

    like (LIKE '%值%')

    like(R column, Object val)
    like(boolean condition, R column, Object val)
    
    • LIKE '%值%'
    • 例: like("name", "王")--->name like '%王%'

    notLike (NOT LIKE '%值%')

    notLike(R column, Object val)
    notLike(boolean condition, R column, Object val)
    
    • NOT LIKE '%值%'
    • 例: notLike("name", "王")--->name not like '%王%'

    likeLeft (LIKE '%值')

    likeLeft(R column, Object val)
    likeLeft(boolean condition, R column, Object val)
    
    • LIKE '%值'
    • 例: likeLeft("name", "王")--->name like '%王'

    likeRight (LIKE '值%')

    likeRight(R column, Object val)
    likeRight(boolean condition, R column, Object val)
    
    • LIKE '值%'
    • 例: likeRight("name", "王")--->name like '王%'

    isNull (字段 IS NULL)

    isNull(R column)
    isNull(boolean condition, R column)
    
    • 字段 IS NULL
    • 例: isNull("name")--->name is null

    isNotNull (字段 IS NOT NULL)

    isNotNull(R column)
    isNotNull(boolean condition, R column)
    
    • 字段 IS NOT NULL
    • 例: isNotNull("name")--->`name is not null

    in (字段 in (value.get(0), value.get(1), ...))

    in(R column, Collection<?> value)
    in(boolean condition, R column, Collection<?> value)
    
    • 字段 IN (value.get(0), value.get(1), ...)
    • 例: in("age",{1,2,3})--->age in (1,2,3)
    in(R column, Object... values)
    in(boolean condition, R column, Object... values)
    
    • 字段 IN (v0, v1, ...)
    • 例: in("age", 1, 2, 3)--->age in (1,2,3)

    notIn (字段 NOT IN (value.get(0), value.get(1), ...))

    notIn(R column, Collection<?> value)
    notIn(boolean condition, R column, Collection<?> value)
    
    • 字段 NOT IN (value.get(0), value.get(1), ...)
    • 例: notIn("age",{1,2,3})--->age not in (1,2,3)
    notIn(R column, Object... values)
    notIn(boolean condition, R column, Object... values)
    
    • 字段 NOT IN (v0, v1, ...)
    • 例: notIn("age", 1, 2, 3)--->age not in (1,2,3)

    inSql

    inSql(R column, String inValue)
    inSql(boolean condition, R column, String inValue)
    
    • 字段 IN ( sql语句 )
    • 例: inSql("age", "1,2,3,4,5,6")--->age in (1,2,3,4,5,6)
    • 例: inSql("id", "select id from table where id < 3")--->id in (select id from table where id < 3)

    notInSql

    notInSql(R column, String inValue)
    notInSql(boolean condition, R column, String inValue)
    
    • 字段 NOT IN ( sql语句 )
    • 例: notInSql("age", "1,2,3,4,5,6")--->age not in (1,2,3,4,5,6)
    • 例: notInSql("id", "select id from table where id < 3")--->id not in (select id from table where id < 3)

    groupBy

    groupBy(R... columns)
    groupBy(boolean condition, R... columns)
    
    • 分组:GROUP BY 字段, ...
    • 例: groupBy("id", "name")--->group by id,name

    orderByAsc

    orderByAsc(R... columns)
    orderByAsc(boolean condition, R... columns)
    
    • 排序:ORDER BY 字段, ... ASC
    • 例: orderByAsc("id", "name")--->order by id ASC,name ASC

    orderByDesc

    orderByDesc(R... columns)
    orderByDesc(boolean condition, R... columns)
    
    • 排序:ORDER BY 字段, ... DESC
    • 例: orderByDesc("id", "name")--->order by id DESC,name DESC

    orderBy

    orderBy(boolean condition, boolean isAsc, R... columns)
    
    • 排序:ORDER BY 字段, ...
    • 例: orderBy(true, true, "id", "name")--->order by id ASC,name ASC

    having

    having(String sqlHaving, Object... params)
    having(boolean condition, String sqlHaving, Object... params)
    
    • HAVING ( sql语句 )
    • 例: having("sum(age) > 10")--->having sum(age) > 10
    • 例: having("sum(age) > {0}", 11)--->having sum(age) > 11

    func

    func(Consumer<Children> consumer)
    func(boolean condition, Consumer<Children> consumer)
    
    • func 方法(主要方便在出现if...else下调用不同方法能不断链)
    • 例: func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})

    or

    or()
    or(boolean condition)
    
    • 拼接 OR ::: tip 注意事项: 主动调用or表示紧接着下一个方法不是用and连接!(不调用or则默认为使用and连接) :::
    • 例: eq("id",1).or().eq("name","老王")--->id = 1 or name = '老王'
    or(Consumer<Param> consumer)
    or(boolean condition, Consumer<Param> consumer)
    
    • OR 嵌套
    • 例: or(i -> i.eq("name", "李白").ne("status", "活着"))--->or (name = '李白' and status <> '活着')

    and

    and(Consumer<Param> consumer)
    and(boolean condition, Consumer<Param> consumer)
    
    • AND 嵌套
    • 例: and(i -> i.eq("name", "李白").ne("status", "活着"))--->and (name = '李白' and status <> '活着')

    nested

    nested(Consumer<Param> consumer)
    nested(boolean condition, Consumer<Param> consumer)
    
    • 正常嵌套 不带 AND 或者 OR
    • 例: nested(i -> i.eq("name", "李白").ne("status", "活着"))--->(name = '李白' and status <> '活着')

    apply

    apply(String applySql, Object... params)
    apply(boolean condition, String applySql, Object... params)
    
    • 拼接 sql ::: warning 注意事项: 该方法可用于数据库函数 动态入参的params对应前面applySql内部的{index}部分.这样是不会有sql注入风险的,反之会有! :::
    • 例: apply("id = 1")--->id = 1
    • 例: apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
    • 例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")--->date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

    last

    last(String lastSql)
    last(boolean condition, String lastSql)
    
    • 无视优化规则直接拼接到 sql 的最后 ::: tip 注意事项: 只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用 :::
    • 例: last("limit 1")

    exists

    exists(String existsSql)
    exists(boolean condition, String existsSql)
    
    • 拼接 EXISTS ( sql语句 )
    • 例: exists("select id from table where age = 1")--->exists (select id from table where age = 1)

    notExists

    notExists(String notExistsSql)
    notExists(boolean condition, String notExistsSql)
    
    • 拼接 NOT EXISTS ( sql语句 )
    • 例: notExists("select id from table where age = 1")--->not exists (select id from table where age = 1)

    QueryWrapper

    ::: tip 说明: 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
    及 LambdaQueryWrapper, 可以通过 new QueryWrapper().lambda() 方法获取 :::

    select

    select(String... sqlSelect)
    select(Predicate<TableFieldInfo> predicate)
    select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
    
    • 设置查询字段 ::: tip 说明: 以上方法分为两类.
      第二类方法为:过滤查询字段(主键除外),入参不包含 class 的调用前需要wrapper内的entity属性有值! 这两类方法重复调用以最后一次为准
      :::
    • 例: select("id", "name", "age")
    • 例: select(i -> i.getProperty().startsWith("test"))

    UpdateWrapper

    ::: tip 说明: 继承自 AbstractWrapper ,自身的内部属性 entity 也用于生成 where 条件
    LambdaUpdateWrapper, 可以通过 new UpdateWrapper().lambda() 方法获取! :::

    set

    set(String column, Object val)
    set(boolean condition, String column, Object val)
    
    • SQL SET 字段
    • 例: set("name", "老李头")
    • 例: set("name", "")--->数据库字段值变为空字符串
    • 例: set("name", null)--->数据库字段值变为null

    setSql

    setSql(String sql)
    
    • 设置 SET 部分 SQL
    • 例: setSql("name = '老李头'")

    lambda

    • 获取 LambdaWrapper
      QueryWrapper中是获取LambdaQueryWrapper
      UpdateWrapper中是获取LambdaUpdateWrapper

    逻辑删除

    说明: 只对自动注入的 sql 起效:

    • 插入: 不作限制
    • 查找: 追加 where 条件过滤掉已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段
    • 更新: 追加 where 条件防止更新到已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段
    • 删除: 转变为 更新

    例如:

    • 删除: update user set deleted=1 where id = 1 and deleted=0
    • 查找: select id,name,deleted from user where deleted=0

    字段类型支持说明:

    • 支持所有数据类型(推荐使用 Integer,Boolean,LocalDateTime)
    • 如果数据库字段使用datetime,逻辑未删除值和已删除值支持配置为字符串null,另一个值支持配置为函数来获取值如now()

    附录:

    • 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
    • 如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。 :::

    使用方法

    步骤 1: 配置com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig

    • 例: 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注解

    @TableLogic
    private Integer deleted;
    

    常见问题

    1. 如何 insert ?

    1. 字段在数据库定义默认值(推荐)
    2. insert 前自己 set 值
    3. 使用 自动填充功能

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

    1. 使用 update 方法并: UpdateWrapper.set(column, value)(推荐)
    2. 使用 update 方法并: UpdateWrapper.setSql("column=value")
    3. 使用 Sql 注入器 注入 com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill 并使用(推荐)

    自动填充功能

    示例工程:

    mybatis-plus-sample-auto-fill-metainfo

    原理:

    • 实现元对象处理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
    • 注解填充字段 @TableField(.. fill = FieldFill.INSERT) 生成器策略部分也可以配置!
    public class User {
    
        // 注意!这里需要标记为填充字段
        @TableField(.. fill = FieldFill.INSERT)
        private String fillField;
    
        ....
    }
    
    • 自定义实现类 MyMetaObjectHandler
    @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)
        }
    }
    

    ::: warning 注意事项:

    • 填充原理是直接给entity的属性设置值!!!
    • 注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
    • MetaObjectHandler提供的默认方法的策略均为:如果属性有值则不覆盖,如果填充值为null则不填充
    • 字段必须声明TableField注解,属性fill选择对应策略,该声明告知Mybatis-Plus需要预留注入SQL字段
    • 填充处理器MyMetaObjectHandler在 Spring Boot 中需要声明@Component@Bean注入
    • 要想根据注解FieldFill.xxx字段名以及字段类型来区分必须使用父类的strictInsertFill或者strictUpdateFill方法
    • 不需要根据任何来区分可以使用父类的fillStrategy方法 :::
    public enum FieldFill {
        /**
         * 默认不处理
         */
        DEFAULT,
        /**
         * 插入填充字段
         */
        INSERT,
        /**
         * 更新填充字段
         */
        UPDATE,
        /**
         * 插入和更新填充字段
         */
        INSERT_UPDATE
    }
    
  • 相关阅读:
    pytest-html报告自定义字段
    Python SMTP发送邮件
    IE浏览器兼容测试工具 IETester
    全局ID生成--雪花算法改进版
    全局ID生成--雪花算法
    spring-cloud-sleuth/zipkin
    14.跑批到某个点突然所有批都断批
    13.分布式锁在不同环境引发的坑
    spring-cloud-gateway
    spring-cloud-netflix-config
  • 原文地址:https://www.cnblogs.com/qs315/p/15726026.html
Copyright © 2011-2022 走看看