1 概述

在mybatis基础上只做增强不作改变。为简化开发、提高效率而生

1.1 特点

  • 无侵入:对现有的工程不会产生影响
  • 损耗小:启动即会自动注册curd,性能基本无损耗,直接面向对象操作
  • 强大的curd功能:内置通用mapper、通用service,仅仅通过少量配置即可实现表单大部分surd操作,具有强大的条件构造器,满足各类使用需求
  • 支持lambda形式调用
  • 支持主键自动生成
  • 支持ActiveRecord模式
  • 支持自定义全局通用操作
  • 内置代码生成器
  • 内置分页插件
  • 分页插件支持多种数据库
  • 内置性能分析插件
  • 内置全局拦截插件

1.2 使用

官网:https://baomidou.com/

spring boot

  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus-boot-starter</artifactId>
  4. <version>3.4.3.4</version>
  5. </dependency>

dao层

package com.example.demo.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.demo.pojo.UserPo;

/**
 * @Author gett
 * @Date 2021/11/22  15:19
 * @Description
 */

public interface UserDao extends BaseMapper<UserPo> {
    //UserPo是表实体
}

启动类配置注解@MapperScan

package com.example.demo;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.example.demo.dao")
public class DemoApplication  {

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


}

spring

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>mybatis-plus-latest-version</version>
</dependency>
<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>

1.3 注解

@TableName

属性 类型 必须指定 默认值 描述
value String “” 表名
schema String “” schema
keepGlobalPrefix boolean false 是否保持使用全局的 tablePrefix 的值(如果设置了全局 tablePrefix 且自行设置了 value 的值)
resultMap String “” xml 中 resultMap 的 id
autoResultMap boolean false 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建并注入)
excludeProperty String[] {} 需要排除的属性名(@since 3.3.1)

@TableId

属性 类型 必须指定 默认值 描述
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 “” 数据库字段名
el String “” 映射为原生 #{ … } 逻辑,相当于写在 xml 里的 #{ … } 部分
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 N DEFAULT 举例:NOT_NULL: insert into table_a(column) values (#{columnProperty})
updateStrategy Enum N DEFAULT 举例:IGNORED: update table_a set column=#{columnProperty}
whereStrategy Enum N DEFAULT 举例:NOT_EMPTY: where column=#{columnProperty}
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 “” 指定小数点后保留的位数,只生效于update

FieldStrategy

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

FieldFill

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

@Version

乐观锁注解

@EnumValue

枚举类注解

@TableLogic

表字段逻辑处理的注解(逻辑删除)

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

@KeySequence

序列主键策略oracle

属性 类型 必须指定 默认值 描述
value String “” 序列名
clazz Class Long.class id的类型, 可以指定String.class,这样

@OrderBy

默认指定排序,优先级低于wrapper条件查询

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

2 核心功能

2.1 service curd 接口

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

records 用来存放查询出来的数据
total 返回记录的总数
size 每页显示条数,默认 10
current 当前页,默认1
orders 排序字段信息
optimizeCountSql 自动优化 COUNT SQL,默认true
isSearchCount 是否进行 count 查询,默认true
hitCount 是否命中count缓存,默认false
pages是mp给我们自动配置出来用来传给前端表示总共有几页的参数

Count

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

2.2 mapper crud接口

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 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 columnMap 表字段 map 对象
IPage page 分页查询条件(可以为 RowBounds.DEFAULT

2.3 条件构造器

2.3.1 AbstractWrapper

QueryWrapper和UpdateWrapper的父类
用于生成sql的where条件,entity属性用于生成sql的where条件

allEq 全部eq或个别isNull

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则在map的value为null时调用 isNull 方法,为false时则忽略value为null的

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 : 过滤函数,是否允许字段传入比对条件中
params 与 null2IsNull : 同上

eq = 和ne !=

eq(R column, Object val)
eq(boolean condition, R column, Object val)

gt 大于和ge 大于等于

gt(R column, Object val)
gt(boolean condition, R column, Object val)


It 小于和Ie 小于等于

It(R column, Object val)
It(boolean condition, R column, Object val)

between 和not between

between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)

like和notlike和likeLeft和likeRight

like(R column, Object val)
like(boolean condition, R column, Object val)

likeLeft(“name”, “王”)—->name like ‘%王’

isNull和isNotNull

isNull(R column)
isNull(boolean condition, R column)

in和notIn

in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
in(R column, Object... values)
in(boolean condition, R column, Object... values)

inSql和notInSql

inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)

groupby

groupBy(R... columns)
groupBy(boolean condition, R... columns)

orderByDesc

orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)

orderBy

orderBy(boolean condition, boolean isAsc, R... columns)

having

having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)

func

func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)

主要方便在出现if…else下调用不同方法能不断链

or

or()
or(boolean condition)

or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)

or(i -> i.eq(“name”, “李白”).ne(“status”, “活着”))—->or (name = ‘李白’ and status <> ‘活着’)

and

and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)

nested

nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)

apply

apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)

exists和notExists

exists(String existsSql)
exists(boolean condition, String existsSql)

2.3.2 QueryWrapper

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

2.3.3 UpdateWrapper

set

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

setSql

setSql(String sql)

2.4 分页插件

2.5 Sequence主键

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

2.6 自定义ID生成器

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

2.7 配置

mybatis-plus:
    mapper-locations: classpath:/mapper/*.xml

3 代码生成器

                <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.31</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
package com.example.demo.config;


import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;

import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * @Author gett
 * @Date 2021/11/22  17:35
 * @Description
 */

public class CodeGenerator {
    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotBlank(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }

    @Test
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("Oneby");
        gc.setOpen(false);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/demo?useSSL=false&useUnicode=true&characterEncoding=utf-8" +
                "&serverTimezone=GMT%2B8");
        // dsc.setSchemaName("public");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("root");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(scanner("模块名"));
        pc.setParent("com.oneby");
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }

        });
        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir("调用默认方法创建的目录,自定义目录用");
                if (fileType == FileType.MAPPER) {
                    // 已经生成 mapper 文件判断存在,不想重新生成返回 false
                    return !new File(filePath).exists();
                }
                // 允许生成模板文件
                return true;
            }
        });
        */
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        // strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 公共父类
        // strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 写于父类中的公共字段
        strategy.setSuperEntityColumns("id");
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix("t_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}