请教后台接口如何根据前台的筛选条件动态构造查询 sql

180 天前
 irisdev

做管理系统,我们现在开发的大多数表单都是“与”的关系,比如前端有四个查询条件 a,b,c,d ,前端把这四个查询条件都传给我,我在查询接口里面会这么写:

if(a != null)
{
  sql += " and table.a = a";
}

if(b != null)
{
  sql += " and table.b = b";
}

这样写是没有问题的,假如现在有这样一种场景,前端四个查询条件中 a 和 b 是或的关系,比如 a 指的是待筛选内容的创建者,b 指的是待筛选内容的处理者,那么根据创建者或处理者来查询是合理的需求,同时 a 、b 与 c 、d 又是与的关系,比如 c 指截止时间,d 指处理状态,那么这时按照上面的思路,拼 sql 就得这么拼

if(a != null)
{
  if(b != null)
  {
    sql += " and (table.a = a or table.b = b)";
  }
  else {
    sql += " and table.a = a";
  }
}

if(b != null)
{
  if(a != null)
  {
    sql += " and (table.a = a or table.b = b)";
  }
  else {
    sql += " and table.b = b";
}

现在这样算是蒙混过关了(我现在就是这么处理的),但是我又想到一个问题,假如用户 或 的查询条件是不固定的,且前端只传给我一个对象,那这个 sql 拼接就是指数倍增加了。再假设,如果前端写了一个支持根据后台传过去的字段,由用户递归构造且/或查询条件的“且或组件”,这个组件支持用户自定义不确定数量的且或关系,支持自定义操作符,例如,传过来,不传 searchParam 对象,传过来是一个 Json 对象,类似以下:

{
    "prop": "",
    "relation": "and",
    "condition": [
        {
            "relation": "or",
            "condition": [
                {
                    "prop": "Name",
                    "operation": ">",
                    "value": "李华"
                },
                {
                    "prop": "Age",
                    "operation": "=".
                    "value": 24
                }
            ]
        },
        {
            "prop": "School",
            "operation": "=",
            "value": "大学"
        }
    ]
}

这时候的 sql 该咋拼呢,感觉像是一道算法题?是不是直接后序遍历这个 json 结构,把对应拼接的 sql 直接放代码就可以了?算法比较弱,还没写,主要不知道括号往哪放,还是没遍历一层直接嵌套括号就可以了?

最后又回到开始的问题,如果一开始前端就传给我一个{},让我处理,有些字段是或,跟其他字段是且,这样的话我是不是就得写一大串 sql 了,有没有好点的办法,还是我在后台反射下,把不为 null 的给过滤出来,这样就不用判断一大坨为 null 的逻辑了,因为是维护老项目不好在序列化时把 null 去掉,还是说这个工作前端做比较好

3507 次点击
所在节点    Java
51 条回复
importmeta
180 天前
说个之前碰见的某国企的做法, 有个传公式, 另一个字段传数据.
BigEarMosquito
180 天前
lucasdev
180 天前
可以看看 React Query Builder ( https://react-querybuilder.js.org/) 是怎么做的


Convert to 那里可以
- 选 SQL (parameterized) / SQL (named parameters),输出防注入的 SQL
- 选 JSON (和你给的那个 JSON 格式差不多),但这种需要你自己构建语法树,再转成 SQL (也可以找找现成的三方库)
Anakin078
180 天前
@815979670 #32 并不能确保后台的认证、鉴权不会出问题。在有 SQL 注入和没有 SQL 注入的场景下,绕过认证鉴权访问后台的攻击影响是不一样的,在有 SQL 注入的场景下会危害到整库整表,甚至达到服务器的 RCE 。层层防护才能有效增加攻击成本,最大化的保障数据安全。
815979670
180 天前
@Anakin078 是的 不能因为假设的前提 就完全信任客户端体积的数据
Anakin078
180 天前
@815979670 #45 赞!有这种认识很好,开发的代码安全性会高很多的。
ninjamk200
180 天前
这个 react 库不错
JYii
180 天前
这么拼起来数据量上来了,sql 优化怎么办(小表当没看见
irisdev
179 天前
@JYii 都不用数据量大起来,一般都是多表 join 拼的,不过用 orm 更难优化吧
lianhuayu420
171 天前
好好设计下关系,走 orm 吧,建议 https://github.com/babyfish-ct/jimmer 试试
zjc97816
160 天前
Antlr4 试试呢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://yangjunhui.monster/t/1085135

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX