在最近的項目開發中,有這樣一個需求,就是給定一個查詢的sql,在where語句中添加幾個條件語句。剛開始想的是,是否能用正則去作這個事情呢?其實不用語法樹仍是有一點困難的。git
通過一系列google,看到了咱們國產的druid裏面sql parse的妥當仍是比較詳盡。具體參考這個文檔SQL Parsergithub
仍是回到以前的需求:sql
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; }