前言

以下所有代码和观点来源均为

        <dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.0.1</version></dependency>

mybatis-plus 作为一个强大的 mybatis阵营的orm框架,很多功能已经用的飞起,但是呢在查询方面还是欠缺部分api,比如要进行如下查询时无法用到 lamdba表达式

    select min(column) as n from table

这时候是无法用自带的LambdaQueryWrapper实现的,此时就需要我们手动改造下

分析源码

核心源码其实就两个方法一个属性


// 存放sql语句
private SharedString sqlSelect = new SharedString();@SafeVarargs
@Override
public final LambdaQueryWrapper<T> select(SFunction<T, ?>... columns) {if (ArrayUtils.isNotEmpty(columns)) {this.sqlSelect.setStringValue(columnsToString(false, columns));}return typedThis;
}@Override
public String getSqlSelect() {return sqlSelect.getStringValue();
}

SharedString 这个类本质上也是一个string只是多了几个方法而已

public class SharedString implements Serializable {private static final long serialVersionUID = -1536422416594422874L;/*** 共享的 string 值*/private String stringValue;/*** SharedString 里是 ""*/public static SharedString emptyString() {return new SharedString(StringPool.EMPTY);}/*** 置 empty** @since 3.3.1*/public void toEmpty() {stringValue = StringPool.EMPTY;}/*** 置 null** @since 3.3.1*/public void toNull() {stringValue = null;}
}

所以在使用中多个字段的查询不能函数调用

改造

此时我们自己实现 LambdaQueryWrapper,然后将SharedString 改成一个由list实现的类

自定义的LambdaQueryWrapper 命名为 MyLambdaQueryWrapper

public class MyLambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, MyLambdaQueryWrapper<T>>implements Query<MyLambdaQueryWrapper<T>, T, SFunction<T, ?>> {private SelectBuilder sqlSelect = new SelectBuilder();/*** 不建议直接 new 该实例,使用 Wrappers.lambdaQuery(entity)*/public MyLambdaQueryWrapper() {this((T) null);}/*** 不建议直接 new 该实例,使用 Wrappers.lambdaQuery(entity)*/public MyLambdaQueryWrapper(T entity) {super.setEntity(entity);super.initNeed();}/*** 不建议直接 new 该实例,使用 Wrappers.lambdaQuery(entity)*/public MyLambdaQueryWrapper(Class<T> entityClass) {super.setEntityClass(entityClass);super.initNeed();}/*** 不建议直接 new 该实例,使用 Wrappers.lambdaQuery(...)*/MyLambdaQueryWrapper(T entity, Class<T> entityClass, SelectBuilder sqlSelect, AtomicInteger paramNameSeq,Map<String, Object> paramNameValuePairs, MergeSegments mergeSegments,SharedString lastSql, SharedString sqlComment, SharedString sqlFirst) {super.setEntity(entity);super.setEntityClass(entityClass);this.paramNameSeq = paramNameSeq;this.paramNameValuePairs = paramNameValuePairs;this.expression = mergeSegments;this.sqlSelect = sqlSelect;this.lastSql = lastSql;this.sqlComment = sqlComment;this.sqlFirst = sqlFirst;}/*** SELECT 部分 SQL 设置** @param columns 查询字段*/@SafeVarargs@Overridepublic final MyLambdaQueryWrapper<T> select(SFunction<T, ?>... columns) {if (ArrayUtils.isNotEmpty(columns)) {this.sqlSelect.getParts().add(columnsToString(columns));}return typedThis;}/*** 过滤查询的字段信息(主键除外!)* <p>例1: 只要 java 字段名以 "test" 开头的             -> select(i -&gt; i.getProperty().startsWith("test"))</p>* <p>例2: 只要 java 字段属性是 CharSequence 类型的     -> select(TableFieldInfo::isCharSequence)</p>* <p>例3: 只要 java 字段没有填充策略的                 -> select(i -&gt; i.getFieldFill() == FieldFill.DEFAULT)</p>* <p>例4: 要全部字段                                   -> select(i -&gt; true)</p>* <p>例5: 只要主键字段                                 -> select(i -&gt; false)</p>** @param predicate 过滤方式* @return this*/@Overridepublic MyLambdaQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate) {if (entityClass == null) {entityClass = getEntityClass();} else {setEntityClass(entityClass);}Assert.notNull(entityClass, "entityClass can not be null");this.sqlSelect.getParts().add(TableInfoHelper.getTableInfo(entityClass).chooseSelect(predicate));return typedThis;}@Overridepublic String getSqlSelect() {return sqlSelect.getStringValue();}/*** 用于生成嵌套 sql* <p>故 sqlSelect 不向下传递</p>*/@Overrideprotected MyLambdaQueryWrapper<T> instance() {return new MyLambdaQueryWrapper<>(getEntity(), getEntityClass(), null, paramNameSeq, paramNameValuePairs,new MergeSegments(), SharedString.emptyString(), SharedString.emptyString(), SharedString.emptyString());}@Overridepublic void clear() {super.clear();sqlSelect.toNull();}// =================== 上面的代码都是照抄的   =====================public MyLambdaQueryWrapper<T> min(SFunction<T, ?> column){if (column != null) {this.sqlSelect.getParts().add(String.format("min(%s)", columnToString(column)));}return typedThis;}public MyLambdaQueryWrapper<T> max(SFunction<T, ?> column){if (column != null) {this.sqlSelect.getParts().add(String.format("max(%s)", columnToString(column)));}return typedThis;}public MyLambdaQueryWrapper<T> sum(SFunction<T, ?> column){if (column != null) {this.sqlSelect.getParts().add(String.format("sum(%s)", columnToString(column)));}return typedThis;}public MyLambdaQueryWrapper<T> as(String asName){if (StringUtils.isEmpty(asName)) {return typedThis;}List<String> parts = this.sqlSelect.getParts();if (CollectionUtil.isEmpty(parts)) {return typedThis;}String lastPart = parts.remove(parts.size() - 1);lastPart += " as " + asName;parts.add(lastPart);return typedThis;}}

还有一个暂存查询列的list组装对象

@Getter
@Setter
public class SelectBuilder implements Serializable {private static final long serialVersionUID = -1536422416594422874L;private List<String> parts;public SelectBuilder() {this.parts = new ArrayList<>();}public void toEmpty() {parts.clear();}/*** 置 null** @since 3.3.1*/public void toNull() {parts = null;}public String getStringValue(){if (CollectionUtil.isNotEmpty(parts)) {return String.join(",", parts);}else {return null;}}}

使用代码

MyLambdaQueryWrapper<SignConfig> myLambdaQuery = getMyLambdaQuery();
myLambdaQuery.min(SignConfig::getLongitude).as("logg");
myLambdaQuery.sum(SignConfig::getLongitude).as("lo");return baseMapper.selectObjs(myLambdaQuery);

对应的sql

SELECT min(longitude) as logg,sum(longitude) as lo FROM work_sign_config

mybatis-plus 自定义QueryWrapper(一)实现查询函数相关推荐

  1. MyBatis——@Result注解column参数传递——父查询函数的参数传递到子查询

    问题描述 假设a方法中传入一个带查询参数x 但是a方法的查询结果中不包含参数x 而子查询里也需要参数x 如何在子查询b中带入参数x /*** 按User表中platform查询User*/@Selec ...

  2. mybatis框架中的queryWrapper的or查询,联想到MySQL中and 和or的关系

    统计的原生SQL应该是这样的: SELECTCOUNT( 1 ) FROMtable_name WHERE( id = '679135XXXXXXX1212' AND ( STATUS = 1 OR ...

  3. oracle typehandler,Mybatis实现自定义的类型转换器TypeHandler

    此文其实是java操作Oracle类型XMLType总结二:使用Mybatis附带的一篇小结. Mybatis实现自定义的转换器,十分的简单,其主要步骤分为三步,这里以操作XMLType类型为例. 第 ...

  4. 说说WordPress的主查询函数-query_posts()

    今天说说WordPress 的主查询函数 -query_posts(),因为我正在制作的主题里面多次用到了这个函数 . query_posts()查询函数决定了哪些文章出现在WordPress 主 循 ...

  5. springboot+mybatis集成自定义缓存ehcache用法笔记

    今天小编给大家整理了springboot+mybatis集成自定义缓存ehcache用法笔记,希望对大家能有所办帮助! 一.ehcache介绍 EhCache 是一个纯Java的进程内缓存管理框架,属 ...

  6. ES自定义评分机制:function_score查询详解

    一.function_score介绍 主要用于让用户自定义查询相关性得分,实现精细化控制评分的目的. 在ES的常规查询中,只有参与了匹配查询的字段才会参与记录的相关性得分score的计算.但很多时候我 ...

  7. Django学习笔记(3):使用模型类进行查询(查询函数、F对象、Q对象、聚合函数、查询集、模型类关系、关联查询、自关联、管理器)

    文章目录 1.查询函数 2.F对象 3.Q对象 4.聚合函数 5.Count函数 6.查询集 查询集的特性 对查询集进行切片 判断一个查询集中是否有数据 7.模型类之间的关系 一对多关系 多对多关系 ...

  8. mybatis generator自定义逆向工程防覆盖sql代码

    Mybatis generator 自定义逆向工程防覆盖sql 在项目中常常有数据库的变更,我们会常用到mybats generator逆向工程来为我们更新项目中的sql语句及entity实体,此时会 ...

  9. 大数据技术之_08_Hive学习_03_查询+函数

    大数据技术之_08_Hive学习_03 第6章 查询 6.1 基本查询(select ... from) 6.1.1 全表和特定列查询 6.1.2 列别名 6.1.3 算术运算符 6.1.4 常用函数 ...

  10. 使用mybatis plus自定义拦截器,实现数据权限

    需求 为了增强程序的安全性,需要在用户访问数据库的时候进行权限判断后选择性进行判断是否需要增强sql,来达到限制低级别权限用户访问数据的目的. 根据业务需要,这里将角色按照数据范围做权限限定.比如,角 ...

最新文章

  1. bzoj3467: Crash和陶陶的游戏
  2. 不知道这些AI术语,还敢说你很了解AI吗?
  3. ​基于BCI的现代神经反馈有助于认知增强
  4. 关于大型网站技术演进的思考(一)--存储的瓶颈(上)
  5. Servlet架构初解析
  6. wpf custom control
  7. linux 进程地址空间的一步步探究
  8. xxx in ‘Anonymous class derived from xxx clashes with ‘call(T)‘ in xxx attempting to use incompati
  9. SQL获取变量类型以及变量最大长度
  10. Leetcode每日一题:514.freedom-trail(自由之路)
  11. elasticsearch RestHighLevelClient 使用方法及封装工具
  12. 在运行hadoopdb\hive\hadoop源码时不能正确调用自定义core-site.xml等配置文件
  13. 线上python课程一般多少钱-python培训班一般多少钱?一篇文章告诉你
  14. linux 自学笔记
  15. 5.7 tensorflow2实现主成分分析(PCA) ——python实战(上篇)
  16. Google OKR 目标管理体系学习
  17. nmap的下载与安装
  18. 调用钉钉API发送消息通知给个人或部门 ,钉钉后台
  19. MC0108白给-MC0109新河妇荡杯
  20. 解锁ChatGPT超高级玩法,展示动态图片,纯干货分享!

热门文章

  1. oracle 自治事务异常不回滚,ORA-06519: 检测到活动的自治事务处理,已经回退
  2. oracle 设置不可重复,oracle – 不可重复读和幻读之间有什么区别?
  3. 周长相等的正方形面积一定相等_周长和面积一直是三年级孩子的易失分点,家长要把好关!...
  4. 算法:转换二叉查找树为最大值加上当前值的数Convert BST to Greater Tree
  5. 易筋SpringBoot 2.1 | 第四篇:RestTemplate方法详解(2)
  6. linux访问vdma的数据,Xilinx VDMA 24位流输出与32位AXI总线的内存流数据关系
  7. 2021-09-09321. 拼接最大数 单调栈
  8. ValueError: operands could not be broadcast together with shapes (3000,20) (20,20)
  9. DL实战(1):tensorflow在mnist上实现siamese net
  10. 编译原理完整学习笔记(二):高级程序设计语言