第 4 章 MybatisPlus 条件构造器
第 4 章 MybatisPlus 条件构造器
1、CRUD API 的思考
对于 BaseMapper 中基本 CRUD 方法的思考
继承了 BaseMapper 接口后,我们只能获得基本的 CRUD 能力,那么对于复杂的 SQL 查询,MybatisPlus 貌似也无能为力,但其实并不是这样的
现有一个需求,我们需要分页查询 t_user
表中,年龄在 18~50 之间性别为男且姓名为 xx的所有用户,这时候我们该如何实现上述需求呢?
MyBatis:需要在 SQL映射文件中编写带条件查询的 SQL,并基于 PageHelper插件完成
分页 . 实现以上一个简单的需求,往往需要我们做很多重复单调的工作。
MP:依旧不用编写 SQL语句,MP提供了功能强大的条件构造器 QueryMapper
和 LambdaQueryWrapper
2、AbstractWrapper
条件构造器的抽象父类:AbstractWrapper
AbstractWrapper
是 QueryWrapper
(LambdaQueryWrapper
) 和 UpdateWrapper
(LambdaUpdateWrapper
) 的父类用于生成 sql 的 where
条件,entity
属性也用于生成 sql 的 where
条件
Wrapper
可理解为实体包装器, 主要用于处理 sql 拼接、排序、实体参数查询等。
/*** 查询条件封装** @author hubin miemie HCL* @since 2017-05-26*/
@SuppressWarnings({"serial", "unchecked"})
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {/*** 占位符*/protected final Children typedThis = (Children) this;/*** 必要度量*/protected AtomicInteger paramNameSeq;protected Map<String, Object> paramNameValuePairs;protected SharedString lastSql;/*** SQL注释*/protected SharedString sqlComment;/*** SQL起始语句*/protected SharedString sqlFirst;/*** ß* 数据库表映射实体类*/private T entity;protected MergeSegments expression;/*** 实体类型(主要用于确定泛型以及取TableInfo缓存)*/private Class<T> entityClass;@Overridepublic T getEntity() {return entity;}public Children setEntity(T entity) {this.entity = entity;return typedThis;}
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
的字段
例子
- 例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 = '老王'
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(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 '%王'
leftRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
- LIKE ‘值%’
- 例:
likeRight("name", "王")
—>name 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)
3、QueryWrapper
1、AbstractWrapper 的实现类之一:QueryWrapper
QueryWrapper
继承自 AbstractWrapper
,自身的内部属性 entity
也用于生成 where
条件
及 LambdaQueryWrapper
,可以通过 new QueryWrapper().lambda()
方法获取
QueryWrapper
使用的是数据库字段,不是 Java属性!
/*** Entity 对象封装操作类** @author hubin miemie HCL* @since 2018-05-25*/
@SuppressWarnings("serial")
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>implements Query<QueryWrapper<T>, T, String> {/*** 查询字段*/private final SharedString sqlSelect = new SharedString();public QueryWrapper() {this(null);}public QueryWrapper(T entity) {super.setEntity(entity);super.initNeed();}public QueryWrapper(T entity, String... columns) {super.setEntity(entity);super.initNeed();this.select(columns);}
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"))
2、AbstractWrapper 的实现类之一:LambdaQueryWrapper
在QueryWrapper
中可以获取到获取LambdaQueryWrapper
对象,LambdaQueryWrapper
支持使用 类名 : getXxx()
的方式构造 SQL 语句
/*** 返回一个支持 lambda 函数写法的 wrapper*/
public LambdaQueryWrapper<T> lambda() {return new LambdaQueryWrapper<>(getEntity(), getEntityClass(), sqlSelect, paramNameSeq, paramNameValuePairs,expression, lastSql, sqlComment, sqlFirst);
}
4、UpdateWrapper
1、AbstractWrapper 的实现类之一:UpdateWrapper
UpdateWrapper
继承自 AbstractWrapper
,自身的内部属性 entity
也用于生成 where 条件
及 LambdaUpdateWrapper
, 可以通过 new UpdateWrapper().lambda()
方法获取
UpdateWrapper
使用的是数据库字段,不是 Java属性!
/*** Update 条件封装** @author hubin miemie HCL* @since 2018-05-30*/
@SuppressWarnings("serial")
public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T>>implements Update<UpdateWrapper<T>, String> {/*** SQL 更新字段内容,例如:name='1', age=2*/private final List<String> sqlSet;public UpdateWrapper() {// 如果无参构造函数,请注意实体 NULL 情况 SET 必须有否则 SQL 异常this(null);}public UpdateWrapper(T entity) {super.setEntity(entity);super.initNeed();this.sqlSet = new ArrayList<>();}
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 = '老李头'")
2、AbstractWrapper 的实现类之一:LambdaUpdateWrapper
在UpdateWrapper
中可以获取到LambdaUpdateWrapper
对象,LambdaUpdateWrapper
支持使用类名 : getXxx()
的方式构造 SQL 语句
/*** 返回一个支持 lambda 函数写法的 wrapper*/
public LambdaUpdateWrapper<T> lambda() {return new LambdaUpdateWrapper<>(getEntity(), getEntityClass(), sqlSet, paramNameSeq, paramNameValuePairs,expression, lastSql, sqlComment, sqlFirst);
}
5、Wrapper 原理分析
为什么支持链式调用?
Wrapper 条件构造器支持链式调用,比如:lambdaQuery().eq(Entity::getId, value).one();
、update().eq("id", value).remove();
这样的形式
在 AbstractWrapper
类中定义的条件构造方法,返回值都会 Children
类型。Children
为 AbstractWrapper
类的泛型:Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
哟,搁这儿套娃呢?不过我们知道 Children
继承了 AbstractWrapper
抽象类就行,因此调用条件构造方法返回的仍然是 AbstractWrapper
类型的对象,这就是解释了为什么 AbstractWrapper
支持链式调用
/*** 查询条件封装** @author hubin miemie HCL* @since 2017-05-26*/
@SuppressWarnings({"serial", "unchecked"})
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {@Overridepublic Children eq(boolean condition, R column, Object val) {return addCondition(condition, column, EQ, val);}@Overridepublic Children ne(boolean condition, R column, Object val) {return addCondition(condition, column, NE, val);}@Overridepublic Children gt(boolean condition, R column, Object val) {return addCondition(condition, column, GT, val);}@Overridepublic Children ge(boolean condition, R column, Object val) {return addCondition(condition, column, GE, val);}@Overridepublic Children lt(boolean condition, R column, Object val) {return addCondition(condition, column, LT, val);}@Overridepublic Children le(boolean condition, R column, Object val) {return addCondition(condition, column, LE, val);}@Overridepublic Children like(boolean condition, R column, Object val) {return likeValue(condition, LIKE, column, val, SqlLike.DEFAULT);}@Overridepublic Children notLike(boolean condition, R column, Object val) {return likeValue(condition, NOT_LIKE, column, val, SqlLike.DEFAULT);}
举个栗子:QueryWrapper
继承了 AbstractWrapper
抽象父类,其 Children
泛型为 QueryWrapper<T>
,因此调用 QueryWrapper
的条件构造方法返回的是 QueryWrapper
对象,那肯定也能再继续调用条件构造方法啦~~~
/*** Entity 对象封装操作类** @author hubin miemie HCL* @since 2018-05-25*/
@SuppressWarnings("serial")
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>implements Query<QueryWrapper<T>, T, String> {
为什么 LambdaQueryWrapper 可以传入类的 getter 方法?
LambdaQueryWrapper
的父类为 AbstractLambdaWrapper
,在 AbstractLambdaWrapper
父类中定义了 columnsToString()
方法:用于将 getter 方法对应的字段名转换为数据库列名
columnsToString()
方法最终会调用 getColumn()
方法:通过 String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
将 lambda 表达式转换为字段名
/*** Lambda 语法使用 Wrapper* <p>统一处理解析 lambda 获取 column</p>** @author hubin miemie HCL* @since 2017-05-26*/
@SuppressWarnings("serial")
public abstract class AbstractLambdaWrapper<T, Children extends AbstractLambdaWrapper<T, Children>>extends AbstractWrapper<T, SFunction<T, ?>, Children> {private Map<String, ColumnCache> columnMap = null;private boolean initColumnMap = false;@SuppressWarnings("unchecked")@Overrideprotected String columnsToString(SFunction<T, ?>... columns) {return columnsToString(true, columns);}@SuppressWarnings("unchecked")protected String columnsToString(boolean onlyColumn, SFunction<T, ?>... columns) {return Arrays.stream(columns).map(i -> columnToString(i, onlyColumn)).collect(joining(StringPool.COMMA));}@Overrideprotected String columnToString(SFunction<T, ?> column) {return columnToString(column, true);}protected String columnToString(SFunction<T, ?> column, boolean onlyColumn) {return getColumn(LambdaUtils.resolve(column), onlyColumn);}/*** 获取 SerializedLambda 对应的列信息,从 lambda 表达式中推测实体类* <p>* 如果获取不到列信息,那么本次条件组装将会失败** @param lambda lambda 表达式* @param onlyColumn 如果是,结果: "name", 如果否: "name" as "name"* @return 列* @throws com.baomidou.mybatisplus.core.exceptions.MybatisPlusException 获取不到列信息时抛出异常* @see SerializedLambda#getImplClass()* @see SerializedLambda#getImplMethodName()*/private String getColumn(SerializedLambda lambda, boolean onlyColumn) {Class<?> aClass = lambda.getInstantiatedType();tryInitCache(aClass);String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());ColumnCache columnCache = getColumnCache(fieldName, aClass);return onlyColumn ? columnCache.getColumn() : columnCache.getColumnSelect();}private void tryInitCache(Class<?> lambdaClass) {if (!initColumnMap) {final Class<T> entityClass = getEntityClass();if (entityClass != null) {lambdaClass = entityClass;}columnMap = LambdaUtils.getColumnMap(lambdaClass);initColumnMap = true;}Assert.notNull(columnMap, "can not find lambda cache for this entity [%s]", lambdaClass.getName());}private ColumnCache getColumnCache(String fieldName, Class<?> lambdaClass) {ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName));Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]",fieldName, lambdaClass.getName());return columnCache;}
}
6、获取 Wrapper 对象
Wrappers 类:获取各种 Wrapper 对象
public static <T> QueryWrapper<T> query() {
:获取QueryWrapper
对象public static <T> LambdaQueryWrapper<T> lambdaQuery() {
:获取LambdaQueryWrapper
对象public static <T> UpdateWrapper<T> update() {
:获取UpdateWrapper
对象public static <T> LambdaUpdateWrapper<T> lambdaUpdate() {
:获取LambdaUpdateWrapper
对象public static <T> QueryWrapper<T> emptyWrapper() {
:获取EmptyWrapper
对象
/*** Wrapper 条件构造** @author Caratacus*/
public final class Wrappers {/*** 空的 EmptyWrapper*/private static final QueryWrapper<?> emptyWrapper = new EmptyWrapper<>();private Wrappers() {// ignore}/*** 获取 QueryWrapper<T>** @param <T> 实体类泛型* @return QueryWrapper<T>*/public static <T> QueryWrapper<T> query() {return new QueryWrapper<>();}/*** 获取 QueryWrapper<T>** @param entity 实体类* @param <T> 实体类泛型* @return QueryWrapper<T>*/public static <T> QueryWrapper<T> query(T entity) {return new QueryWrapper<>(entity);}/*** 获取 LambdaQueryWrapper<T>** @param <T> 实体类泛型* @return LambdaQueryWrapper<T>*/public static <T> LambdaQueryWrapper<T> lambdaQuery() {return new LambdaQueryWrapper<>();}/*** 获取 LambdaQueryWrapper<T>** @param entity 实体类* @param <T> 实体类泛型* @return LambdaQueryWrapper<T>*/public static <T> LambdaQueryWrapper<T> lambdaQuery(T entity) {return new LambdaQueryWrapper<>(entity);}/*** 获取 LambdaQueryWrapper<T>** @param entityClass 实体类class* @param <T> 实体类泛型* @return LambdaQueryWrapper<T>* @since 3.3.1*/public static <T> LambdaQueryWrapper<T> lambdaQuery(Class<T> entityClass) {return new LambdaQueryWrapper<>(entityClass);}/*** 获取 UpdateWrapper<T>** @param <T> 实体类泛型* @return UpdateWrapper<T>*/public static <T> UpdateWrapper<T> update() {return new UpdateWrapper<>();}/*** 获取 UpdateWrapper<T>** @param entity 实体类* @param <T> 实体类泛型* @return UpdateWrapper<T>*/public static <T> UpdateWrapper<T> update(T entity) {return new UpdateWrapper<>(entity);}/*** 获取 LambdaUpdateWrapper<T>** @param <T> 实体类泛型* @return LambdaUpdateWrapper<T>*/public static <T> LambdaUpdateWrapper<T> lambdaUpdate() {return new LambdaUpdateWrapper<>();}/*** 获取 LambdaUpdateWrapper<T>** @param entity 实体类* @param <T> 实体类泛型* @return LambdaUpdateWrapper<T>*/public static <T> LambdaUpdateWrapper<T> lambdaUpdate(T entity) {return new LambdaUpdateWrapper<>(entity);}/*** 获取 LambdaUpdateWrapper<T>** @param entityClass 实体类class* @param <T> 实体类泛型* @return LambdaUpdateWrapper<T>* @since 3.3.1*/public static <T> LambdaUpdateWrapper<T> lambdaUpdate(Class<T> entityClass) {return new LambdaUpdateWrapper<>(entityClass);}/*** 获取 EmptyWrapper<T>** @param <T> 任意泛型* @return EmptyWrapper<T>* @see EmptyWrapper*/@SuppressWarnings("unchecked")public static <T> QueryWrapper<T> emptyWrapper() {return (QueryWrapper<T>) emptyWrapper;}
第 4 章 MybatisPlus 条件构造器相关推荐
- MyBatisPlus条件构造器中last方法怎样使用
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
- Mybatis-Plus条件构造器学习and方法
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Mybatis-Plus条件构造器学习and方法 一.代码 1.Controller 2.Service 3.效果 一.代码 1.Co ...
- Mybatis-Plus 条件构造器Wrapper常用方法
Mybatis-Plus 条件构造器Wrapper常用方法 下面拼接的也就是sql语句里面where后面的: 1.eq 匹配与键值相等的数据 eq(键,值) 2.ne 匹配与键值不相等的数据 ne(键 ...
- MyBatisPlus条件构造器Condition的用法
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
- MyBatisPlus条件构造器带条件排序方法orderBy、orderByDesc、orderByAsc使用
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
- MyBatisPlus条件构造器实现降序排序的两种方式
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
- MyBatisPlus条件构造器排序方法orderByDesc参数怎样构造
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
- MyBatisPlus条件构造器带条件删除delete使用
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
- MyBatisPlus条件构造器带条件更新update使用
场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...
最新文章
- 20155328 《信息安全系统设计基础》第六周 课堂提交补充
- jQuery对象与DOM对象的区别
- kali linux子远程桌面,适用于kali linux的远程桌面开启方法(从windows xp 远程登录到kali linux )...
- NFS配置及开机自动挂载
- centos-rpm
- 深度学习打造精准推荐系统,细说国美互联网 AI 发展的进击之路
- TCP 实战抓包分析
- Office安装找不到Office.zh-cn\***文件以及安装后无法正常显示图标
- delphi微信授权登陆
- Generative Adversarial Nets[AAE]
- Yuuki and a problem (树套树)
- 计算机网络 中 网络层
- python——Matplotlib饼图、直方图的绘制
- [简化] [排除] [推理]
- Django案例:显示图书的信息books
- 你知道如何使用Java将DWG / DXF CAD文件转换为图像格式吗?
- 【论文精读】Pairwise learning for medical image segmentation
- python中的pass是什么意思_Python中pass的作用与使用教程
- Eric靶机渗透测试通关全教程
- MySQL 数据库 User表权限以及用户授权详解
热门文章
- 中国加热织物市场趋势报告、技术动态创新及市场预测
- matlab中if语句中的结果返回,matlab中if 语句后面的判别式不能是算术表达式?或者说变量?...
- linux查看串口端口,规范模式Linux串行端口
- 前端开发者必备google插件
- 写好规范 Java 代码去大厂!
- AR 圈最大收购案 Ubimax 10 亿“卖身”背后:究竟什么才是真正值钱的东西?
- 教会别人编程,你能收获什么?
- Python 数据分析实战:经典的同期群分析
- 2019,燃烧的中国开源年
- 近十年数据库流行趋势纵览!存储计算分离、ACID 全面回归......