JSON驱动的动态SQL查询:实现灵活条件筛选的查询

当我们构建动态 SQL 查询功能时,需要考虑到安全性和灵活性的平衡。本文将讨论如何通过 JSON 数据和 FreeMarker 模板构造动态 SQL 查询,以及如何减少 SQL 注入的风险。

JSON 数据与动态 SQL

JSON 是一种常用的数据交换格式,它的灵活性和易读性使得它在前后端数据传输中得到广泛应用。我们可以利用 JSON 数据来构建动态 SQL 查询,根据用户的输入条件动态生成 SQL 语句,实现灵活的查询功能。

FreeMarker 模板引擎

FreeMarker 是一个强大的模板引擎,它可以将数据模型和模板文件结合起来生成文本输出。我们可以利用 FreeMarker 的语法和功能,将 JSON 数据和 SQL 查询模板结合起来,动态生成最终的 SQL 语句。

动态 SQL 查询示例

让我们以一个示例来说明如何通过 JSON 数据和 FreeMarker 构造动态 SQL 查询功能。假设我们有一个需求:根据用户输入的查询条件动态生成 SQL 查询语句,并执行查询操作。

首先,我们可以定义一个 JSON 数据格式,包含用户的查询条件,如下所示

{
    "model": "pageForPurchaseOrder",
    "page": 1,
    "size": 10,
    "filters": {
        "acceptance": "0",
        "account": "",
        "beginDate": "2024-01-03",
        "endDate": "2024-05-09",
        "warehouseCodeList": "000,SD002"
    }
}

接下来,我们可以编写一个 FreeMarker 模板文件,定义 SQL 查询语句的模板,例如:

SELECT * FROM users
WHERE 1=1
</#if>
<#if age??>
AND age = ${age}
</#if>
<#if city??>
AND city = '${city}'
</#if>

在这个模板中,我们使用了 FreeMarker 的条件判断语句 <#if>${} 表达式,根据传入的查询条件动态生成 SQL 查询语句。

后台配置具体内容

结合后台的 FreeMarker 模板引擎和前台传递的 JSON 数据是一种常见的做法。下面将通过引入代码示例来说明如何整合后台的 FreeMarker 和前台的 JSON 数据生成 SQL 查询语句,并进一步探讨其实现原理和优势。

首先,让我们来看一下代码示例:

public ResponseObject<SqlObject> getSqlObject(HttpServletRequest request) {
    ResponseObject<SqlObject> result = new ResponseObject<>();
    try {
        SqlObject obj = new SqlObject();
        JSONObject search = JSON.parseObject(request.getInputStream());
        obj.setPage(search.getLongValue("page", 1));
        obj.setSize(search.getLongValue("size", 10));
        String modelKey = search.getString("model");
        QueryTemplateRequest req = new QueryTemplateRequest();
        req.setId(modelKey);
        ResponseObject<QueryTemplateResponse> model = queryTemplateApi.view(req);
        if (model.getCode() != 200) {
            result.setCode(501);
            result.setMsg("model不存在");
            return result;
        }
        Map<String, Object> param = new HashMap<>();
        param.put("phone", UserUtils.user().getPhone());
        if (search.containsKey("filters")){
            JSONObject filters = search.getJSONObject("filters");

            QueryTemplateExt ext = model.getData().getExtData();
            if (ext != null && ext.getFilters() != null) {
                for (QueryFilter filter : ext.getFilters()) {
                    if (filter.getJavaName() != null) {
                        if (filters.containsKey(filter.getJavaName())){
                            try {
                                Object temp = FieldTypeMatch.matchType(filter.getJavaName(), filter.getFieldType(), filters);
                                if (temp!=null){
                                    param.put(filter.getJavaName(), temp);
                                }
                            }catch (Exception e){
                                e.printStackTrace();
                            }

                        }
                    }
                }
            }
        }

        obj.setSql(process(model.getData().getContent(), param));
        result.setData(obj);
        return result;
    } catch (Exception e) {
        e.printStackTrace();
        result.setCode(501);
        result.setMsg("解析json出错");
        return result;
    }
}

在这段代码中,我们接收了一个 HTTP 请求,通过 HttpServletRequest 获取了前台传递的 JSON 数据。然后,利用 FreeMarker 模板引擎和后台的业务逻辑,动态生成了 SQL 查询语句。下面我们来逐步解析这段代码的关键步骤:

  1. 解析 JSON 数据: 首先通过 JSON.parseObject(request.getInputStream()) 解析前台传递的 JSON 数据,获取了查询所需的各种参数,例如页码、每页大小、模型关键字和筛选条件等。

  2. 查询模型信息: 根据获取的模型关键字,调用 queryTemplateApi 获取模型信息。如果模型不存在或获取失败,则返回相应的错误信息。

  3. 构建参数: 根据前台传递的筛选条件,利用后台的业务逻辑构建查询所需的参数。这里通过 FieldTypeMatch 类中的 matchType 方法,根据字段类型匹配,减少 SQL 注入的风险,并构建最终的查询参数。

  4. 生成 SQL 语句: 最后通过 process 方法,结合模型内容和参数,生成最终的 SQL 查询语句,并将其设置到 SqlObject 对象中,作为返回结果。

通过这段代码示例,我们展示了如何整合后台的 FreeMarker 模板引擎和前台传递的 JSON 数据,实现动态生成 SQL 查询语句的功能。这种方法使得系统可以根据用户的不同需求动态生成不同的 SQL 查询,具有很高的灵活性和可扩展性。

这种整合方式的优势在于:

  • 灵活性: 可以根据前端传递的 JSON 数据动态生成不同的 SQL 查询,适应不同的业务需求。
  • 安全性: 通过后台的业务逻辑和参数处理,可以有效减少 SQL 注入的风险。
  • 可维护性: 使用 FreeMarker 模板可以将 SQL 查询逻辑与 Java 代码分离,提高代码的可读性和可维护性。

在动态生成 SQL 查询语句的过程中,FieldTypeMatch 类发挥了重要作用。这个类中的 matchType 方法根据字段类型和前台传递的 JSON 数据,将不同类型的值转换为适合 SQL 查询的格式。让我们来看一下这个方法的具体实现:

 public static Object matchType(String key, Integer fieldType, JSONObject filter) {
        Object value;
        if (fieldType == 1) {
            value = filter.getString(key);
        } else if (fieldType == 2) {
            value = filter.getInteger(key);
        } else if (fieldType == 3) {
            value = filter.getLong(key);
        } else if (fieldType == 4) {
            value = filter.getDouble(key);
        } else if (fieldType == 5) {
            value = filter.getBigDecimal(key);
        } else if (fieldType == 6) {
            Object value = filter.getDate(key);
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            value = format.format(value);
        } else if (fieldType == 7) {
            value = filter.getBoolean(key);
        } else {
            String[] stars;
            String temp;
            if (fieldType == 10) {
                temp = filter.getString(key);
                if (temp == null) {
                    return null;
                }

                stars = temp.split(",");
                value = Arrays.stream(stars).map(String::trim).filter(StringUtils::hasText).map((s) -> {
                    return "'" + s + "'";
                }).collect(Collectors.joining(","));
                value = "(" + value + ")";
            } else if (fieldType == 11) {
                temp = filter.getString(key);
                if (temp == null) {
                    return null;
                }

                stars = temp.split(",");
                value = Arrays.stream(stars).map(String::trim).filter(StringUtils::hasText).map(Long::valueOf).map(String::valueOf).collect(Collectors.joining(","));
                value = "(" + value + ")";
            } else if (fieldType == 12) {
                temp = filter.getString(key);
                if (temp == null) {
                    return null;
                }

                stars = temp.split(",");
                value = Arrays.stream(stars).map(String::trim).filter(StringUtils::hasText).map(Double::valueOf).map(String::valueOf).collect(Collectors.joining(","));
                value = "(" + value + ")";
            } else {
                value = null;
            }
        }

        return value;
    }

在这个方法中,根据传入的 fieldType 参数,对应处理了不同类型的值转换:

  • 对于基本类型(如字符串、整数、长整数、双精度浮点数、布尔值等),直接通过 filter 对象的对应方法获取值。
  • 对于日期类型(fieldType 为 6),采用 SimpleDateFormat 进行日期格式化处理。
  • 对于其他复杂类型(例如逗号分隔的字符串列表,整数列表,双精度浮点数列表等),进行了特殊处理,将其转换为适合 SQL 查询的格式。

这样的设计使得在动态生成 SQL 查询语句时,可以根据字段类型准确地处理对应的值,避免了因数据类型不匹配而导致的错误或异常,同时也增强了代码的健壮性和可维护性。

总结

通过结合 JSON 数据和 FreeMarker 模板引擎,我们可以实现动态生成 SQL 查询语句的功能。这种方法使得查询条件可以灵活地根据用户需求动态生成,提高了系统的灵活性和可维护性。在实际应用中,可以根据具体的业务需求和数据模型,结合 FreeMarker 的强大功能,实现更加智能和高效的动态 SQL 查询功能。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【读点论文】YOLOX: Exceeding YOLO Series in 2021,无锚框单阶段目标检测方案,解耦检测头的分类和回归分支,优化标签分配策略

YOLOX: Exceeding YOLO Series in 2021 Abstract 在本报告中&#xff0c;我们介绍了YOLO系列的一些经验改进&#xff0c;形成了一种新的高性能探测器—YOLOX。我们将YOLO检测器切换到无锚方式&#xff0c;并进行其他先进的检测技术&#xff0c;即去耦头和领先的标签分配策略S…

信号处理相关知识

一&#xff1a; 1.序列——三种典型序列通过matlab绘图即可 2.数字信号的自变量一定是整数&#xff0c;幅度上取值是有限的状态&#xff08;不一定是整数&#xff09;。 3.抽取和插值 4.模拟正弦信号sin(wt):w是角频率&#xff0c;单位rad/s,f是频率w/2Π。 5.假设用采样周…

浏览器工作原理与实践--浏览上下文组:如何计算Chrome中渲染进程的个数

经常有朋友问到如何计算Chrome中渲染进程个数的问题&#xff0c;那么今天就来完整地解答这个问题。 在前面“04 | 导航流程”这一讲中我们介绍过了&#xff0c;在默认情况下&#xff0c;如果打开一个标签页&#xff0c;那么浏览器会默认为其创建一个渲染进程。不过我们在“04 |…

Qt | 远程仓库

git | 基本操作 01 远程仓库 在了解之前&#xff0c;先注册github(gitee或者gitcode等等)账号&#xff0c;由于你的本地Git仓库和github仓库之间的传输是通过SSH加密的&#xff0c;所以需要一点设置&#xff1a; 第一步&#xff1a;创建SSH Key。在用户主目录下&#xff0c;看看…

姿态估计-人脸识别mesh-3d手势识别-3d目标检测-背景分割-人脸关键点

往期热门博客项目回顾&#xff1a;点击前往 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 AI健身教练-引体向上…

UE4 相机围绕某点旋转

关卡&#xff08;一个相机CameraActor&#xff0c;一个Cube(名叫Target)&#xff09;&#xff1a; 关卡蓝图里的逻辑(为了大家看得清楚&#xff0c;特意连得很紧凑&#xff0c;也比较乱&#xff0c;不然一张截图放不下)&#xff1a; 只对Yaw 只Pitch: 同样对Roll: 围绕任…

Modelsim与Verilog入门

0.什么是Modelsim&#xff1f; Modelsim是一个支持多语言的仿真环境&#xff0c;比如我知道的Verilog和VHDL语言都可以在里边使用&#xff0c;这俩都是硬件描述语言&#xff1b; 即就是个软件&#xff0c;你可以用Verilog语言来写代码&#xff0c;然后编译&#xff0c;仿真出…

C++学习进阶:异常

目录 1.异常处理机制 1.1.抛异常和捕获异常 1.1.1.异常机制的基本场景 1.1.2.函数调用中异常栈展开的匹配规则&#xff1a; 1.2.异常机制的实际应用场景 2.异常相关知识 2.1.异常安全和异常重新抛出 2.2.noexcept关键字 2.3.异常的优缺点 1.异常处理机制 我们在C语言…

Finding a needle in Haystack: Facebook’s photo storage——论文泛读

OSDI 2010 Paper 分布式元数据论文阅读笔记整理 问题 到2010年为止&#xff0c;用户已经在Facebook上传了超过650亿张照片&#xff0c;对于每个上传的照片&#xff0c;Facebook生成并存储四个不同大小的图像&#xff0c;导致目前存储了超过2600亿张图片&#xff0c;相当于超过…

AQS(AbstractQueuedSynchronizer)队列同步器源码解读

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 目录 1. 前言 2. AOS、AQS、AQLS的区别 3. AQS的底层原理 3.1. 核心思想 3.2. 数…

Qt 项目文件(.pro)概述

Qt 项目pro文件 引言一、pro文件初探二、部分参数详解 引言 Qt工程项目由项目文件&#xff08;.pro&#xff09;进行管理。qmake使用文件中的信息生成Makefile&#xff0c;其中包含构建每个项目所需的所有命令。pro文件通常包含源文件和头文件的列表、常规配置信息以及任何特定…

ST-GCN模型详解(+openpose)

ST-GCN模型详解&#xff08;openpose&#xff09; 一、什么是ST-GCN呢 基于骨架的动作识别&#xff08;Skeleton-Based Action Recognition&#xff09;主要任务是从一系列时间连续的骨骼关键点&#xff08;2D/3D&#xff09;中识别出正在执行的动作。因为牵涉到骨骼框架这种…

CentOS7升级openssl

文章目录 一 系统环境二 操作步骤三 版本检查 一 系统环境 公司服务器等保要求&#xff0c;修复openssl的高危漏洞。 本机使用centos7.9系统&#xff0c;openssl版本是1.0.2k&#xff0c;计划升级到1.1.1q 在执行下列操作前&#xff0c;务必要打快照做好备份&#xff0c;以防升…

030——从GUI->Client->Server->driver实现对红外遥控的控制

目录 1、 解决韦东山老师irda模块中断申请失败的bug 2、 client添加处理程序 3、 添加服务器处理程序和驱动处理句柄 4、 处理数据读出不准确问题 5、 修改后的展示 1、 解决韦东山老师irda模块中断申请失败的bug irda需要通过中断来触发读操作&#xff0c;申请中断需要引…

Octopus v2:斯坦福的嵌入设备专用大模型

斯坦福大学推出了 Octopus v2&#xff0c;这是一种突破性的设备上语言模型&#xff0c;旨在解决与现有模型相关的延迟、准确性和隐私问题。 NSDT工具推荐&#xff1a; Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑…

源码篇--Nacos服务--中章(1):Nacos服务端的启动

文章目录 前言一、Nacos Console 启动入口&#xff1a;二、启动过程&#xff1a;2.1 容器启动监听器&#xff1a;2.1.1 调整启动标识为正在启动状态&#xff1a;2.1.2 环境准备阶段&#xff1a;2.1.3 容器环境准备&#xff1a;2.1.4 自定义的环境变量 设置&#xff1a;2.1.5 服…

Spectre-v2 以及 Linux Retpoline技术简介

文章目录 前言一、Executive Summary1.1 Spectre-v2: Branch Predictor Poisoning1.2 Mitigating Spectre-v2 with Retpolines1.3 Retpoline Concept 二、BackgroundExploit Composition 三、(Un-)Directing Speculative Execution四、Construction (x86)4.1 Speculation Barri…

测试人员通常遇到的“坑”

网上看到一个帖子&#xff0c;从事多年的测试从业者&#xff0c;吐槽测试过程中遇到的“坑”&#xff0c;感觉比较有意思&#xff0c;我在工作当中也遇到通常的问题&#xff0c;看得出这位网友比较喜欢总结&#xff0c;帖子地址奉上&#xff0c;有兴趣的可以浏览一下&#xff1…

bug(警告):[vue-router] Duplicate named routes definition: …

查看警告&#xff1a;[vue-router] Duplicate named routes definition——翻译[vue-router]重复命名路由定义 小编劝诫&#xff1a;当我们在开发过程中警告也一定不要忽略&#xff0c;虽然你在本地跑代码时这些警告影响项目的正常运行&#xff0c;但是会让你产生误区&#xff…

大模型日报|今日必读的8篇大模型论文

大家好&#xff0c;今日必读的大模型论文来啦&#xff01; 1.EdgeFusion&#xff1a;端侧文本到图像生成&#xff0c;只需不到一秒 用于文本到图像生成的稳定扩散&#xff08;SD&#xff09;技术需要大量计算&#xff0c;这对其实际应用构成了重大障碍。为此&#xff0c;最近…