利用jsqlparser解析SQL语句

本文介绍了如何利用jsqlparser这个SQL解析工具,替代传统的StringBuild方法,优雅地处理SQL语句的拼接和替换。通过创建DBSelectDeParser、定义TablePickerImpl接口,实现了对查询和插入语句的解析。jsqlparser支持多种SQL语句,包括CRUD操作,以及where语句的解析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

时常会遇到很多情况,我们需要对SQL语句进行替换或者拼接。以往我们可能会用StringBuild来进行拼接。

StringBuilder sql = new StringBuilder();
sql.append("select * from");
sql.append(schema);
sql.append(".");
sql.append(table);
sql.append("where id = '"+id+"'");

但是这样的操作不仅看起来不优雅,也不简洁。面对复杂的sql,有很多子循环的情况下,并不适用。

因此我们需要借助一些工具来实现这个功能。这里我们使用jsqlparser这个sql解析工具。

SqlParser - github地址:https://github.com/JSQLParser/JSqlParser

SqlParser最新版jar下载:http://search.maven.org/remotecontent?filepath=com/github/jsqlparser/jsqlparser/0.9.1/jsqlparser-0.9.1.jar

maven依赖为

        <dependency>
            <groupId>com.github.jsqlparser</groupId>
            <artifactId>jsqlparser</artifactId>
        </dependency>

在GitHub中有很详细的介绍,我们对常用的CRUD方法做一个总结。

首先建立一个DBSelectDeParser继承SelectDeParser

public class DBSelectDeParser extends SelectDeParser {

    public DBSelectDeParser(ExpressionVisitor expressionVisitor, StringBuilder buffer){
        super(expressionVisitor, buffer);
    }

    @Override
    public void visit(Table tableName) {
        String schema = tableName.getSchemaName();
        String table = tableName.getName();

        if (fullTableName ==null){
            throw new SqlvpException("table is null");
        }
        tableName.setSchemaName("user");
        tableName.setName("age");
        StringBuilder buffer = getBuffer();

        buffer.append(tableName.getFullyQualifiedName());
        Pivot pivot = tableName.getPivot();
        if (pivot != null) {
            pivot.accept(this);
        }
        Alias alias = tableName.getAlias();
        if (alias != null) {
            buffer.append(alias);
        }
    }
}

现在来定义一个接口,每次只要调用这个接口就可以了

public interface TablePicker {
    /**
     * 从sql文中挑选出所有的库表
     *
     * @param sql sql文
     * @param mode 错误的策略模式
     * @param params
     * @return 库表列表
     */
    String pickTable(String sql, ErrorMode mode, Map<String, Object> params);
}

实现类:TablePickerImpl

public class TablePickerImpl implements TablePicker {

    private static Logger logger = LoggerFactory.getLogger(TablePickerImpl.class);
     @Override
    public String pickTable(String sql, ErrorMode mode, Map<String, Object> params) {

        CCJSqlParserManager parser = new CCJSqlParserManager();
        StringBuilder buffer = new StringBuilder();
        try {
            Statement stmt = parser.parse(new StringReader(sql));

            // 查询语句处理
            if (stmt instanceof Select) {
                Select Statement = (Select) stmt;
                logger.debug("解析sql的语句: {} ",Statement.toString());
                //Start of value modification
                ExpressionDeParser expressionDeParser = new ExpressionDeParser();
                SelectDeParser deparser = new DBSelectDeParser(expressionDeParser, buffer, mode, params);
                expressionDeParser.setSelectVisitor(deparser);
                expressionDeParser.setBuffer(buffer);
                Statement.getSelectBody().accept(deparser);
                logger.debug("替换成功,文本为: {} ",buffer.toString());
                return buffer.toString();
            }
            // 插入语句处理
            if (stmt instanceof Insert) {
                Insert Statement = (Insert) stmt;
                logger.debug("解析sql的语句: {} ",Statement.toString());

                Table t = new Table();
                t.setSchemaName("user");
                t.setName("age");
                Statement.setTable(t);

                // 获取insert语句中的查询语句,如果没有则不替换select
                Select select = Statement.getSelect();
                if (select != null) {
                    ExpressionDeParser expressionDeParser = new ExpressionDeParser();
                    SelectDeParser deparser = new DBSelectDeParser(expressionDeParser, buffer, mode, params);
                    expressionDeParser.setSelectVisitor(deparser);
                    expressionDeParser.setBuffer(buffer);
                    select.getSelectBody().accept(deparser);
                }
                logger.debug("替换成功,文本为: {} ",Statement.toString());
                return Statement.toString();
            }



        } catch (JSQLParserException e) {
            logger.error(e.getMessage());
        }
        // 如果四种条件都不匹配则抛出异常。
        throw new SqlvpException("error sql can not be parse!check your sql!");

    }
}

通过以上操作我们就完成了对查询和插入语句的解析替换,查询和插入是两个不同的操作,所以语句解析也不相同。

官方支持各种SQL语句,可以查看源码包。
这里写图片描述

同样还支持对where语句的解析,大家可自行测试。

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值