利用jsqlparser解析SQL语句

时常会遇到很多情况,我们需要对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.jsqlparsergroupId>
            <artifactId>jsqlparserartifactId>
        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 params);
}

实现类:TablePickerImpl

public class TablePickerImpl implements TablePicker {

    private static Logger logger = LoggerFactory.getLogger(TablePickerImpl.class);
     @Override
    public String pickTable(String sql, ErrorMode mode, Map 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语句,可以查看源码包。
利用jsqlparser解析SQL语句_第1张图片

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

你可能感兴趣的:(mysql)