MyBatisPlus总结

MyBatis-Plus时Mybatis的Best Partner

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

特性

  • 无侵入
  • 损耗小
  • 强大的 CRUD 操作
  • 支持 Lambda 形式调用
  • 支持主键自动生成
  • 支持 ActiveRecord 模式
  • 支持自定义全局通用操作
  • 内置代码生成器
  • 内置分页插件
  • 分页插件支持多种数据库
  • 内置性能分析插件
  • 内置全局拦截插件

#支持数据库

框架结构

引入 MyBatis-Plus 之后请不要再次引入 MyBatis 以及 mybatis-spring-boot-starter和MyBatis-Spring,以避免因版本差异导致的问题

注解

@TableName

描述:表名注解,标识实体类对应的表

使用位置:实体类

注意: 默认是以对象名为表名,可以配置全局配置名字增加前缀,

也可以用@TableName进行注释表名,如下(同时配置,注解生效)

。@TableName("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. 定义在 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

指定主键类型(在不写type类型的时候默认为雪花算法)

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 长整型类型(pleaseuseASSIGN_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

是否为数据库表字段

condition

String

""

字段

where

实体查询比较条件,有值设置则按设置的值为准,没有则为默认全局的

%s=#{%s}

参考

@Version

描述:乐观锁注解,标记@version在字段上

@EnumValue

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

@TableLogic

描述:表字段逻辑处理注解(逻辑删除)

属性

类型

必须指定

默认值

描述

value

String

""

逻辑未删除值

delval

String

""

逻辑删除值

@OrderBy

描述:内置Sql默认指定排序,优先级低于wrapper条件查询

属性

类型

必须指定

默认值

描述

asc

boolean

true

是否倒序查询

sort

short

Short.MAX_VALUE

数字越小越靠前

@Mapper

写在Dao类上,将类注入Spring容器中

@MapperScan()

@MapperScan(value = {"com.aqiuo.dao"})

写在启动类上,将需要扫描的包写在value中

CRUD接口

Service CRUD 接口

说明: 通用 Service CRUD 封装IService (opens new window)

  • 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 注解存在更新记录,否插入一条记录,
//如果有这个记录,则修改记录,如果没有就插入记录
//如果没有id就是插入,有就是修改
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

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

参数说明

类型

参数名

描述

Wrapper

queryWrapper

实体包装类 QueryWrapper

Serializable

id

主键 ID

Map

columnMap

表字段 map 对象

Collection

idList

主键 ID 列表

Update

(注意updateById才能根据id修改内容,其他的要用wrapper)

// 根据 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

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

idList

主键 ID 列表

Map

columnMap

表字段 map 对象

Function

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 (返回值类型是lanmdateQuery)

(存在有一个静态方法引用非静态方法的问题)

// 链式查询 普通
QueryChainWrapper<T> query();
// 链式查询 lambda 式。注意:不支持 Kotlin
LambdaQueryChainWrapper<T> lambdaQuery();// 示例:
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();
update(返回值是LamdaQueryWrapper)
// 链式更改 普通
UpdateChainWrapper<T> update();
// 链式更改 lambda 式。注意:不支持 Kotlin
LambdaUpdateChainWrapper<T> lambdaUpdate();// 示例:
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);

Mapper CRUD 接口

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

Insert

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

参数说明

类型

参数名

描述

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

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

使用提示:

在调用updateById方法前,需要在T entity(对应的实体类)中的主键属性上加上@TableId注解。

参数说明

类型

参数名

描述

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

idList

主键 ID 列表(不能为 null 以及 empty)

Map

columnMap

表字段 map 对象

IPage

page

分页查询条件(可以为 RowBounds.DEFAULT)

条件构造器

说明:

  • 以下出现的第一个入参 boolean condition 表示该条件是否加入最后生成的sql语句中,例如:
    • query.like(StringUtils.isNotBlank(name),Entity::getName,name).eq(age!=null && age>=0,Entity::getAge,age)
  • 以下代码块内的多个方法均从上往下补全个别 boolean 类别的入参,默认为 true
  • 以下方法在入参中出现的 R 为泛型,在普通wrapper中 是String, 在 LambdaWrapper 中是函数
    • 例如: Entity::getId,Entity 为实体类,getId 为字段 id 的getter Method)
  • 以下方法入参中的 R column 均为数据库字段,当 R 具体类型为 String 时则为数据库字段名(字段名是数据库关键字的自己用转义符包裹!)
  • 以下举例均为使用普通wrapper ,入参为Map 和List 的均以json形式表现!
  • 如果入参的Map或者List为空,则不会加入最后生成的SQL中!!!

警告

  1. wrapper 很重
  2. 传输 wrapper 可以类比为你的 controller 用 map 接收值(开发一时爽,维护火葬场)
  3. 正确的 RPC 调用姿势是写一个 DTO 进行传输,被调用方再根据 DTO 执行相应的操作
  4. 我们拒绝接受任何关于 RPC 传输 Wrapper 报错相关的 issue 甚至 pr

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)

全部eq(或个别isNull)

个别参数说明:

  • params : key 为数字库字段名 value为 字段值
  • null2IsNull: 为true,则 在 map 的value为null时调用isNull方法,为false,则忽略value的值为null的

例一:allEq({id:1,name:"老王",age:null}) --->id = 1 and name = '老王' and age is null

例二:allEq({id:1,name:"老王",age:null}, false)-->id = 1 and 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

#between

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

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(R column, Object val) like(boolean condition, R column, Object val)

  • LIKE '%值%'
  • 例: like("name", "王")--->name like '%王%'

#notLike

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

  • NOT LIKE '%值%'
  • 例: notLike("name", "王")--->name not like '%王%'

#likeLeft

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

  • LIKE '%值'
  • 例: likeLeft("name", "王")--->name like '%王'

likeRight

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

  • LIKE '值%'
  • 例: likeRight("name", "王")--->name like '王%'

notLikeLeft

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

  • NOT LIKE '%值'
  • 例: notLikeLeft("name", "王")--->name not like '%王'

notLikeRight

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

  • NOT LIKE '值%'
  • 例: notLikeRight("name", "王")--->name not like '王%'

#isNull

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

  • 字段 IS NULL
  • 例: isNull("name")--->name is null

isNotNull

isNotNull(R column) isNotNull(boolean condition, R column)

  • 字段 IS NOT NULL
  • 例: isNotNull("name")--->name is not null

in

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

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

注意事项:

主动调用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
    • 注意事项:

该方法可用于数据库函数 动态入参的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 的最后

注意事项:

只能调用一次,多次调用以最后一次为准 有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

说明:

继承自 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属性有值! 这两类方法重复调用以最后一次为准

  • 例: select("id", "name", "age")
  • 例: select(i -> i.getProperty().startsWith("test"))

UpdateWrapper

说明:

继承自 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

(这个lambda可以用方法引用,其他不行,支持链式编程)

  • 获取 LambdaWrapper

在QueryWrapper是LambdaQueryWrapper

在UpdateWrapper是LambdaUpdateWrapper

乐观OptimisticLockerInnerInterceptor

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

乐观锁实现方式:

取出记录时,获取当前 version更新时,带上这个 version执行更新时, set version = newVersion where version = oldVersion如果 version 不对,就更新失败

spring boot 注解方式:

@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; } }

代码生成器

引入依赖

<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>最新版本</version> </dependency>

快速生成

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/166735.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android开发从0开始(广播)

应用广播 发送标准广播的三步骤 发送标准广播&#xff1a; //发送标准广播 Intent intent new Intent("com.dongnaoedu.chapter09.standard"); sendBroadcast(intent); 定义广播接受者: public class StanderdReceiver extends BroadcastReceiver { public s…

在ASP.NET Core 中使用 .NET Aspire 消息传递组件

前言 云原生应用程序通常需要可扩展的消息传递解决方案&#xff0c;以提供消息队列、主题和订阅等功能。.NET Aspire 组件简化了连接到各种消息传递提供程序&#xff08;例如 Azure 服务总线&#xff09;的过程。在本教程中&#xff0c;小编将为大家介绍如何创建一个 ASP.NET …

PLC通过RS232转PROFINET与电子分析天平秤通讯案例

本案例是通过用兴达易控的XD-PNR200型RS232转Profinet网关连接电子分析天平秤与PLC通讯的配置案例&#xff0c;用到设备为西门子S7-1200PLC&#xff0c;RS232转Profinet网关&#xff0c;电子分析天平秤。 打开博图&#xff0c;添加PLC&#xff1b;本案例使用的是1200PLC。 添加…

『接口测试干货』| Newman+Postman接口自动化测试完整过程

『接口测试干货』| NewmanPostman接口自动化测试完整过程 1 Newman简介2 如何安装Newman&#xff1f;2.1 安装NodeJs2.2 安装Newman2.2 解决Newman不是内部命令 3 Newman使用3.1 Newman如何运行集合&#xff1f;3.2 如何查看帮助文档&#xff1f;3.3 环境变量设置3.4 关于全局变…

微信小程序制作

如果你也想搭建一个小程序&#xff0c;但不知道如何入手&#xff0c;那么今天我就教你如何使用第三方制作平台&#xff0c;在短短三十分钟内搭建一个小程序。 一、登录小程序制作平台 首先&#xff0c;登录到小程序制作平台的官方网站或应用程序&#xff0c;进入后台管理系统。…

文章解读与仿真程序复现思路——电网技术 EI\CSCD\北大核心《考虑5G基站储能可调度容量的有源配电网协同优化调度方法》

这篇文章的标题涉及到以下关键概念&#xff1a; 5G基站&#xff1a; 提到了5G基站&#xff0c;这表明文章的焦点可能是与第五代移动通信技术相关的内容。5G技术对于提高通信速度、降低延迟以及支持大规模连接等方面有显著的改进&#xff0c;因此对于基站的电力需求和供应可能存…

2023年ESG投资研究报告

第一章 ESG投资概况 1.1 定义 ESG投资&#xff0c;亦称负责任投资&#xff0c;是一种融合环境&#xff08;Environment&#xff09;、社会&#xff08;Social&#xff09;和治理&#xff08;Governance&#xff09;考量的投资方法&#xff0c;旨在通过综合这些因素来优化投资…

美国汽车零部件巨头 AutoZone 遭遇网络攻击

Security Affairs 网站披露&#xff0c;美国汽车配件零售商巨头 AutoZone 称其成为了 Clop MOVEit 文件传输网络攻击的受害者&#xff0c;导致大量数据泄露。 AutoZone 是美国最大的汽车零配件售后市场经销商之一&#xff0c;在美国、墨西哥、波多黎各、巴西和美属维尔京群岛经…

「Whale 帷幄」连续入选科技榜单,AGI 冲击波正在加速行业洗牌

以 AGI 为底座&#xff0c;品牌 MarTech 正在经历一场前所未有的深度变革。 近日&#xff0c;弯弓研究院发布「中国 MarTech 500 强榜单」&#xff0c;以 2023 中国营销技术&#xff08;MarTech&#xff09;生态为研究对象&#xff0c;洞察行业现象与未来趋势。作为品牌数字化…

前后端性能优化实践(含Java代码部分、数据库部分、React前端部分)

最近的一个大屏报表统计的接口查询速度很慢&#xff0c;耗时近一分钟左右&#xff0c;数据量级只是700万左右&#xff0c;但很慢&#xff0c;最后优化到4秒左右&#xff0c;客户还能接受&#xff0c;但其实还可以在优化&#xff0c;先这样吧&#xff0c;简单记录下。这次主要优…

App Inventor 2 文本转数字

App Inventor 2 是弱语言类型&#xff0c;文本和数字之间不用刻意去转换&#xff0c;之间赋值就可以了。文本赋值给数字变量如下&#xff1a; 运行结果&#xff1a;124 注意&#xff1a;数字变量初始化的时候要给一个数字的初始值&#xff0c;表明它是数字。 如果文本中含有非…

系列三、事务

一、事务 1.1、概述 事务是数据库操作的基本单元&#xff0c;它是指逻辑上的一组操作&#xff0c;要么都成功&#xff0c;要么都失败。典型场景&#xff1a;转账&#xff0c;例如Jack给Rose转账1000元&#xff0c;转账成功&#xff1a;Jack账户的余额少1000元&#xff0c;Rose…

关于进制的转化

二进制转十进制&#xff1a; &#x1f530; 方法一&#xff1a;二进制转十进制&#xff0c;用各数的码位与位权的乘积之和&#xff0c;说白了就是用从右到左的每个数去乘以2的幂次方&#xff08;最右边是0&#xff09;&#xff0c;然后就所有的数相加。 补充&#xff1a;位权是…

<蓝桥杯软件赛>零基础备赛20周--第7周--栈和二叉树

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…

MFC所有控件介绍及基本使用

一、前言 本篇文档介绍了MFC控件的基本使用&#xff0c;同时提供了关于MFC控件使用的工程代码&#xff0c;程序界面如下图&#xff0c;有兴趣的可以到文档最后的链接处进行下载。 二、控件介绍 2.1 Button &#xff08;按钮&#xff09; 2.2 CheckBox&#xff08;复选框&am…

【jvm】虚拟机之堆

目录 一、堆的核心概述二、堆的内存细分&#xff08;按分代收集理论设计&#xff09;2.1 java7及以前2.2 java8及以后 三、堆内存大小3.1 说明3.2 参数设置3.3 默认大小3.4 手动设置3.5 jps3.6 jstat3.7 OutOfMemory举例 四、年轻代与老年代4.1 说明 五、对象分配过程5.1 说明5…

电脑键盘推荐

一、键盘分类 &#xff08;1&#xff09;键位个数 目前有75&#xff0c;84&#xff0c;87&#xff0c;98&#xff0c;104&#xff0c;108的。 &#xff08;2&#xff09;薄膜键盘和机械键盘 薄膜键盘就是大多数办公室常见的键盘&#xff0c;主要打一个便宜&#xff0c;耐造…

Python武器库开发-前端篇之Html基础语法(二十九)

前端篇之Html基础语法(二十九) HTML 元素 HTML元素指的是HTML文档中的标签和内容。标签用于定义元素的类型&#xff0c;而内容则是元素所包含的内容。HTML元素由开始标签和结束标签组成&#xff0c;也可以是自闭合标签。 例如&#xff0c;下面是一个叫做<p>的HTML元素…

Android开发从0开始(服务)

Android后台运行的解决方案&#xff0c;不需要交互&#xff0c;长期运行。 服务基础框架&#xff1a; public class MyService extends Service { public MyService() { } Override public IBinder onBind(Intent intent) { //activity与service交互&#xff08;需要继…

全网最全图解Kafka适用场景

消息系统 消息系统被用于各种场景&#xff0c;如解耦数据生产者&#xff0c;缓存未处理的消息。Kafka 可作为传统的消息系统的替代者&#xff0c;与传统消息系统相比&#xff0c;kafka有更好的吞吐量、更好的可用性&#xff0c;这有利于处理大规模的消息。 根据经验&#xff…