利用druid sql parser搞一些事情


在最近的項目開發中,有這樣一個需求,就是給定一個查詢的sql,在where語句中添加幾個條件語句。剛開始想的是,是否能用正則去做這個事情呢?其實不用語法樹還是有一點困難的。

經過一系列google,看到了我們國產的druid里面sql parse的穩當還是比較詳盡。具體參考這個文檔SQL Parser

還是回到之前的需求:

public List<Map<String, Object>> search(String sql, Map<String, Object> conditions) {
    List<Map<String, Object>> result = new ArrayList<>();
    // SQLParserUtils.createSQLStatementParser可以將sql裝載到Parser里面
    SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcUtils.MYSQL);
	// parseStatementList的返回值SQLStatement本身就是druid里面的語法樹對象
    List<SQLStatement> stmtList = parser.parseStatementList();


    SQLStatement stmt = stmtList.get(0);
    if (stmt instanceof SQLSelectStatement) {
        // convert conditions to 'and' statement
        StringBuffer constraintsBuffer = new StringBuffer();
        Set<String> keys = conditions.keySet();
        Iterator<String> keyIter = keys.iterator();
        if (keyIter.hasNext()) {
            constraintsBuffer.append(keyIter.next()).append(" = ?");
        }
        while (keyIter.hasNext()) {
            constraintsBuffer.append(" AND ").append(keyIter.next()).append(" = ?");
        }
        SQLExprParser constraintsParser = SQLParserUtils.createExprParser(constraintsBuffer.toString(), JdbcUtils.MYSQL);
        SQLExpr constraintsExpr = constraintsParser.expr();

        SQLSelectStatement selectStmt = (SQLSelectStatement) stmt;
        // 拿到SQLSelect 通過在這里打斷點看對象我們可以看出這是一個樹的結構
        SQLSelect sqlselect = selectStmt.getSelect();
        SQLSelectQueryBlock query = (SQLSelectQueryBlock) sqlselect.getQuery();
        SQLExpr whereExpr = query.getWhere();
        // 修改where表達式
        if (whereExpr == null) {
            query.setWhere(constraintsExpr);
        } else {
            SQLBinaryOpExpr newWhereExpr = new SQLBinaryOpExpr(whereExpr, SQLBinaryOperator.BooleanAnd, constraintsExpr);
            query.setWhere(newWhereExpr);
        }
        sqlselect.setQuery(query);
        sql = sqlselect.toString();
        Session session = sessionFactory.openSession();
        SQLQuery sqlQuery = session.createSQLQuery(sql);
        Collection values = conditions.values();
        int index = 1;
        for (Object value : values) {
            sqlQuery.setParameter(index, value);
            index++;
        }
        result = sqlQuery.list();
        session.close();
    } else {
        throw new Exception("not select statement");
    }
    return result;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM