数据权限的设计与实现系列11——前端筛选器组件Everright-filter集成功能完善2

筛选条件数据类型完善

文本类

筛选器组件给了一个文本类操作的范例,如下:

            Text: [{label: '等于',en_label: 'Equal',style: 'noop'},{label: '等于其中之一',en_label: 'Equal to one of',value: 'one_of',style: 'tags'},{label: '不等于',en_label: 'Not equal',value: 'not_equal',style: 'noop'},{label: '包含',en_label: 'Contains',value: 'contains',style: 'noop'},{label: '不包含',en_label: 'Not contain',value: 'not_contain',style: 'noop'},{label: '为空',en_label: 'Empty',value: 'empty',style: 'none'},{label: '不为空',en_label: 'Not empty',value: 'not_empty',style: 'none'}]

即以下几种情况:

  • 等于
  • 等于其中之一
  • 不等于
  • 包含
  • 不包含
  • 为空
  • 不为空

平台认为不是太合理,做了以下调整:

  1. 等于其中之一很少用,并且可以等价转换一个条件组,内含多个等于关系的条件,组内逻辑关系为或,因此去除
  2. 对于字符串,常用的主要是模糊匹配、以……开始、以……结束,因此将包含调整为模糊匹配、去除不包含,增加以……开始、以……结束两种,其他保留不变,同时对操作符的编码也做了相应调整。

调整完成后如下:

              Text: [{label: '等于',value: 'EQ',style: 'noop'},{label: '模糊匹配',value: 'LK',style: 'noop'},{label: '以…开始',value: 'RL',style: 'noop'},{label: '以…结束',value: 'LL',style: 'noop'},{label: '不等于',value: 'NE',style: 'noop'},{label: '为空',value: 'NL',style: 'none'},{label: '不为空',value: 'NN',style: 'none'}]

后端将规则转换成SQL片段的功能方法也要进行相应调整,这里参考了平台原本的通用查询功能的部分处理,改造如下:

@Overridepublic String generateSqlPart(String id, String rule) {String result = "";// 转换数据DataFilterRuleVO dataFilterRule = JSON.parseObject(rule, DataFilterRuleVO.class);// 获取组集合List<DataFilterGroupVO> dataFilterGroupList = dataFilterRule.getFilters();// 存放各组对应的条件sql片段List<String> groupSqlPartList = new ArrayList<>(dataFilterGroupList.size());// 遍历组集合for (DataFilterGroupVO dataFilterGroup : dataFilterGroupList) {// 获取条件集合List<DataFilterConditionVO> conditionList = dataFilterGroup.getConditions();if (CollectionUtils.isNotEmpty(conditionList)) {// 存放各条件对应的条件sql片段List<String> conditionSqlPartList = new ArrayList<>(conditionList.size());// 遍历条件集合for (DataFilterConditionVO condition : conditionList) {// 获取字段名,命名风格驼峰转换成下划线String fieldName = CommonUtil.camelToUnderline(condition.getProperty());Object value = condition.getValue();// 获取操作String operator = condition.getOperator();QueryRuleEnum queryRule = EnumUtils.getEnum(QueryRuleEnum.class, operator, QueryRuleEnum.EQ);QueryWrapper<?> queryWrapper = new QueryWrapper<>();addEasyQuery(queryWrapper, fieldName, queryRule, value);log.info(queryWrapper.getSqlSegment());log.info(queryWrapper.getParamNameValuePairs().toString());// 放入结果列表缓存                 conditionSqlPartList.add(queryWrapper.getTargetSql());}// 完成各条件的处理后,进行组内拼接if (conditionList.size() > 1) {String logicalOperator = dataFilterGroup.getLogicalOperator();StringBuffer sb = new StringBuffer();sb.append("(");conditionSqlPartList.stream().forEach(sqlPart -> {sb.append(sqlPart);sb.append(" " + logicalOperator + " ");});sb.delete(sb.length() - logicalOperator.length() - 1, sb.length());sb.append(")");groupSqlPartList.add(sb.toString());} else {groupSqlPartList.add("(" + conditionSqlPartList.get(0) + ")");}}}

这里调用了一个方法,addEasyQuery,借助了MybatisPlus组件的条件构造器功能,如下:

/*** 根据规则走不同的查询** @param queryWrapper QueryWrapper* @param name         字段名字* @param rule         查询规则* @param value        查询条件值*/private void addEasyQuery(QueryWrapper<?> queryWrapper, String name, QueryRuleEnum rule, Object value) {if (value == null || rule == null || ObjectUtils.isEmpty(value)) {return;}name = CommonUtil.camelToUnderline(name);switch (rule) {case GT:queryWrapper.gt(name, value);break;case GE:queryWrapper.ge(name, value);break;case LT:queryWrapper.lt(name, value);break;case LE:queryWrapper.le(name, value);break;case EQ:queryWrapper.eq(name, value);break;case NE:queryWrapper.ne(name, value);break;case IN:if (value instanceof String) {queryWrapper.in(name, (Object[]) value.toString().split(COMMA));} else if (value instanceof String[]) {queryWrapper.in(name, (Object[]) value);} else {queryWrapper.in(name, value);}break;case LK:queryWrapper.like(name, value);break;case LL:queryWrapper.likeLeft(name, value);break;case RL:queryWrapper.likeRight(name, value);break;default:log.info("--查询规则未匹配到---");break;}}

如何获取完整SQL片段

此处遇到了一个棘手的问题。
我们需要获取到完整的SQL片段,类似这种:((param_value = ‘10’ and param_name like ‘%用户%’ ) or (param_key like ‘%password%’) )。
但是MybatisPlus组件的条件构造器QueryWrapper拿不到这种完整的sql片段,而是将sql语句参数和值分开保存的,通过getSqlSegment可以获取到参数化的sql语句,通过getParamNameValuePairs可以获取到参数值,如下:

查了半天资料,也没找到现成的方法可用,将这二者处理成我们期望的完整SQL片段。
于是有两种方案可选,一种是放弃借助QueryWrapper,自己来拼接SQL语句;一种是仍然使用QueryWrapper,自己来实现转换功能。
综合考虑了下,后一种的扩展性更好一些,只是写个单条件的字符串替换处理,复杂度不高,需要注意区分数值类和非数值类类型,相应的处理时要不要加单引号。

转换方法行不复杂,如下:

 /*** 将参数化的SQL填充值处理为完整的SQL片段** @param sqlSegment          参数化的SQL片段* @param paramNameValuePairs 参数值对* @param numberFlag          是否为数值类型* @return 完整的SQL片段*/private String handleSqlPart(String sqlSegment, Map<String, Object> paramNameValuePairs, boolean numberFlag) {for (int i = 0; i < paramNameValuePairs.size(); i++) {String value = paramNameValuePairs.get("MPGENVAL" + (i + 1)).toString();// 若为非数值类,则加上单引号if (!numberFlag) {value = "'" + value + "'";}sqlSegment = StringUtils.replace(sqlSegment, "#{ew.paramNameValuePairs.MPGENVAL" + (i + 1) + "}", value);}return sqlSegment;}

是否为数值类型,则是通过实体模型配置,获取当前模型属性的数据类型来判断的,如下:

 @Overridepublic String generateSqlPart(String id, String rule) {String result = "";List<EntityModelProperty> modelPropertyList = entityModelPropertyService.getFullPropertyByEntityModelId(id);String[] numberDataType = {"INTEGER", "LONG", "DOUBLE", "DECIMAL"};// 转换数据DataFilterRuleVO dataFilterRule = JSON.parseObject(rule, DataFilterRuleVO.class);// 获取组集合List<DataFilterGroupVO> dataFilterGroupList = dataFilterRule.getFilters();// 存放各组对应的条件sql片段List<String> groupSqlPartList = new ArrayList<>(dataFilterGroupList.size());// 遍历组集合for (DataFilterGroupVO dataFilterGroup : dataFilterGroupList) {// 获取条件集合List<DataFilterConditionVO> conditionList = dataFilterGroup.getConditions();if (CollectionUtils.isNotEmpty(conditionList)) {// 存放各条件对应的条件sql片段List<String> conditionSqlPartList = new ArrayList<>(conditionList.size());// 遍历条件集合for (DataFilterConditionVO condition : conditionList) {// 获取字段名,命名风格驼峰转换成下划线String fieldName = CommonUtil.camelToUnderline(condition.getProperty());Object value = condition.getValue();// 获取操作String operator = condition.getOperator();QueryRuleEnum queryRule = EnumUtils.getEnum(QueryRuleEnum.class, operator, QueryRuleEnum.EQ);QueryWrapper<?> queryWrapper = new QueryWrapper<>();addEasyQuery(queryWrapper, fieldName, queryRule, value);log.info(queryWrapper.getSqlSegment());log.info(queryWrapper.getParamNameValuePairs().toString());AtomicBoolean numberFlag = new AtomicBoolean(false);modelPropertyList.stream().filter(modelProperty -> modelProperty.getCode().equals(condition.getProperty())).findFirst().ifPresent(modelProperty -> {String dataType = modelProperty.getDataType();if (ArrayUtils.contains(numberDataType, dataType)) {numberFlag.set(true);}});String sqlPart = handleSqlPart(queryWrapper.getSqlSegment(), queryWrapper.getParamNameValuePairs(), numberFlag.get());// 放入结果列表缓存conditionSqlPartList.add(sqlPart);}// 完成各条件的处理后,进行组内拼接if (conditionList.size() > 1) {String logicalOperator = dataFilterGroup.getLogicalOperator();StringBuffer sb = new StringBuffer();sb.append("(");conditionSqlPartList.stream().forEach(sqlPart -> {sb.append(sqlPart);sb.append(" " + logicalOperator + " ");});sb.delete(sb.length() - logicalOperator.length() - 1, sb.length());sb.append(")");groupSqlPartList.add(sb.toString());} else {groupSqlPartList.add("(" + conditionSqlPartList.get(0) + ")");}}}

实现效果如下:

数值类未加单引号,非数值类附加了单引号,符合预期。

开源平台资料

平台名称:一二三开发平台
简介: 企业级通用开发平台
设计资料:[csdn专栏]
开源地址:[Gitee]
开源协议:MIT
如果您在阅读本文时获得了帮助或受到了启发,希望您能够喜欢并收藏这篇文章,为它点赞~
请在评论区与我分享您的想法和心得,一起交流学习,不断进步,遇见更加优秀的自己!

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

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

相关文章

Gin框架简易搭建(3)--Grom与数据库

写在前面 项目地址 个人认为GORM 指南这个网站是相比较之下最为清晰的框架介绍 但是它在环境搭建阶段对于初学者而言不是很友好&#xff0c;尤其是使用mysql指令稍有不同&#xff0c;以及更新的方法和依赖问题都是很让人头疼的&#xff0c;而且这些报错并非逻辑上的&#xf…

【Redis】如何在 Ubuntu 上安装 Redis 5

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 本期内容主要介绍如何在 Ubuntu 上安装 Redis5 一些碎碎念&#xff1a; 本来这期内容介绍如何在 Centos 安装 Redis …

TypeScript 设计模式之【状态模式】

文章目录 状态模式&#xff1a;优雅切换的交通信号灯状态模式的奥秘状态模式有什么利与弊?如何使用状态模式来优化你的系统代码实现案例状态模式的主要优点状态模式的主要缺点状态模式的适用场景总结 状态模式&#xff1a;优雅切换的交通信号灯 当你站在繁忙的十字路口&#…

Android AMS介绍

注&#xff1a;本文为作者学习笔记&#xff0c;如有误&#xff0c;请各位大佬指点 系统进程运行环境的初始化 Context是一个抽象类&#xff0c;它可以访问application环境的全局信息和各种资源信息和类 context功能&#xff1a; 对Activity、Service生命周期的管理通过Intent发…

Rust 语言开发 ESP32C3 并在 Wokwi 电子模拟器上运行(esp-hal 非标准库、LCD1602、I2C)

文章目录 esp-rs 简介GithubRust 包仓库Rust 教程Wokwi 电子模拟器开发环境Rust 环境esp-rs 环境创建 ESP32C3 项目项目结构编译项目命令运行模拟器ESP32C3 烧录 esp-rs 简介 esp-rs 是一个专注于为 Espressif 系列芯片&#xff08;如 ESP32、ESP32-S2、ESP32-C3 等&#xff0…

可视化图表与源代码显示配置项及页面的动态调整功能分析

可视化图表与源代码显示配置项及页面的动态调整功能分析 文章目录 可视化图表与源代码显示配置项及页面的动态调整功能分析1.分析图表源代码2.分析源代码显示功能**完整代码参考&#xff1a;** 3.分析源代码显示及动态调整**完整代码参考&#xff1a;** 4.分析代码编辑器及运行…

中国电信解锁万亿参数大模型:TeleAI的创新与突破

首个由万卡集群训练出来的万亿参数大模型&#xff0c;已被一家央企解锁。 具体而言&#xff0c;为了推动纯国产人工智能的探索&#xff0c;带来这条新路径的正是中国电信人工智能研究院&#xff08;TeleAI&#xff09;。 该研究院由中国电信集团的CTO、首席科学家兼院长李学龙…

CSS中字体图标的使用

引言&#xff1a; 在网页设计当中&#xff0c;会有很多很简洁的图标&#xff0c;比如箭头&#xff0c;照相机&#xff0c;放大镜等 这些大概率都是使用字体图标来完成的&#xff0c;因为字体图标比较简洁高效&#xff0c;不会像图片一样需要向浏览器请求数据。那么字体图标该…

使用powershell的脚本报错:因为在此系统中禁止执行脚本

1.添加powershell功能环境&#xff1a; 2.启动powershell的执行策略 因为在此系统中禁止执行脚本。 set-executionpolicy unrestricted

Redis: 主从复制读写分离环境搭建

概述 Redis 的单机模式实际上就是在一个服务器上装了一个单节点的Redis通过简单的配置和简单的命令启动起来就可以使用这种搭建环境&#xff0c;不保证高可用的情况下&#xff0c;完全没有问题如果说你的项目必须要具备高可用&#xff0c;而且 Redis 也要提供更高的性能这个单…

【hot100-java】【寻找重复数】

技巧 使用字典&#xff0c;边记录边比较&#xff0c;有直接输出。 def findDuplicate(nums):seen {}for num in nums:if num in seen:return numseen[num] Truereturn None 可惜不是O(1) 二分查找 class Solution {public int findDuplicate(int[] nums) {int left0;int ri…

宝塔搭建nextcould 30docker搭建onlyoffic8.0

宝塔搭建nextcould 宝塔搭建nextcould可以参考这两个博文 我搭建的是30版本的nextcould&#xff0c;服务组件用的是下面这些&#xff0c;步骤是一样的&#xff0c;只是版本不一样而已 nginx 1.24.0 建议选择nginx&#xff0c;apache没成功。 MySQL 8.0以上都可以 php 8.2.…

Certbot自动申请并续期https证书

Certbot自动申请并续期https证书 一、 安装 Certbot&#xff1a;使用命令安装 Certbot&#xff1a; dnf install certbot python3-certbot-nginx获取 SSL 证书&#xff1a;运行 Certbot 命令来获取并安装 SSL 证书。 示例命令&#xff0c;替换其中的域名和路径信息&#xff1a…

jmeter-请求参数加密-MD5加密

方法1 &#xff1a;使用jmeter自带的函数助手digest Tool(工具)---Function Helper Dialog(函数助手对话框) 第一个参数是要md5加密的值&#xff0c;第二个参数是保存加密后值的变量 &#xff08; 此处变量是从txt文件导入的&#xff0c;所以使用的是${wd} &#xff09; …

Linux网络操作命令与函数全面总结

1. 引言 Linux作为服务器和开发平台&#xff0c;网络操作是其核心功能之一。本文旨在全面总结Linux系统中的网络操作方法&#xff0c;包括命令行工具和编程接口&#xff0c;帮助读者深入理解Linux网络管理的机制。 2. 命令行工具 2.1 ping 命令 ping 命令用于测试网络连接和…

基于投影滤波算法的rick合成地震波滤波matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 RICK合成地震波模型 4.2 投影滤波算法原理 5.完整工程文件 1.课题概述 基于投影滤波算法的rick合成地震波滤波matlab仿真。分别通过标准的滤波投影滤波以及卷积滤波投影滤波对合成地震剖面进行滤波…

基于Hive和Hadoop的共享单车分析系统

本项目是一个基于大数据技术的共享单车分析系统&#xff0c;旨在为用户提供全面的单车使用信息和深入的出行行为分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 S…

论文阅读 | HiDDeN网络架构

ECCV 2018 斯坦福-李飞飞团队 一、问题描述 受以下启发&#xff1a; 对抗性例子的发现&#xff1a;深度学习模型在图像识别任务中对微小的、难以察觉的输入扰动非常敏感&#xff0c;这些扰动可以导致模型错误分类图像。这一现象表明&#xff0c;神经网络可以在图像中编码信息&…

Python或R时偏移算法实现

&#x1f3af;要点 计算单变量或多变量时序距离&#xff0c;使用欧几里得、曼哈顿等函数量化不同时序差异。量化生成时序之间接近度相似性矩阵。使用高尔距离和堪培拉距离等相似度测量。实现最小方差匹配算法&#xff0c;绘制步进模式的图形表示。其他语言包算法实现。 &…

IP协议讲解

IP协议 IP协议的本质&#xff1a;提供一种能力&#xff0c;将数据跨网络从A主机传输到B主机 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是4. 4位头部长度(header length): IP头部的长度是多少个32bit, 也就是 length * 4 的字节数. 4bit表示最大 的数字是15, 因…