目录
-
- 一、引言
- [二、解析与修改 SELECT 语句](#二、解析与修改 SELECT 语句)
- [三、解析与修改 INSERT 语句](#三、解析与修改 INSERT 语句)
- [四、解析与修改 UPDATE 语句](#四、解析与修改 UPDATE 语句)
- [五、动态追加 WHERE 条件](#五、动态追加 WHERE 条件)
- 六、实际项目中的应用:DpSqlParserHelper
- 七、总结
- 八、附录
一、引言
在日常开发中,尤其是涉及SQL语句动态生成、分析、重写等场景时,直接操作SQL字符串容易出错且难以维护。JSqlParser 是一个开源的 Java SQL 解析器,能够将 SQL 语句解析为可操作的 Java 对象,极大地方便了 SQL 的分析与处理。常见的使用场景包括:SQL 语法分析、SQL 动态拼接、SQL 审计、权限控制等。
maven依赖:
xml
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>5.3</version>
</dependency>
本文将结合实际单元测试代码,介绍 JSqlParser 的基本用法,包括解析和修改 SELECT、INSERT、UPDATE 语句,以及如何动态追加 WHERE 条件。最后结合实际项目中的 DpSqlParserHelper 工具类,说明其在数据权限场景下的应用。
二、解析与修改 SELECT 语句
下面通过单元测试 testSelect 方法,演示如何解析和修改 SELECT 语句的各个部分。
java
@Test
void testSelect() throws JSQLParserException {
String sql = "SELECT DISTINCT u.id, r.role_name, u.user_name, u.sex, u.email "
+ "FROM t_user u "
+ "LEFT JOIN t_role r ON u.role_id = r.id "
+ "WHERE r.role_name = '管理员' "
+ "ORDER BY u.age DESC "
+ "LIMIT 0,10";
String modifiedSql = "SELECT * FROM t_user u "
+ "LEFT JOIN t_role r ON u.role_id = r.id "
+ "WHERE u.id = 1 "
+ "ORDER BY u.age "
+ "LIMIT 0, 5";
System.out.println("【原始 SQL】:" + sql);
System.out.println("--------------------------------------------------------");
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = select.getPlainSelect();
System.out.println("【DISTINCT 子句】:" + plainSelect.getDistinct());
System.out.println("【查询字段】:" + plainSelect.getSelectItems());
System.out.println("【FROM 表】:" + plainSelect.getFromItem());
System.out.println("【WHERE 子句】:" + plainSelect.getWhere());
System.out.println("【JOIN 子句】:" + plainSelect.getJoins());
System.out.println("【LIMIT 子句】:" + plainSelect.getLimit());
System.out.println("【OFFSET 子句】:" + plainSelect.getOffset());
System.out.println("【ORDER BY 子句】:" + plainSelect.getOrderByElements());
System.out.println("--------------------------------------------------------");
// 取消去重
plainSelect.setDistinct(null);
// 修改查询字段为 *
List<SelectItem<?>> selectItems = new ArrayList<>();
selectItems.add(new SelectItem<>(new AllColumns()));
plainSelect.setSelectItems(selectItems);
// 修改 WHERE 子句
EqualsTo equalsTo = new EqualsTo();
equalsTo.setLeftExpression(new Column("u.id"));
equalsTo.setRightExpression(new LongValue(1));
plainSelect.setWhere(equalsTo);
// 修改 LIMIT 子句
Limit limit = new Limit();
limit.setRowCount(new LongValue(5));
limit.setOffset(new LongValue(0));
plainSelect.setLimit(limit);
// 修改排序为 u.age ASC
OrderByElement orderByElement = new OrderByElement();
orderByElement.setExpression(new Column("u.age"));
orderByElement.setAsc(true); // 升序
plainSelect.setOrderByElements(Collections.singletonList(orderByElement));
System.out.println("【处理后 SQL】:" + plainSelect);
Assertions.assertEquals(modifiedSql, plainSelect.toString(), "处理后select SQL不符合预期");
}
运行结果:
【原始 SQL】:SELECT DISTINCT u.id, r.role_name, u.user_name, u.sex, u.email FROM t_user u LEFT JOIN t_role r ON u.role_id = r.id WHERE r.role_name = '管理员' ORDER BY u.age DESC LIMIT 0,10
--------------------------------------------------------
【DISTINCT 子句】:DISTINCT
【查询字段】:[u.id, r.role_name, u.user_name, u.sex, u.email]
【FROM 表】:t_user u
【WHERE 子句】:r.role_name = '管理员'
【JOIN 子句】:[LEFT JOIN t_role r ON u.role_id = r.id]
【LIMIT 子句】: LIMIT 0, 10
【OFFSET 子句】:null
【ORDER BY 子句】:[u.age DESC]
--------------------------------------------------------
【处理后 SQL】:SELECT * FROM t_user u LEFT JOIN t_role r ON u.role_id = r.id WHERE u.id = 1 ORDER BY u.age LIMIT 0, 5
说明:
- 使用
CCJSqlParserUtil.parse解析 SQL 字符串为Select对象。 - 可通过
PlainSelect获取和修改DISTINCT、查询字段、WHERE、ORDER BY、LIMIT等子句。 - 修改后可直接通过
toString()输出新的 SQL 语句。
三、解析与修改 INSERT 语句
通过 testInsert 方法,演示如何解析和修改 INSERT 语句的字段和值。
java
@Test
void testInsert() throws JSQLParserException {
String sql = "INSERT INTO t_user (role_id, user_name, email, age, sex, register_time ) "
+ "VALUES ( 1, 'xw', 'isxuwei@qq.com', 25, '男', '2024-04-12 17:37:18' );";
String modifiedSql = "INSERT INTO t_user (role_id, user_name, email, age, register_time, status) "
+ "VALUES (1, 'xw', 'isxuwei@qq.com', 26, '2024-04-12 17:37:18', 'create')";
System.out.println("【原始 SQL】:" + sql);
System.out.println("--------------------------------------------------------");
Insert insert = (Insert) CCJSqlParserUtil.parse(sql);
System.out.println("【插入目标表】:" + insert.getTable());
System.out.println("【插入字段】:" + insert.getColumns());
System.out.println("【插入值】:" + insert.getValues());
System.out.println("--------------------------------------------------------");
ExpressionList<Column> columns = insert.getColumns();
ExpressionList<Expression> values = (ExpressionList<Expression>) insert.getValues().getExpressions();
// 字段和值是一一对应的,把性别删除掉
columns.remove(4);
values.remove(4);
// 新增一列状态,默认为 create
columns.add(new Column("status"));
values.add(new StringValue("create"));
// 更新年龄字段 +1
Expression expression = values.get(3);
LongValue longValue = (LongValue) expression;
longValue.setValue(longValue.getValue() + 1);
System.out.println("【处理后 SQL】:" + insert);
Assertions.assertEquals(modifiedSql, insert.toString(), "处理后insert SQL不符合预期");
}
运行结果:
【原始 SQL】:INSERT INTO t_user (role_id, user_name, email, age, sex, register_time ) VALUES ( 1, 'xw', 'isxuwei@qq.com', 25, '男', '2024-04-12 17:37:18' );
--------------------------------------------------------
【插入目标表】:t_user
【插入字段】:role_id, user_name, email, age, sex, register_time
【插入值】:VALUES (1, 'xw', 'isxuwei@qq.com', 25, '男', '2024-04-12 17:37:18')
--------------------------------------------------------
【处理后 SQL】:INSERT INTO t_user (role_id, user_name, email, age, register_time, status) VALUES (1, 'xw', 'isxuwei@qq.com', 26, '2024-04-12 17:37:18', 'create')
说明:
- 通过
Insert对象可获取和修改插入的字段及对应值。 - 支持动态增删字段、修改值等操作。
四、解析与修改 UPDATE 语句
通过 testUpdate 方法,演示如何解析和修改 UPDATE 语句的 SET 和 WHERE 子句。
java
@Test
void testUpdate() throws JSQLParserException {
String sql = "UPDATE t_user "
+ "SET email = '373675032@qq.com', phone = '10086' "
+ "WHERE id = 1";
String modifiedSql = "UPDATE t_user "
+ "SET email = '373675032@qq.com', update_time = 1768960154010 "
+ "WHERE id = 1 AND deleted = 0";
System.out.println("【原始 SQL】:" + sql);
System.out.println("--------------------------------------------------------");
Update update = (Update) CCJSqlParserUtil.parse(sql);
System.out.println("【更新目标表】:" + update.getTable());
List<UpdateSet> updateSets = update.getUpdateSets();
for (UpdateSet updateSet : updateSets) {
System.out.println("【更新字段】:" + updateSet.getColumns());
System.out.println("【更新字】:" + updateSet.getValues());
}
System.out.println("【更新条件】:" + update.getWhere());
System.out.println("--------------------------------------------------------");
// 去掉更新手机号
updateSets.remove(1);
// 添加更新字段
UpdateSet updateSet = new UpdateSet();
updateSet.add(new Column("update_time"), new LongValue(1768960154010L));
updateSets.add(updateSet);
// 更新 Where 条件
AndExpression expression = new AndExpression();
expression.withLeftExpression(update.getWhere());
EqualsTo equalsTo = new EqualsTo();
equalsTo.setLeftExpression(new Column("deleted"));
equalsTo.setRightExpression(new LongValue(0));
expression.withRightExpression(equalsTo);
update.setWhere(expression);
System.out.println("【处理后 SQL】:" + update);
Assertions.assertEquals(modifiedSql, update.toString(), "处理后update SQL不符合预期");
}
运行结果:
【原始 SQL】:UPDATE t_user SET email = '373675032@qq.com', phone = '10086' WHERE id = 1
--------------------------------------------------------
【更新目标表】:t_user
【更新字段】:email
【更新字】:'373675032@qq.com'
【更新字段】:phone
【更新字】:'10086'
【更新条件】:id = 1
--------------------------------------------------------
【处理后 SQL】:UPDATE t_user SET email = '373675032@qq.com', update_time = 1768960154010 WHERE id = 1 AND deleted = 0
说明:
- 通过
Update对象可获取和修改 SET 字段和值。 - WHERE 条件可通过表达式对象灵活拼接。
五、动态追加 WHERE 条件
通过 testAppendSelectWhereCondition 方法,演示如何为 SELECT 语句动态追加 WHERE 条件。
java
@ParameterizedTest
@CsvSource(value = {
"column2 > 10 => SELECT * FROM table WHERE column1 = 'value' AND column2 > 10 ORDER BY column1 ASC LIMIT 0, 5",
"(column2 > 10) OR (column3 = '20') => SELECT * FROM table WHERE column1 = 'value' AND (column2 > 10) OR (column3 = '20') ORDER BY column1 ASC LIMIT 0, 5",
"false => SELECT * FROM table WHERE column1 = 'value' AND false ORDER BY column1 ASC LIMIT 0, 5",
"column2 IN (SELECT id FROM table2 WHERE deleted = '0') => SELECT * FROM table WHERE column1 = 'value' AND column2 IN (SELECT id FROM table2 WHERE deleted = '0') ORDER BY column1 ASC LIMIT 0, 5"
},
delimiterString = "=>")
void testAppendSelectWhereCondition(String appendCondition, String modifiedSql) throws JSQLParserException {
String sql = "SELECT * FROM table WHERE column1 = 'value' ORDER BY column1 ASC LIMIT 0, 5";
System.out.println("Original SQL: " + sql);
System.out.println("Append Where condition: " + appendCondition);
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = select.getPlainSelect();
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
for (SelectItem<?> item : selectItems) {
System.out.println("Selected column: " + item);
}
System.out.println("Table: " + plainSelect.getFromItem());
System.out.println("Where clause: " + plainSelect.getWhere());
// 修改 WHERE 条件
Expression extebdExpression = CCJSqlParserUtil.parseCondExpression(appendCondition);
AndExpression andExpression = new AndExpression(plainSelect.getWhere(), extebdExpression);
plainSelect.setWhere(andExpression);
System.out.println("Modified SQL: " + plainSelect);
System.out.println("--------------------------------------------------------");
Assertions.assertEquals(modifiedSql, plainSelect.toString(), "附加select where条件后的SQL不符合预期");
}
运行结果:
Original SQL: SELECT * FROM table WHERE column1 = 'value' ORDER BY column1 ASC LIMIT 0, 5
Append Where condition: column2 > 10
Selected column: *
Table: table
Where clause: column1 = 'value'
Modified SQL: SELECT * FROM table WHERE column1 = 'value' AND column2 > 10 ORDER BY column1 ASC LIMIT 0, 5
--------------------------------------------------------
Original SQL: SELECT * FROM table WHERE column1 = 'value' ORDER BY column1 ASC LIMIT 0, 5
Append Where condition: (column2 > 10) OR (column3 = '20')
Selected column: *
Table: table
Where clause: column1 = 'value'
Modified SQL: SELECT * FROM table WHERE column1 = 'value' AND (column2 > 10) OR (column3 = '20') ORDER BY column1 ASC LIMIT 0, 5
--------------------------------------------------------
Original SQL: SELECT * FROM table WHERE column1 = 'value' ORDER BY column1 ASC LIMIT 0, 5
Append Where condition: false
Selected column: *
Table: table
Where clause: column1 = 'value'
Modified SQL: SELECT * FROM table WHERE column1 = 'value' AND false ORDER BY column1 ASC LIMIT 0, 5
--------------------------------------------------------
Original SQL: SELECT * FROM table WHERE column1 = 'value' ORDER BY column1 ASC LIMIT 0, 5
Append Where condition: column2 IN (SELECT id FROM table2 WHERE deleted = '0')
Selected column: *
Table: table
Where clause: column1 = 'value'
Modified SQL: SELECT * FROM table WHERE column1 = 'value' AND column2 IN (SELECT id FROM table2 WHERE deleted = '0') ORDER BY column1 ASC LIMIT 0, 5
--------------------------------------------------------
说明:
- 通过解析追加条件表达式,并与原有 WHERE 条件用
AndExpression组合,实现动态追加。
六、实际项目中的应用:DpSqlParserHelper
在实际项目中,常常需要对 SQL 语句进行权限控制,比如为所有查询、更新、删除语句自动追加数据权限条件。手动拼接 SQL 易出错,比如原实现在order by后面附加条件导致的sql语法错误,JSqlParser 则能安全、优雅地实现这一需求。
DpSqlParserHelper 工具类封装了 SQL 解析与 WHERE 条件追加的逻辑,核心方法如下:
java
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.update.Update;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* Sql解析器助手
*
* @author luohq
* @date 2026-01-21
*/
public class DpSqlParserHelper {
public static final Logger log = LoggerFactory.getLogger(DpSqlParserHelper.class);
private DpSqlParserHelper() {
}
/**
* 在原SQL的where条件上追加AND条件<br/>
* 注:使用JSqlParser附加where条件,避免字符串拼接带来的SQL语法错误(比如原实现在order by后面附加条件导致的sql语法错误)
*
* @param originalSql 原SQL语句
* @param appendCondition 追加的条件表达式
* @return 追加AND条件后的SQL语句
*/
public static String appendWhereAndCondition2(String originalSql, String appendCondition) {
log.debug("SqlParserHelper appendAndConditionToWhere - originalSql: {}, appendCondition: {}", originalSql, appendCondition);
Statement statement = null;
Expression appendCondtionExpression = null;
try {
//解析原始SQL语句
statement = CCJSqlParserUtil.parse(originalSql);
//解析附加的条件表达式
appendCondtionExpression = CCJSqlParserUtil.parseCondExpression(appendCondition);
//将附加条件用括号括起来,避免和原SQL的where条件出现优先级问题
if (!(appendCondtionExpression instanceof ParenthesedExpressionList)) {
appendCondtionExpression = new ParenthesedExpressionList<>(appendCondtionExpression);
}
} catch (JSQLParserException e) {
throw new RuntimeException(e);
}
//根据SQL语句类型,获取和设置where条件的函数
Supplier<Expression> whereGetter = null;
Consumer<Expression> whereSetter = null;
if (statement instanceof Select) {
Select select = (Select) statement;
PlainSelect plainSelect = select.getPlainSelect();
whereGetter = plainSelect::getWhere;
whereSetter = plainSelect::setWhere;
} else if (statement instanceof Update) {
Update update = (Update) statement;
whereGetter = update::getWhere;
whereSetter = update::setWhere;
} else if (statement instanceof Delete) {
Delete delete = (Delete) statement;
whereGetter = delete::getWhere;
whereSetter = delete::setWhere;
} else {
log.warn("SqlParserHelper appendAndConditionToWhere - insert sql语句不支持设置where条件:{}", statement);
throw new UnsupportedOperationException("insert sql语句不支持设置where条件:" + statement);
}
//获取原SQL的where条件
Expression originWhereExpression = whereGetter.get();
//设置新的where条件
if (originWhereExpression == null) {
//原SQL没有where条件,直接设置新的条件
whereSetter.accept(appendCondtionExpression);
} else {
//原SQL的where条件是多个OR组合条件,将其用括号括起来,避免和追加的AND条件出现优先级问题
if (originWhereExpression instanceof OrExpression) {
originWhereExpression = new ParenthesedExpressionList<>(originWhereExpression);
}
//原SQL有where条件,追加AND条件
Expression newWhereExpression = new AndExpression(originWhereExpression, appendCondtionExpression);
whereSetter.accept(newWhereExpression);
}
String modifiedSql = statement.toString();
log.debug("SqlParserHelper appendAndConditionToWhere - modifiedSql: {}", modifiedSql);
return modifiedSql;
}
}
实际场景说明:
- 统一为 SELECT、UPDATE、DELETE 语句追加数据权限条件,避免 SQL 注入和语法错误。
- 通过 JSqlParser 解析和重写 SQL,保证 SQL 结构正确,适用于多种复杂场景。
- 结合单元测试,确保各种 SQL 语句追加条件后的正确性。
七、总结
JSqlParser 提供了强大的 SQL 解析与重写能力,极大提升了 SQL 动态处理的安全性和可维护性。无论是 SQL 语句的分析、字段/条件的动态修改,还是实际项目中的数据权限控制,JSqlParser 都能提供优雅的解决方案。推荐在涉及 SQL 动态处理的 Java 项目中优先考虑使用 JSqlParser。
八、附录
上述相关单元测试的完整代码如下:
java
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.*;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* JSqlParser测试
*
* @author luohq
* @date 2026-01-21
*/
public class JSqlParserTest {
@Test
void testSelect() throws JSQLParserException {
String sql = "SELECT DISTINCT u.id, r.role_name, u.user_name, u.sex, u.email "
+ "FROM t_user u "
+ "LEFT JOIN t_role r ON u.role_id = r.id "
+ "WHERE r.role_name = '管理员' "
+ "ORDER BY u.age DESC "
+ "LIMIT 0,10";
String modifiedSql = "SELECT * FROM t_user u "
+ "LEFT JOIN t_role r ON u.role_id = r.id "
+ "WHERE u.id = 1 "
+ "ORDER BY u.age "
+ "LIMIT 0, 5";
System.out.println("【原始 SQL】:" + sql);
System.out.println("--------------------------------------------------------");
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = select.getPlainSelect();
System.out.println("【DISTINCT 子句】:" + plainSelect.getDistinct());
System.out.println("【查询字段】:" + plainSelect.getSelectItems());
System.out.println("【FROM 表】:" + plainSelect.getFromItem());
System.out.println("【WHERE 子句】:" + plainSelect.getWhere());
System.out.println("【JOIN 子句】:" + plainSelect.getJoins());
System.out.println("【LIMIT 子句】:" + plainSelect.getLimit());
System.out.println("【OFFSET 子句】:" + plainSelect.getOffset());
System.out.println("【ORDER BY 子句】:" + plainSelect.getOrderByElements());
System.out.println("--------------------------------------------------------");
// 取消去重
plainSelect.setDistinct(null);
// 修改查询字段为 *
List<SelectItem<?>> selectItems = new ArrayList<>();
selectItems.add(new SelectItem<>(new AllColumns()));
plainSelect.setSelectItems(selectItems);
// 修改 WHERE 子句
EqualsTo equalsTo = new EqualsTo();
equalsTo.setLeftExpression(new Column("u.id"));
equalsTo.setRightExpression(new LongValue(1));
plainSelect.setWhere(equalsTo);
// 修改 LIMIT 子句
Limit limit = new Limit();
limit.setRowCount(new LongValue(5));
limit.setOffset(new LongValue(0));
plainSelect.setLimit(limit);
// 修改排序为 u.age ASC
OrderByElement orderByElement = new OrderByElement();
orderByElement.setExpression(new Column("u.age"));
orderByElement.setAsc(true); // 升序
plainSelect.setOrderByElements(Collections.singletonList(orderByElement));
System.out.println("【处理后 SQL】:" + plainSelect);
Assertions.assertEquals(modifiedSql, plainSelect.toString(), "处理后select SQL不符合预期");
}
@Test
void testInsert() throws JSQLParserException {
String sql = "INSERT INTO t_user (role_id, user_name, email, age, sex, register_time ) "
+ "VALUES ( 1, 'xw', 'isxuwei@qq.com', 25, '男', '2024-04-12 17:37:18' );";
String modifiedSql = "INSERT INTO t_user (role_id, user_name, email, age, register_time, status) "
+ "VALUES (1, 'xw', 'isxuwei@qq.com', 26, '2024-04-12 17:37:18', 'create')";
System.out.println("【原始 SQL】:" + sql);
System.out.println("--------------------------------------------------------");
Insert insert = (Insert) CCJSqlParserUtil.parse(sql);
System.out.println("【插入目标表】:" + insert.getTable());
System.out.println("【插入字段】:" + insert.getColumns());
System.out.println("【插入值】:" + insert.getValues());
System.out.println("--------------------------------------------------------");
ExpressionList<Column> columns = insert.getColumns();
ExpressionList<Expression> values = (ExpressionList<Expression>) insert.getValues().getExpressions();
// 字段和值是一一对应的,把性别删除掉
columns.remove(4);
values.remove(4);
// 新增一列状态,默认为 create
columns.add(new Column("status"));
values.add(new StringValue("create"));
// 更新年龄字段 +1
Expression expression = values.get(3);
LongValue longValue = (LongValue) expression;
longValue.setValue(longValue.getValue() + 1);
System.out.println("【处理后 SQL】:" + insert);
Assertions.assertEquals(modifiedSql, insert.toString(), "处理后insert SQL不符合预期");
}
@Test
void testUpdate() throws JSQLParserException {
String sql = "UPDATE t_user "
+ "SET email = '373675032@qq.com', phone = '10086' "
+ "WHERE id = 1";
String modifiedSql = "UPDATE t_user "
+ "SET email = '373675032@qq.com', update_time = 1768960154010 "
+ "WHERE id = 1 AND deleted = 0";
System.out.println("【原始 SQL】:" + sql);
System.out.println("--------------------------------------------------------");
Update update = (Update) CCJSqlParserUtil.parse(sql);
System.out.println("【更新目标表】:" + update.getTable());
List<UpdateSet> updateSets = update.getUpdateSets();
for (UpdateSet updateSet : updateSets) {
System.out.println("【更新字段】:" + updateSet.getColumns());
System.out.println("【更新字】:" + updateSet.getValues());
}
System.out.println("【更新条件】:" + update.getWhere());
System.out.println("--------------------------------------------------------");
// 去掉更新手机号
updateSets.remove(1);
// 添加更新字段
UpdateSet updateSet = new UpdateSet();
updateSet.add(new Column("update_time"), new LongValue(1768960154010L));
updateSets.add(updateSet);
// 更新 Where 条件
AndExpression expression = new AndExpression();
expression.withLeftExpression(update.getWhere());
EqualsTo equalsTo = new EqualsTo();
equalsTo.setLeftExpression(new Column("deleted"));
equalsTo.setRightExpression(new LongValue(0));
expression.withRightExpression(equalsTo);
update.setWhere(expression);
System.out.println("【处理后 SQL】:" + update);
Assertions.assertEquals(modifiedSql, update.toString(), "处理后update SQL不符合预期");
}
@ParameterizedTest
@CsvSource(value = {
"column2 > 10 => SELECT * FROM table WHERE column1 = 'value' AND column2 > 10 ORDER BY column1 ASC LIMIT 0, 5",
"(column2 > 10) OR (column3 = '20') => SELECT * FROM table WHERE column1 = 'value' AND (column2 > 10) OR (column3 = '20') ORDER BY column1 ASC LIMIT 0, 5",
"false => SELECT * FROM table WHERE column1 = 'value' AND false ORDER BY column1 ASC LIMIT 0, 5",
"column2 IN (SELECT id FROM table2 WHERE deleted = '0') => SELECT * FROM table WHERE column1 = 'value' AND column2 IN (SELECT id FROM table2 WHERE deleted = '0') ORDER BY column1 ASC LIMIT 0, 5"
},
delimiterString = "=>")
void testAppendSelectWhereCondition(String appendCondition, String modifiedSql) throws JSQLParserException {
String sql = "SELECT * FROM table WHERE column1 = 'value' ORDER BY column1 ASC LIMIT 0, 5";
System.out.println("Original SQL: " + sql);
System.out.println("Append Where condition: " + appendCondition);
Select select = (Select) CCJSqlParserUtil.parse(sql);
PlainSelect plainSelect = select.getPlainSelect();
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
for (SelectItem<?> item : selectItems) {
System.out.println("Selected column: " + item);
}
System.out.println("Table: " + plainSelect.getFromItem());
System.out.println("Where clause: " + plainSelect.getWhere());
// 修改 WHERE 条件
Expression extebdExpression = CCJSqlParserUtil.parseCondExpression(appendCondition);
AndExpression andExpression = new AndExpression(plainSelect.getWhere(), extebdExpression);
plainSelect.setWhere(andExpression);
System.out.println("Modified SQL: " + plainSelect);
System.out.println("--------------------------------------------------------");
Assertions.assertEquals(modifiedSql, plainSelect.toString(), "附加select where条件后的SQL不符合预期");
}
}
参考:
https://github.com/JSQLParser/JSqlParser
JSqlParser实战指南:解析、修改和生成SQL语句的实用技巧
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?