JSqlParser入门

目录

一、引言

在日常开发中,尤其是涉及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 的基本用法,包括解析和修改 SELECTINSERTUPDATE 语句,以及如何动态追加 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、查询字段、WHEREORDER BYLIMIT 等子句。
  • 修改后可直接通过 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 语句?

相关推荐
10km5 个月前
jsqlparser(六):TablesNamesFinder 深度解析与 SQL 格式化实现
java·数据库·sql·jsqlparser
问道飞鱼9 个月前
【Springboot进阶】springboot+mybatis+jsqlparser实现数据权限控制
mybatis·springboot·jsqlparser·数据权限
战神刘玉栋1 年前
《通俗易懂 · JSqlParser 解析和构造SQL》
架构师·jsqlparser
天幕繁星1 年前
JSqlParser、JavaCC实操
mybatis·mybatis plus·jsqlparser·javacc
HezhezhiyuLe2 年前
JSQLParserException异常
jsqlparser