【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