数据权限的设计与实现系列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'}]
即以下几种情况:
- 等于
- 等于其中之一
- 不等于
- 包含
- 不包含
- 为空
- 不为空
平台认为不是太合理,做了以下调整:
- 等于其中之一很少用,并且可以等价转换一个条件组,内含多个等于关系的条件,组内逻辑关系为或,因此去除
- 对于字符串,常用的主要是模糊匹配、以……开始、以……结束,因此将包含调整为模糊匹配、去除不包含,增加以……开始、以……结束两种,其他保留不变,同时对操作符的编码也做了相应调整。
调整完成后如下:
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
如果您在阅读本文时获得了帮助或受到了启发,希望您能够喜欢并收藏这篇文章,为它点赞~
请在评论区与我分享您的想法和心得,一起交流学习,不断进步,遇见更加优秀的自己!
相关文章:
数据权限的设计与实现系列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,v…...
C++ 游戏开发
C游戏开发 C 是一种高效、灵活且功能强大的编程语言,因其性能和控制能力而在游戏开发中被广泛应用。许多著名的游戏引擎,如 Unreal Engine、CryEngine 和 Godot 等,都依赖于 C 进行核心开发。本文将详细介绍 C 在游戏开发中的应用࿰…...
【历年CSP-S复赛第一题】暴力解法与正解合集(2019-2022)
P5657 [CSP-S2019] 格雷码P7076 [CSP-S2020] 动物园P7913 [CSP-S 2021] 廊桥分配P8817 [CSP-S 2022] 假期计划 P5657 [CSP-S2019] 格雷码 暴力50分 #include<bits/stdc.h> #define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0) #define int long long #d…...
基于PyQt5和SQLite的数据库操作程序
基于PyQt5和SQLite的数据库操作程序:功能解析 在现代办公和数据处理中,数据库操作是不可或缺的一部分。然而,传统的数据库管理工具往往界面复杂,操作繁琐,对于非专业人士来说存在一定的学习曲线。为了解决这个问题,我们开发了一款基于PyQt5和SQLite的数据库操作程序。该…...
在Ubuntu 20.04中安装CARLA
0. 引言 CARLA (Car Learning to Act) 是一款开源自动驾驶模拟器,其支持自动驾驶系统全管线的开发、训练和验证(Development, Training, and Validation of autonomous driving systems)。Carla提供了丰富的数字资产,例如城市布局…...
【高中数学/对数/导数】曲线y=ln|x|过坐标原点的两切线方程为?
【问题】 曲线yln|x|过坐标原点的两切线方程为?(高考真题) 【出处】 《高考数学 函数与导数题型解题研究》P5第8题 中原教研工作室编著 【解答】 yln|x|的图线分两部分,y轴左边的部分是ylnx的镜像 所以知ylnx上切线过原点的…...
Qt CMake
使用 CMake 构建 CMake 是一款用于简化跨不同平台开发项目的构建流程的工具。 CMake 可自动生成构建系统,如 Makefile 和 Visual Studio 项目文件。 CMake 是一个第三方工具,有自己的文档。 本主题介绍如何在 Qt 5 中使用 CMake 3.1.0。 开始使用 CMak…...
制造企业各部门如何参与生产成本控制与管理?
国内制造业的分量可不轻,从日常生活用品到高端工业设备,中国制造几乎涵盖了各个领域。 不过很多制造业企业在管理方面确实存在一些难题:成本控制不容易,产品质量并不稳定,生产周期也常常较长。 一、中国制造业生产管…...
FireRedTTS - 小红书最新开源AI语音克隆合成系统 免训练一键音频克隆 本地一键整合包下载
小红书技术团队FireRed最近推出了一款名为FireRedTTS的先进语音合成系统,该系统能够基于少量参考音频快速模仿任意音色和说话风格,实现独特的音频内容创造。 FireRedTTS 只需要给定文本和几秒钟参考音频,无需训练,就可模仿任意音色…...
活体检测标签之2.4G有源RFID--SI24R2F+
首先从客户对食品安全和可追溯性的关注切入,引出活体标签这个解决方案。接着分别阐述活体标签在动物养殖和植物产品方面的应用,强调其像 “身份证” 一样记录重要信息,让客户能够了解食品的来源和成长历程,从而放心食用。最后呼吁…...
Web3Auth 如何工作?
Web3Auth 用作钱包基础设施,为去中心化应用程序 (dApp) 和区块链钱包提供增强的灵活性和安全性。在本文档中,我们将探索 Web3Auth 的功能,展示它如何为每个用户和应用程序生成唯一的加密密钥提供程序。 高级架构 Web3Auth SDK 完全存在于用…...
问:SQL中join语法的差异?
在SQL中,JOIN语法用于结合来自两个或多个表的数据。不同类型的JOIN会基于不同的条件来合并表中的数据。以下是几种常见的JOIN及其差异: 假设我们有两个表:employees 和 departments。 employees 表: employee_idnamedepartment_id1Alice10…...
计算机网络各层有哪些协议?计算机网络协议解析:从拟定到实现,全面了解各层协议的作用与区别
在数字化时代,计算机网络无处不在,已经成为不可或缺的一部分。为了让不同设备能够有效地进行通信,网络协议作为一种约定和规则,确保了数据在网络中的可靠传输。今天,我们将深入探讨计算机网络的各层协议,详…...
解决方案:机器学习中,基学习器 跟 弱学习器,有什么区别
文章目录 一、现象二、解决方案 一、现象 在工作中,在机器学习中,有时候会看到基学习器 跟 弱学习器,会容易混淆,所以整理一下 二、解决方案 在机器学习中,“基学习器”(Base Learner)和“弱…...
【Python】ftfy 使用指南:修复 Unicode 编码问题
ftfy(fixes text for you)是一个专为修复各种文本编码错误而设计的 Python 工具。它的主要目标是将损坏的 Unicode 文本恢复为正确的 Unicode 格式。ftfy 并非用于处理非 Unicode 编码,而是旨在修复因为编码不一致、解码错误或混合编码导致的…...
第9课-C++String功能的探索
1:C 语言中的字符串 vs C string 类 1.1 C 语言中的字符串 在 C 语言中,字符串本质上是以 \0 结尾的字符数组。C 标准库为此提供了 str 系列函数,如 strlen()、strcpy() 和 strcat() 等。虽然这些函数可以操作字符串,但它们的操…...
基于Hive和Hadoop的保险分析系统
本项目是一个基于大数据技术的保险分析系统,旨在为用户提供全面的汽车保险信息和深入的保险价格分析。系统采用 Hadoop 平台进行大规模数据存储和处理,利用 MapReduce 进行数据分析和处理,通过 Sqoop 实现数据的导入导出,以 Spark…...
国庆节快乐前端(HTML+CSS+JavaScript+BootStrap.min.css)
一、效果展示 二、制作缘由 最近,到了国庆节,自己呆在学校当守校人,太无聊了,顺便做一个小demo帮祖国目前庆生!!! 三、项目目录结构 四、准备工作 (1)新建好对应的文件目录 为了方便ÿ…...
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化
【重学 MySQL】四十九、阿里 MySQL 命名规范及 MySQL8 DDL 的原子化 阿里 MySQL 命名规范MySQL8 DDL的原子化 阿里 MySQL 命名规范 【强制】表名、字段名必须使用小写字母或数字,禁止出现数字开头,禁止两个下划线中间只出现数字。数据库字段名的修改代价…...
PyTorch源码系列(一)——Optimizer源码详解
目录 1. Optimizer类2. Optimizer概览3. 源码解析3.1 构造方法3.1.1 全局设置情形3.1.2 局部设置情形3.1.3 覆盖测试3.1.4 逐行讲解 3.2 add_param_group3.3 step3.4 zero_grad3.5 self.state3.6 state_dict3.7 load_state_dict 4. SGD Optimizer5. 极简版Optimizer源码6. 自定…...
Java - LeetCode面试经典150题(三)
区间 228. 汇总区间 题目 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某个范围但不属于 nums 的数字 x 。 列表中…...
基于SpringBoot+Vue+MySQL的民宿预订平台
系统展示 用户前台界面 管理员后台界面 商家后台界面 系统背景 随着旅游业的蓬勃发展,民宿作为一种独特的住宿方式,受到了越来越多游客的青睐。然而,传统的民宿预定方式往往存在信息不对称、效率低下等问题,难以满足游客的个性化需…...
Hadoop krb5.conf 配置详解
krb5.conf文件是Kerberos认证系统中的一个关键配置文件,它包含了Kerberos的配置信息,如KDC(Key Distribution Centers)和Kerberos相关域的管理员服务器位置、当前域和Kerberos应用的默认设置、以及主机名与Kerberos域的映射等。以…...
工程师 - DNS请求过程
DNS(Domain Name System,域名系统)是互联网的重要基础设施之一,其主要功能是将人们容易记忆的域名(例如 www.example.com)转换为计算机能识别的IP地址(例如 192.0.2.1),类…...
Solidity智能合约中的事件和日志
1. Solidity 中的事件和日志概述 1.1 什么是事件? 在 Solidity 中,事件(Event)是一种允许智能合约与外部世界进行通信的机制。通过触发事件,可以记录合约执行中的关键操作,并将这些操作发送到链上。事件的…...
第四十一篇-Docker安装Neo4j
创建目录 mkdir /opt/neo4j-data创建 docker run \ -d --name neo4j \ -p 7474:7474 -p 7687:7687 \ -v /opt/neo4j-data/data:/data \ -v /opt/neo4j-data/logs:/logs \ -v /opt/neo4j-data//conf:/var/lib/neo4j/conf \ -v /opt/neo4j-data/plugins:/plugins \ --env NEO4J…...
数电基础(组合逻辑电路+Proteus)
1.组合逻辑电路 1.1组合逻辑电路的分析 1.1.1组合逻辑电路的定义 组合逻辑电路的定义 (1)对于一个逻辑电路,其输出状态在任何时刻只取决于同一时刻的输入状态,而与电路的原来状态无关,这种电路被定义为组合逻辑电路…...
自给自足:手搓了一个睡眠监测仪,用着怎么样?
很久不分享手搓党作品拉! 今天分享一个“基于毫米波雷达的睡眠监测仪”作品! 用Air700E开发板毫米波雷达,手搓一个开箱即用的睡眠监测仪,不花冤枉钱! 来仔细瞧瞧! 一、项目原理及硬件制作 毫米波是指频率…...
Miniforge详细安装教程(macOs和Windows)
(注:主要是解决商业应用anaconda收费问题,这是轻量级的代替,个人完全可以使用anaconda和miniconda) Miniforge 是一个轻量级的包管理器,类似于 Anaconda 和 Miniconda。它主要用于安装基于 conda 的 Python 环境,专注于…...
HDFS Shell作业1
1.在HDFS上建立/user/stu/自己学号,和/user/stu/input目录。 命令: hdfs dfs -mkdir -p /user/stu/22 hdfs dfs -mkdir /user/stu/input 2.用两种不同的方法上传albums.csv至HDFS的学号目录和input目录中。 命令: hdfs dfs -put par…...
做玄幻封面素材网站/中国最新领导班子
统计目录大小的python脚本: vi dirsize.py 注: 1、def为自定义函数,有返回值以return结束 #!/usr/bin/python import osfrom os.path import join, getsize def getdirsize(dir):size 0for root, dirs, files in os.walk(dir):size sum([ge…...
做柜子好的设计网站/网络营销制度课完整版
ProgressDialog 继承自AlertDialog,AlertDialog继承自Dialogpublic class ProgressDialog extends AlertDialogProgressDialog的创建方式有两种,一种是new ProgressDialog,一种是调用ProgressDialog的静态方法show()创建并显示,这…...
宣城高端网站建设/互联网全网推广
大多数情况下,为了保证对外服务的安全性,我们在服务端实现的为服务接口时往往都会有一定的权限校验机制,比如对用户登录状态的校验等;同时为了防止客户端在发起请求时被篡改等安全方面的考虑,还会有一些签名校验的机制…...
自助搭建网站系统/网络营销常用的工具和方法
本文主要是介绍Spring和Mybatis三种整合方式的配置文件,即在DAO层注入问题,仅当做自己的一次笔记 1、采用MapperScannerConfigurer,它将会查找类路径下的映射器并自动将它们创建成MapperFactoryBean。 applicationContext_MapperScannerCon…...
成套小说网站模板/数据分析师资格证书怎么考
1. 什么是架构设计? 架构设计就是一个系统的草图。 软件架构就是对软件从整体到部分的描述,从开发到运行再到后期扩展的描述,从性能和安全可靠性进行描述。 2. 架构设计为了解决什么问题? 解决开发之初,也就是逻辑设计…...
计算机网站php设计代做/搜索引擎优化的方法与技巧
摘要: PyTorch是一个基于Python语言的深度学习框架,专门针对 GPU 加速的深度神经网络(DNN)的程序开发。基本上,它所有的程序都是用python写的,这就使得它的源码看上去比较简洁,在机器学习领域中…...