第 4 章 MybatisPlus 条件构造器

1、CRUD API 的思考

对于 BaseMapper 中基本 CRUD 方法的思考

继承了 BaseMapper 接口后,我们只能获得基本的 CRUD 能力,那么对于复杂的 SQL 查询,MybatisPlus 貌似也无能为力,但其实并不是这样的

现有一个需求,我们需要分页查询 t_user 表中,年龄在 18~50 之间性别为男且姓名为 xx的所有用户,这时候我们该如何实现上述需求呢?

MyBatis:需要在 SQL映射文件中编写带条件查询的 SQL,并基于 PageHelper插件完成
分页 . 实现以上一个简单的需求,往往需要我们做很多重复单调的工作。

MP:依旧不用编写 SQL语句,MP提供了功能强大的条件构造器 QueryMapperLambdaQueryWrapper

2、AbstractWrapper

条件构造器的抽象父类:AbstractWrapper

AbstractWrapperQueryWrapper(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则在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 = '老王'

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 类型。ChildrenAbstractWrapper 类的泛型: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 对象

  1. public static <T> QueryWrapper<T> query() {:获取 QueryWrapper 对象
  2. public static <T> LambdaQueryWrapper<T> lambdaQuery() {:获取 LambdaQueryWrapper 对象
  3. public static <T> UpdateWrapper<T> update() {:获取 UpdateWrapper 对象
  4. public static <T> LambdaUpdateWrapper<T> lambdaUpdate() {:获取 LambdaUpdateWrapper 对象
  5. 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&lt;T&gt;** @param <T> 实体类泛型* @return QueryWrapper&lt;T&gt;*/public static <T> QueryWrapper<T> query() {return new QueryWrapper<>();}/*** 获取 QueryWrapper&lt;T&gt;** @param entity 实体类* @param <T>    实体类泛型* @return QueryWrapper&lt;T&gt;*/public static <T> QueryWrapper<T> query(T entity) {return new QueryWrapper<>(entity);}/*** 获取 LambdaQueryWrapper&lt;T&gt;** @param <T> 实体类泛型* @return LambdaQueryWrapper&lt;T&gt;*/public static <T> LambdaQueryWrapper<T> lambdaQuery() {return new LambdaQueryWrapper<>();}/*** 获取 LambdaQueryWrapper&lt;T&gt;** @param entity 实体类* @param <T>    实体类泛型* @return LambdaQueryWrapper&lt;T&gt;*/public static <T> LambdaQueryWrapper<T> lambdaQuery(T entity) {return new LambdaQueryWrapper<>(entity);}/*** 获取 LambdaQueryWrapper&lt;T&gt;** @param entityClass 实体类class* @param <T>         实体类泛型* @return LambdaQueryWrapper&lt;T&gt;* @since 3.3.1*/public static <T> LambdaQueryWrapper<T> lambdaQuery(Class<T> entityClass) {return new LambdaQueryWrapper<>(entityClass);}/*** 获取 UpdateWrapper&lt;T&gt;** @param <T> 实体类泛型* @return UpdateWrapper&lt;T&gt;*/public static <T> UpdateWrapper<T> update() {return new UpdateWrapper<>();}/*** 获取 UpdateWrapper&lt;T&gt;** @param entity 实体类* @param <T>    实体类泛型* @return UpdateWrapper&lt;T&gt;*/public static <T> UpdateWrapper<T> update(T entity) {return new UpdateWrapper<>(entity);}/*** 获取 LambdaUpdateWrapper&lt;T&gt;** @param <T> 实体类泛型* @return LambdaUpdateWrapper&lt;T&gt;*/public static <T> LambdaUpdateWrapper<T> lambdaUpdate() {return new LambdaUpdateWrapper<>();}/*** 获取 LambdaUpdateWrapper&lt;T&gt;** @param entity 实体类* @param <T>    实体类泛型* @return LambdaUpdateWrapper&lt;T&gt;*/public static <T> LambdaUpdateWrapper<T> lambdaUpdate(T entity) {return new LambdaUpdateWrapper<>(entity);}/*** 获取 LambdaUpdateWrapper&lt;T&gt;** @param entityClass 实体类class* @param <T>         实体类泛型* @return LambdaUpdateWrapper&lt;T&gt;* @since 3.3.1*/public static <T> LambdaUpdateWrapper<T> lambdaUpdate(Class<T> entityClass) {return new LambdaUpdateWrapper<>(entityClass);}/*** 获取 EmptyWrapper&lt;T&gt;** @param <T> 任意泛型* @return EmptyWrapper&lt;T&gt;* @see EmptyWrapper*/@SuppressWarnings("unchecked")public static <T> QueryWrapper<T> emptyWrapper() {return (QueryWrapper<T>) emptyWrapper;}

第 4 章 MybatisPlus 条件构造器相关推荐

  1. MyBatisPlus条件构造器中last方法怎样使用

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

  2. Mybatis-Plus条件构造器学习and方法

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 Mybatis-Plus条件构造器学习and方法 一.代码 1.Controller 2.Service 3.效果 一.代码 1.Co ...

  3. Mybatis-Plus 条件构造器Wrapper常用方法

    Mybatis-Plus 条件构造器Wrapper常用方法 下面拼接的也就是sql语句里面where后面的: 1.eq 匹配与键值相等的数据 eq(键,值) 2.ne 匹配与键值不相等的数据 ne(键 ...

  4. MyBatisPlus条件构造器Condition的用法

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

  5. MyBatisPlus条件构造器带条件排序方法orderBy、orderByDesc、orderByAsc使用

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

  6. MyBatisPlus条件构造器实现降序排序的两种方式

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

  7. MyBatisPlus条件构造器排序方法orderByDesc参数怎样构造

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

  8. MyBatisPlus条件构造器带条件删除delete使用

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

  9. MyBatisPlus条件构造器带条件更新update使用

    场景 项目搭建专栏: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/column/info/37194 基础搭建: https://blog.csdn.net/B ...

最新文章

  1. 20155328 《信息安全系统设计基础》第六周 课堂提交补充
  2. jQuery对象与DOM对象的区别
  3. kali linux子远程桌面,适用于kali linux的远程桌面开启方法(从windows xp 远程登录到kali linux )...
  4. NFS配置及开机自动挂载
  5. centos-rpm
  6. 深度学习打造精准推荐系统,细说国美互联网 AI 发展的进击之路
  7. TCP 实战抓包分析
  8. Office安装找不到Office.zh-cn\***文件以及安装后无法正常显示图标
  9. delphi微信授权登陆
  10. Generative Adversarial Nets[AAE]
  11. Yuuki and a problem (树套树)
  12. 计算机网络 中 网络层
  13. python——Matplotlib饼图、直方图的绘制
  14. [简化] [排除] [推理]
  15. Django案例:显示图书的信息books
  16. 你知道如何使用Java将DWG / DXF CAD文件转换为图像格式吗?
  17. 【论文精读】Pairwise learning for medical image segmentation
  18. python中的pass是什么意思_Python中pass的作用与使用教程
  19. Eric靶机渗透测试通关全教程
  20. MySQL 数据库 User表权限以及用户授权详解

热门文章

  1. 中国加热织物市场趋势报告、技术动态创新及市场预测
  2. matlab中if语句中的结果返回,matlab中if 语句后面的判别式不能是算术表达式?或者说变量?...
  3. linux查看串口端口,规范模式Linux串行端口
  4. 前端开发者必备google插件
  5. 写好规范 Java 代码去大厂!
  6. AR 圈最大收购案 Ubimax 10 亿“卖身”背后:究竟什么才是真正值钱的东西?
  7. 教会别人编程,你能收获什么?
  8. Python 数据分析实战:经典的同期群分析
  9. 2019,燃烧的中国开源年
  10. 近十年数据库流行趋势纵览!存储计算分离、ACID 全面回归......