再探:jsqlparser怎样实现复杂SQL的解析和重写

本文最后更新于 2025年2月19日

未完待续

一、引言

之前的数据权限和多租户功能,都由Mybatis-Plus的Interceptor机制实现,本质上都是在Interceptor中拦截和解析SQL然后追加条件,利用数据权限或租户相关的字段对涉及数据权限或租户的表进行条件过滤,而解析SQL然后追加条件的功能均需要依赖Java的SQL解析库:JSQLParser

二、JSQLParser

三、数据权限DataPermissionInterceptor源码解读

public String parserSingle(String sql, Object obj) {
    if (logger.isDebugEnabled()) {
        logger.debug("original SQL: " + sql);
    }
    try {
        Statement statement = JsqlParserGlobal.parse(sql);
        return processParser(statement, 0, sql, obj);
    } catch (JSQLParserException e) {
        throw ExceptionUtils.mpe("Failed to process, Error SQL: %s", e.getCause(), sql);
    }
}

public String parserMulti(String sql, Object obj) {
    if (logger.isDebugEnabled()) {
        logger.debug("original SQL: " + sql);
    }
    try {
        // fixed github pull/295
        StringBuilder sb = new StringBuilder();
        Statements statements = JsqlParserGlobal.parseStatements(sql);
        int i = 0;
        for (Statement statement : statements) {
            if (i > 0) {
                sb.append(StringPool.SEMICOLON);
            }
            sb.append(processParser(statement, i, sql, obj));
            i++;
        }
        return sb.toString();
    } catch (JSQLParserException e) {
        throw ExceptionUtils.mpe("Failed to process, Error SQL: %s", e.getCause(), sql);
    }
}

/**
 * 执行 SQL 解析
 *
 * @param statement JsqlParser Statement
 * @return sql
 */
protected String processParser(Statement statement, int index, String sql, Object obj) {
    if (logger.isDebugEnabled()) {
        logger.debug("SQL to parse, SQL: " + sql);
    }
    if (statement instanceof Insert) {
        this.processInsert((Insert) statement, index, sql, obj);
    } else if (statement instanceof Select) {
        this.processSelect((Select) statement, index, sql, obj);
    } else if (statement instanceof Update) {
        this.processUpdate((Update) statement, index, sql, obj);
    } else if (statement instanceof Delete) {
        this.processDelete((Delete) statement, index, sql, obj);
    }
    sql = statement.toString();
    if (logger.isDebugEnabled()) {
        logger.debug("parse the finished SQL: " + sql);
    }
    return sql;
}

/**
 * 新增
 */
protected void processInsert(Insert insert, int index, String sql, Object obj) {
    throw new UnsupportedOperationException();
}

/**
 * 删除
 */
protected void processDelete(Delete delete, int index, String sql, Object obj) {
    throw new UnsupportedOperationException();
}

/**
 * 更新
 */
protected void processUpdate(Update update, int index, String sql, Object obj) {
    throw new UnsupportedOperationException();
}

/**
 * 查询
 */
protected void processSelect(Select select, int index, String sql, Object obj) {
    throw new UnsupportedOperationException();
}

四、多租户TenantLineInnerInterceptor源码解读


再探:jsqlparser怎样实现复杂SQL的解析和重写
https://blog.liuzijian.com/post/yudao-source-code-jsqlparser.html
作者
Liu Zijian
发布于
2025年2月1日
更新于
2025年2月19日
许可协议