MyBatisPlus基本了解使用

712 阅读11分钟

入门

简介

Mybatis-Plus(简称:MP),是一个Mybatis的增强工具,在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 操作智能分析阻断,也可自定义拦截规则,预防误

操作

代码生成器

AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、

Mapper、 XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。

    public void generator(){
        FastAutoGenerator.create("jdbc:mysql://localhost:3306/drj",
                        "root", "xxxx")
                .globalConfig(builder -> {
                    builder.author("dairuijie") // 设置作者
                            .enableSwagger() // 开启 swagger 模式// .fileOverride() // 覆盖已生成文件,默认值:false
                            .disableOpenDir() //禁止打开输出目录,默认值:true
                            .dateType(DateType.ONLY_DATE) //定义生成的实体 类中日期类型 时间策略 DateType.ONLY_DATE 默认值: DateType.TIME_PACK
                            .outputDir("D:\\mpdemo" +
                                    "/src/main/java"); // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent("com.chonger.eg") // 设置父包名
                            .moduleName("user3") // 设置父包模块名表名注解,应用于类上

                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml,
                                    "D:\\mpdemo" + "/src/main/resources/mapper")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude("ym_user") // 设置需要生成的表名
                            .addTablePrefix("ym_"); // 设置过滤表前缀
                    builder.entityBuilder()
                            .naming(NamingStrategy.underline_to_camel)//  数据库表映射到实体的命名策略.默认下划线转驼峰命名

                            .columnNaming(NamingStrategy.underline_to_camel)//数据库表字段映射到实体的命名策略,默认为 null,未指定按照 naming 执行
                            .addTableFills(new Column("createTime",
                                    FieldFill.INSERT))
                            .addTableFills(new Property("updateTime",
                                    FieldFill.INSERT_UPDATE))
                            .idType(IdType.AUTO) //主键策略
                            .enableLombok();//开启 lombok 模型,默认 值:false
                    builder.controllerBuilder()
                            .enableHyphenStyle()//开启驼峰转连字符,默认 值:false
                            .enableRestStyle();//开启生成@RestController 控制器,默认值:false
                    builder.serviceBuilder()
                            .formatServiceImplFileName("%sServiceImp")// 格式化 service 实现类文件名称
                            .formatServiceFileName("%sService");//格式化 service 接口文件名称,去掉Service接口的首字母I
                })
                .strategyConfig(builder -> {
                })
// .templateEngine(new FreemarkerTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
    

注解配置

TableName

value: 表名,默认为“”

schema:schema,默认为“”

keepGlobalPrefix:是否保持使用全局的tablePrefix值(如果设置了全局tablePrefix且自行设置

了value的值),默认为false

resultMap:xml中resultMap的id,默认为“”

autoResultMap:是否自动构建 resultMap 并使用,默认为false

excludeProperty:需要排除的属性名

以上都为非必输项。

TableId

主键注解,应用于主键字段上

value:主键字段名,默认为“”

type:主键类型,默认为IdType.NONE

以上都为非必输项。

IdType:

AUTO:数据库ID自增

NONE:无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)

INPUT:insert前自行set主键值

ASSIGN_ID:分配ID,主键类型为Number(Long和Integer)或String,版本

3.3.0以上,使用接口

IdentifierGenerator的方法nextId(默认实现类为

DefaultIdentifierGenerator 雪花算法)

ASSIGN_UUID:分配UUID,主键类型为String,版本3.3.0以上,使用接口

IdentifierGenerator的方法nextUUID

以下已过时,不建议使用:

ID_WORKER:分布式全局唯一ID 长整型类型,使用ASSIGN_ID代替

UUID:32位UUID字符串,使用ASSIGN_UUID代替

ID_WORKER_STR:分布式全局唯一ID 字符串类型,使用ASSIGN_ID代替

TableField

字段注解(非主键)

value:数据库字段名

el:映射为原生#{}逻辑,相当于写在xml中的#{}部分

exist:是否为数据库表字段,默认为true

condition:where查询比较条件,如果设置了值,则获取设置的值,如果没有则默认为全局的-

->%s=#{%s},%s会填充为字段名

参考:链接

update:字段update set部分注入,例如:字段名 = ‘%s+1’,表示更新时,会set

version=version+1

该属性优先级高于el。

insertStrategy:字段验证策略之 insert: 当insert操作时,该字段拼接insert语句时的

策略

IGNORED: 直接拼接

NOT_NULL: 判断是否为空NULL后,在决定是否拼接

NOT_EMPTY: 判断是否为NULL和‘’后,在决定是否拼接

DEFAULT:默认的,一般只用于注解里,在全局里代表 NOT_NULL,在注解里代表 跟

随全局

eg:

insert into table (字段名)

values (#{字段名})

updateStrategy:字段验证策略之 update: 当更新操作时,该字段拼接set语句时的策略

IGNORED: 直接拼接

NOT_NULL:判断是否为空NULL后,在决定是否拼接

NOT_EMPTY:判断是否为NULL和‘’后,在决定是否拼接

DEFAULT:默认的,一般只用于注解里,在全局里代表 NOT_NULL,在注解里代表 跟

随全局

whereStrategy:段验证策略之 where: 表示该字段在拼接where条件时的策略

IGNORED: 直接拼接

NOT_NULL:判断是否为空NULL后,在决定是否拼接

NOT_EMPTY:判断是否为NULL和‘’后,在决定是否拼接

DEFAULT:默认的,一般只用于注解里,在全局里代表 NOT_NULL,在注解里代表 跟

随全局

fill:字段自动填充策略,在对应模式下将会忽略 insertStrategy 或 updateStrategy

的配置,等于断言该字段必有值

FieldFill:

DEFAULT:默认不处理

INSERT:插入时填充字段

UPDATE:更新时填充字段

INSERT_UPDATE:插入和更新时填充字段

select:是否进行 select 查询,值大字段可设置为 false 不加入 select 查询范围,提

高响应效率

keepGlobalFormat:是否保持使用全局的 columnFormat 的值

只生效于既设置了全局的 columnFormat 也设置了上面vaule的值,如果是 false

, 全局的 columnFormat 不生效

jdbcType:JDBC类型,只生效于 mp 自动注入的 method,一般和autoResultMap一起使用

typeHandler:类型处理器,只生效于 mp 自动注入的 method,一般和autoResultMap一起

使用

numericScale:指定小数点后保留的位数,只生效于 mp 自动注入的 method,一般和

autoResultMap一起使用

Version

  • 乐观锁注解、在对应的字段上,使用@version注解字段

EnumValue

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

TableLogic

  • 表字段逻辑处理注解

  • 逻辑删除字段上 value:未删除的值 delval:已删除的值

  • 一般在3.3.0版本以上,此注解建议过时,可直接在springboot的配置文件中,一次性指定逻辑字段、未删除的值和已删除的值

逻辑删除

全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)

mybatis-plus.global-config.db-config.logic-delete-field= 逻辑删除的字段名

逻辑已删除值(默认为 1) mybatis-plus.global-config.db-config.logic-delete-value=1

逻辑未删除值(默认为 0) mybatis-plus.global-config.db-config.logic-not-delete-value=0

KeySequence主键

  • 序列主键策略,作用于类上

value:序列名

dbType:数据库类型,未配置默认使用注入 IKeyGenerator 实现,多个实现必须指定

OrderBy

  • 内置 SQL 默认指定排序
  • 优先级低于 wrapper 条件查询

isDesc:是否倒序查询,默认true,false为正序

ase:默认false

sort:数字越小越靠前,默认Short.MAX_VALUE

API功能

说明

  • 一般简单的CRUD操作,我们可以直接使用mapper接口进行操作,无需写xml和service
  • 但是在常规企业研发中,一般我们会涉及很多复杂的sql和业务,以及规范要求,不写xml和service则无法满足所以,一般我们会进行封装IService接口,进一步封装CRUD接口,采用更符合规范的命名来进行API书写,避免和mapper接口混淆
  • 同样,也有对应的 T 泛型,为任意实体对象
  • 创建自己的IService继承Mybatis-plus提供的基类
  • 对象Wrapper为条件构造器

IService层API

save

boolean save(T entity);
// 插入(批量,一次性插入)
boolean saveBatch(Collection<T> entityList);//执行1条sql,将数据全部一次性插入
// 插入(批量,batchSize:插入批次数量,默认批次提交数量=1000)
boolean saveBatch(Collection<T> entityList, int batchSize);//可查看控制台日志,
例如batchSize=2,则执行了2条sql

saveOrUpdate

boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);//先执行update,如
果为0,则执行insert
// 批量修改插入,没执行一条数据,都先SELECT,然后update或者insert
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入,batchSize:插入批次数量,默认批次提交数量=1000
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

Remove

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

Update

boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新,1条sql执行
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新,batchSize条sql执行
boolean updateBatchById(Collection<T> entityList, int batchSize);

Get

T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,取一条加上限制条件
wrapper.last("LIMIT 1")
// 随机取则加:order by rand() limit 1
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录,有多个 result 是否抛出异常,如果为false则输出多个记
录
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);

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

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

Count

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

Chain

QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();
// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list()


// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();
// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);

Mapper层API

insert

int insert(T entity);

delete

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

Select

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

Update

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

条件表达构造器

  • boolean condition:表示该条件是否加入最后生成的sql中
  • 不支持以及不赞成在 RPC 调用中把 Wrapper 进行传输。wrapper 很重,正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
  • QueryWrapper和UpdateWrapper都是用于生成sql的where条件,包含Lambda

image.png