在最近的项目开发中,有这样一个需求,就是给定一个查询的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; }