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

7 小时 45 分钟前
 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 去掉,还是说这个工作前端做比较好

1654 次点击
所在节点    Java
44 条回复
hukei
5 小时 35 分钟前
额 没有 ORM 吗 交给框架就好
cheng6563
5 小时 29 分钟前
让前端传 SQL ,后台查的时候设置连接 readonly 。
注入随他注吧,别把表删了就行。
siweipancc
5 小时 29 分钟前
兄弟你好奔放啊,没被攻击过?
sparklee
5 小时 23 分钟前
前端传 sql 语句中的 where 部分, 做好验证, 内网基本没啥大问题吧
nice2cu
4 小时 42 分钟前
<if test="param.xx!=null">
AND xxx = #{param.xxx}
</if>
mybatis
adoal
4 小时 33 分钟前
大概率是业务需求没梳理清楚……
ccsert
4 小时 18 分钟前
可以看看 bean-searcher 这个框架,专门做复杂查询的 https://gitee.com/troyzhxu/bean-searcher
NoKey
4 小时 7 分钟前
常规业务吧,产品经理可以定一下,哪些字段可以查询,可以限制一下,别太多,后端就好处理了
vcbal
4 小时 3 分钟前
标准 XY 问题
fzdfengzi
4 小时 1 分钟前
用表达式目录树动态拼 sql
kingcanfish
4 小时 0 分钟前
如果是各种条件乱七八糟的复杂查询 是不是应该用 cel https://cel.dev/?hl=zh-cn
815979670
3 小时 52 分钟前
插个楼 问一下 为什么后台还需要考虑注入的问题?@siweipancc @cheng6563 @BugCry

我的理解是 后台 只要把登录体系的身份验证做好(例如强密码、定期修改密码、MFA 多因素认证、短信验证码、webAuthn 、登录网段限制等手段),保证别人不能非法登录进去这个前提下。

后端不像前端 不会直面用户,为了后台开发的灵活性,我觉得做一些 SQL 拼接操作是可以接受的,只要记录好操作记录、正常使用后台的内部人员不会故意通过注入等手段破坏系统数据的吧?

当然 可能有我没想到的原因,所以想提出来交流一下。
codehz
3 小时 35 分钟前
@815979670 就算假设业务人员不会有恶意的情况,也可能意外复制粘贴了有问题的文本到查询框里
siweipancc
3 小时 29 分钟前
@815979670 搜索用户名我传两”_ ”进去 ,上家就是这么烂的
skallz
3 小时 26 分钟前
@siweipancc 说的对,就算内网用户没有任何恶意行为,也会因为预想之外的内容导致出现问题
treblex
3 小时 1 分钟前
https://github.com/LazyFury/SpringLearn/blob/master/kt/src/main/java/io/lazyfury/lucky_cat/common/helper/SearchHelper.kt

试试这个,url 格式类似 django ,用 jpa Specification 实现的,
我在 java 和 php 和 go 都尝试了类似的实现,最后选的 go ,所以这个代码不太严谨,但是能跑😂
815979670
2 小时 10 分钟前
@codehz @siweipancc @skallz
有道理 我忽略了非主观故意的场景,所以最好的方式还是走 SQL 预处理,通过占位符,使数据与 SQL 分离,这样即使非主观故意 也不会对业务产生影响
wogogoing
1 小时 54 分钟前
@BugCry 哈哈 果然有这样的回复。
Sayuri
1 小时 48 分钟前
https://www.npmjs.com/package/nicot

安利一下自己写的 npm 包,可以解决这个问题。
diagnostics
1 小时 47 分钟前
@irisdev #8 graphql 可以解决

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

https://www.v2ex.com/t/1085135

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

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

© 2021 V2EX