【JSqlParser】使用JSqlParser解析sql并动态删除查询条件

【JSqlParser】使用JSqlParser解析sql并动态删除查询条件

已封装成工具类,完整代码在文章末尾

现有需求/场景

用户(BI报表中)可以输入sql,并且配置${}占位符,可以选择值,实现sql查询条件动态赋值。

- 这里的${name}是用户选择的任务名称
select *from table where task_name = ${name}

- 转换后
select *from table where task_name = '2025年年报'

实际中,用户可选必填选填,选填时,${}没有值,依旧存在于sql中,无法正确执行sql,即用户不选值时,需要将sql查询条件删除

- 这里的${name},用户未选择值,将对应的查询条件删除
select *from table where task_name = ${name}
- 转换后
select *from table

使用JsqlParser

  • JsqlParser解析sql时可以分出where后的查询条件,连接词(or and)等。比直接使用正则去匹配sql中的关键字更加强大,可以处理更复杂的sql(子查询,in,like,group having等)

  • 已考虑到各种复杂sql,和去除查询条件后单独剩下where,或者where后还有连接词的情况。以下情况均已做正确处理

select *from table where
select *from table where and id = 1
select *from table and id = 1

测试

    @Test
    public void test() throws Exception {
        // ${}无法使用jsqlparser解析,需要手动替换成其他字符,这里使用USER_NOT_INPUT
//        String sql = "select * from table where id = 1 and name = USER_NOT_INPUT or age = 4 and salary > 1000 and create_date > date_format('yyyy-mm-dd', USER_NOT_INPUT)";
//        String sql = "select *from table";
        String sql = "select *from table where id in (1,2,3) and age like '%${age}%' or address in (select address from table2 where id = ${id})";
//        String sql = "select *from table where id in (USER_NOT_INPUT) or name like '%USER_NOT_INPUT'";
        handleEmptySqlConditions(sql);
    }

java代码

 /**
     * 分割表达式为带连接词的条件项,递归实现
     * @param expr
     * @param connector
     * @param list
     */
    private static void splitRecursive(Expression expr, String connector, List<ConditionNode> list) {
        // 如果表达式为空,直接返回
        if (Objects.isNull(expr)) {
            return;
        }
        if (expr instanceof AndExpression) {
            AndExpression andExpr = (AndExpression) expr;
            // 左边连接词继续传connector
            splitRecursive(andExpr.getLeftExpression(), connector, list);
            // 右边连接词变为 AND
            splitRecursive(andExpr.getRightExpression(), "AND", list);
        } else if (expr instanceof OrExpression) {
            OrExpression orExpr = (OrExpression) expr;
            splitRecursive(orExpr.getLeftExpression(), connector, list);
            splitRecursive(orExpr.getRightExpression(), "OR", list);
        }    // 处理 IN 表达式(例如:col IN (1,2,3))
        else if (expr instanceof InExpression) {
            list.add(new ConditionNode(connector, expr));
        }
        // 处理 LIKE 表达式(例如:col LIKE '%val%')
        else if (expr instanceof LikeExpression) {
            list.add(new ConditionNode(connector, expr));
        }
        // 处理其他比较操作(=, >, < 等)
        else if (expr instanceof ComparisonOperator) {
            list.add(new ConditionNode(connector, expr));
        }
        // 处理括号包裹的表达式(例如:(a=1 OR b=2))
        else if (expr instanceof Parenthesis) {
            Parenthesis parenthesis = (Parenthesis) expr;
            splitRecursive(parenthesis.getExpression(), connector, list);
        } else {
            // 叶子表达式,添加列表
            list.add(new ConditionNode(connector, expr));
        }
    }

完整代码在我的:github

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值