├── README.md ├── docs └── assets │ └── imgs │ ├── expression-list.png │ ├── extend-ExpressionDeParser-result.png │ ├── extend-ExpressionDeParser.png │ ├── extend-ExpressionDeParser2.png │ └── image1.png ├── pom.xml └── src ├── main └── java │ └── com │ └── sql │ ├── constant │ └── Constant.java │ ├── entity │ ├── JdbcTemplateQueryParams.java │ ├── NamedParameterJdbcTemplateQueryParams.java │ └── ParamExp.java │ ├── parser │ ├── ExpressionParser.java │ ├── ReplaceColumnValues.java │ ├── ReplaceParamToMark.java │ ├── ReplaceParamToNamedParam.java │ ├── SQLConditionHandle.java │ └── SqlParser.java │ └── util │ ├── ParamsUtil.java │ └── SQLUtil.java └── test └── java └── com └── test ├── Test.java └── TestReplaceColumnValues.java /README.md: -------------------------------------------------------------------------------- 1 | # sql-parser 2 | 3 | sql-parser是一个依赖于[JSqlParser](https://github.com/JSQLParser/JSqlParser)做参数替换的工具,SQL语句中的参数是通过${}或#{}标识的,如有SQL语句:select * from user where id=${id} and name='${name}',则参数即为id和name,解析的原则是先将SQL中的参数替换为指定的标识后再做值替换。目前支持替换为三张类型的SQL语句。 4 | 5 | 1. 替换为SQL语句 6 | 2. 替换为Spring JdbcTemplate执行的SQL语句(能防止SQL注入,但是不能解决in查询) 7 | 3. 替换为Spring NamedParameterJdbcTemplate执行的SQL语句(能防止SQL注入,能解决in查询) 8 | 9 | 10 | 11 | (此方法会存在SQL注入问题)、 12 | 13 | 14 | 15 | ![例子](https://raw.githubusercontent.com/myjgithubdl/sql-parser/master/docs/assets/imgs/image1.png) 16 | 17 | 18 | 19 | 20 | 21 | # 一、替换为SQL语句 22 | 23 | 下面就根据SQL语句select * from user where id=${id} and name='${name}'做介绍。 24 | 25 | ## 1、正则替换 26 | 27 | ​ 该步骤是解析出SQL中所有参数,如果在传入的Map参数列表中有对应的值则作替换,如果没有则使用特定的值代替(目的是使用JSqlParser解析出表达式后做条件剔除)。在上图中因为只传入了name参数的值为Myron,所以解析出的SQL为: 28 | 29 | ```sql 30 | select * from user where id=-00000000 and name='Myron' 31 | ``` 32 | 33 | 34 | 35 | ## 2、解析SQL表达式 36 | 37 | ​ 在使用正则对SQL中的参数做替换以后,再用CCJSqlParserUtil解析出SQL中的表达式。 38 | 39 | ![表达式列表](https://raw.githubusercontent.com/myjgithubdl/sql-parser/master/docs/assets/imgs/expression-list.png) 40 | 41 | ## 3、表达式替换 42 | 43 | ​ 根据正则替换后的SQL和解析出的SQL表达式再次做替换。 44 | 45 | 46 | 47 | ## 使用方法 48 | 49 | 50 | 51 | ```java 52 | //需要解析的SQL语句 53 | String sql="select * from user where id=${id} and name='${name}'"; 54 | //参数列表 55 | Map params = new HashMap<>(); 56 | params.put("name", "Myron"); 57 | //解析SQL 58 | String realSql =SQLUtil.replaceSQLParams(sql, params); 59 | ``` 60 | 61 | 62 | 63 | # 二、替换为Spring JdbcTemplate SQL 64 | 65 | 下面就根据SQL语句select * from user where id=${id} and name='${name}'做介绍。 66 | 67 | ## 1、替换查询条件为字符串 68 | 69 | 如上面的SQL语句中的条件id=${id} 如果在SQL编译器看来${id}是数值,需要将其转化为'${id}'。然后在使用CCJSqlParserUtil.parse(addSingleQuoteSql)解析SQL语句 70 | 71 | ## 2、解析SQL表达式 72 | 73 | ​ 在使用正则对SQL中的参数做替换以后,再用CCJSqlParserUtil解析出SQL中的表达式,同时对查询语句中的字符串(''标识的条件)做处理,检查如果是查询参数则判断是否有改参数的值,如果有则使用?代替,没有值的话则打上一个没有值的标记,后期会把该条件清除。 74 | 75 | ​ 需要解析SQL语句中的字符串内容则要继承ExpressionDeParser类并重写其中的visit(StringValue stringValue)方法。 76 | 77 | ![表达式列表](https://raw.githubusercontent.com/myjgithubdl/sql-parser/master/docs/assets/imgs/extend-ExpressionDeParser.png) 78 | 79 | ## 3、表达式替换 80 | 81 | ​ 根据替换后的SQL中被标记没有值的查询条件删除。 82 | 83 | 84 | 85 | ## 使用方法 86 | 87 | ```java 88 | //需要解析的SQL语句 89 | String sql = "select * from user where id=${id} and name='${name}' " + 90 | "and age=${age} and address like ${address} "; 91 | //参数列表 92 | Map params = new HashMap<>(); 93 | params.put("name", "Myron"); 94 | params.put("age", "12"); 95 | 96 | JdbcTemplateQueryParams jdbcTemplateQueryParams = SQLUtil.sqlToJdbcTemplateQuery(sql, params); 97 | 98 | System.out.println("解析前SQL:"+sql); 99 | System.out.println("解析后SQL:"+jdbcTemplateQueryParams.getSql()); 100 | ``` 101 | 102 | 103 | 104 | ![表达式列表](https://raw.githubusercontent.com/myjgithubdl/sql-parser/master/docs/assets/imgs/extend-ExpressionDeParser-result.png) 105 | 106 | 107 | 108 | # 三、替换为Spring NamedParameterJdbcTemplate SQL 109 | 110 | 下面就根据SQL语句select * from user where id=${id} and name='${name}' and age=${age} and address like ${address} and sex in (${sex})做介绍。 111 | 112 | ## 1、替换查询条件为字符串 113 | 114 | 如上面的SQL语句中的条件id=${id} 如果在SQL编译器看来${id}是数值,需要将其转化为'${id}'。然后在使用CCJSqlParserUtil.parse(addSingleQuoteSql)解析SQL语句。 115 | 116 | ## 2、解析SQL表达式 117 | 118 | ​ 在使用正则对SQL中的参数做单引号处理以后,再用CCJSqlParserUtil解析出SQL中的表达式,同时对查询语句中的字符串(''标识的条件)做处理,检查如果是查询参数则判断是否有改参数的值,如果有则使用 :参数名 代替,没有值的话则打上一个没有值的标记,后期会把该条件清除。 119 | 120 | ​ 需要解析SQL语句中的字符串内容则要继承ExpressionDeParser类并重写其中的visit(StringValue stringValue)方法。 121 | 122 | ## 3、表达式替换 123 | 124 | ​ 根据替换后的SQL中被标记没有值的查询条件删除。 125 | 126 | 127 | 128 | ## 使用方法 129 | 130 | ```java 131 | //需要解析的SQL语句 132 | String sql = "select * from user where id=${id} and name='${name}' and age=${age} and address like ${address} and sex in (${sex}) "; 133 | 134 | List sexList=new ArrayList<>(); 135 | sexList.add("男"); 136 | 137 | //参数列表 138 | Map params = new HashMap<>(); 139 | params.put("name", "Myron"); 140 | params.put("age", "12"); 141 | params.put("sex",sexList); 142 | 143 | JdbcTemplateQueryParams jdbcTemplateQueryParams = SQLUtil.sqlToNamedParameterJdbcTemplateQuery(sql, params); 144 | 145 | System.out.println("解析前SQL:"+sql); 146 | System.out.println("解析后SQL:"+jdbcTemplateQueryParams.getSql()); 147 | ``` 148 | 149 | ![表达式列表](https://raw.githubusercontent.com/myjgithubdl/sql-parser/master/docs/assets/imgs/extend-ExpressionDeParser2.png) -------------------------------------------------------------------------------- /docs/assets/imgs/expression-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myjgithubdl/sql-parser/0d4efde9fbceacf098bffe30b2140cf543a382f7/docs/assets/imgs/expression-list.png -------------------------------------------------------------------------------- /docs/assets/imgs/extend-ExpressionDeParser-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myjgithubdl/sql-parser/0d4efde9fbceacf098bffe30b2140cf543a382f7/docs/assets/imgs/extend-ExpressionDeParser-result.png -------------------------------------------------------------------------------- /docs/assets/imgs/extend-ExpressionDeParser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myjgithubdl/sql-parser/0d4efde9fbceacf098bffe30b2140cf543a382f7/docs/assets/imgs/extend-ExpressionDeParser.png -------------------------------------------------------------------------------- /docs/assets/imgs/extend-ExpressionDeParser2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myjgithubdl/sql-parser/0d4efde9fbceacf098bffe30b2140cf543a382f7/docs/assets/imgs/extend-ExpressionDeParser2.png -------------------------------------------------------------------------------- /docs/assets/imgs/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myjgithubdl/sql-parser/0d4efde9fbceacf098bffe30b2140cf543a382f7/docs/assets/imgs/image1.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.sql.parser 8 | sql-parser 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | 18 | 19 | 20 | com.github.jsqlparser 21 | jsqlparser 22 | 2.0 23 | 24 | 25 | 26 | 31 | 32 | 33 | 38 | 39 | 40 | 41 | org.apache.commons 42 | commons-text 43 | 1.6 44 | 45 | 46 | 47 | org.projectlombok 48 | lombok 49 | 1.18.6 50 | provided 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-compiler-plugin 64 | 65 | 1.8 66 | 1.8 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /src/main/java/com/sql/constant/Constant.java: -------------------------------------------------------------------------------- 1 | package com.sql.constant; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class Constant { 7 | 8 | /** 9 | * SQL 参数匹配标志 10 | * 如下SQL语句参数为userId和name 11 | * SELECT * FROM tb WHERE userId=${userId} and name=${name} 12 | */ 13 | public static final String[] REG_PARAMS_PATTERN = {"\\$\\{(.*?)\\}"}; 14 | 15 | /** 16 | * 顺序需与上面的保持一致,只是加了一个单引号 17 | */ 18 | public static final String[] SQL_MARK_REG_PARAMS_PATTERN = {"('?)(%?)\\$\\{(.*?)\\}(%?)('?)"}; 19 | 20 | 21 | /** 22 | * 解析SQL参数替换时参数中没有值的代替标志 23 | */ 24 | public static final String PARAMS_NO_VALUE_FLAG = "-00000000"; 25 | 26 | 27 | /** 28 | * 将含有PARAMS_NO_VALUE_FLAG值的表达式替换为1=1 29 | */ 30 | public static final String SQL_NO_VALUE_EXPRESSION_REPLACE_FLAG = " 1=1 "; 31 | 32 | 33 | /** 34 | * 删除SQL中含有该表达式的条件,需与参数SQL_NO_VALUE_EXPRESSION_REPLACE_FLAG对应 35 | *

36 | * "1=1" 不能使用 37 | */ 38 | public static final String[] SQL_EXPRESSION_DELETE_FLAG = {"AND 1=1", "AND 1=1", "OR 1=1", "OR 1=1"}; 39 | 40 | public static final String[] SQL_EXPRESSION_END_DELETE_FLAG = {"WHERE 1=1", "WHERE 1=1"}; 41 | 42 | 43 | /** 44 | * SQL替换 将sql语句中含有key字符的替换为value内容 45 | */ 46 | public static final Map SQL_REPLACE_MAP = new HashMap<>(); 47 | 48 | static { 49 | SQL_REPLACE_MAP.put("WHERE 1=1 ORDER", "ORDER"); 50 | SQL_REPLACE_MAP.put("WHERE 1=1 LIMIT", "LIMIT"); 51 | SQL_REPLACE_MAP.put("WHERE 1=1 AND", "WHERE"); 52 | SQL_REPLACE_MAP.put("WHERE 1=1 GROUP BY", "GROUP BY"); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/sql/entity/JdbcTemplateQueryParams.java: -------------------------------------------------------------------------------- 1 | package com.sql.entity; 2 | 3 | import lombok.*; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * 封装Spring JdbcTemplate 查询参数 9 | * 该方式的问题在于不能解决in查询问题 10 | * 11 | * @since 0.0.1 12 | */ 13 | @Builder 14 | @Getter 15 | @Setter 16 | @NoArgsConstructor 17 | @AllArgsConstructor 18 | public class JdbcTemplateQueryParams { 19 | 20 | /** 21 | * 原始SQL,根据SQL中${}标识的参数解析出sql 22 | * 如:select * from tb where name=${name} 23 | */ 24 | private String originalSql; 25 | 26 | /** 27 | * List> queryForList(String sql, Object[] args, int[] argTypes) 28 | * queryForList执行的SQL,支持?占位符 29 | * select * from tb where name=? 30 | */ 31 | private String sql; 32 | 33 | /** 34 | * 对应于sql中?占位符的参数名 35 | * {"name"} 36 | */ 37 | private String[] argNames; 38 | 39 | /** 40 | * 对应于sql中?占位符的值 41 | * queryForList(String sql, Object[] args, int[] argTypes) 中的args 42 | */ 43 | private Object[] argValues; 44 | 45 | /** 46 | * 对应于sql中?占位符的数据类型 47 | * queryForList(String sql, Object[] args, int[] argTypes) 中的argTypes 48 | * 49 | * @see java.sql.Types 50 | */ 51 | private int[] argTypes; 52 | 53 | /** 54 | * SQL中的表达解析出的所有有参数表达式 55 | */ 56 | private List paramExpList; 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/sql/entity/NamedParameterJdbcTemplateQueryParams.java: -------------------------------------------------------------------------------- 1 | package com.sql.entity; 2 | 3 | 4 | public class NamedParameterJdbcTemplateQueryParams { 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/sql/entity/ParamExp.java: -------------------------------------------------------------------------------- 1 | package com.sql.entity; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Builder; 5 | import lombok.Data; 6 | import lombok.NoArgsConstructor; 7 | 8 | /** 9 | * 参数表达式 10 | */ 11 | @Data 12 | @NoArgsConstructor 13 | @AllArgsConstructor 14 | @Builder 15 | public class ParamExp { 16 | 17 | /** 18 | * 参数名 19 | * 如表达式${id} 的name为id 20 | */ 21 | private String name; 22 | 23 | /** 24 | * 表达式 25 | * 如表达式${id} 的exp为${id} 26 | */ 27 | private String exp; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/sql/parser/ExpressionParser.java: -------------------------------------------------------------------------------- 1 | package com.sql.parser; 2 | 3 | /** 4 | * 解析表达式 5 | */ 6 | public class ExpressionParser { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/sql/parser/ReplaceColumnValues.java: -------------------------------------------------------------------------------- 1 | package com.sql.parser; 2 | 3 | import com.sql.constant.Constant; 4 | import net.sf.jsqlparser.expression.StringValue; 5 | import net.sf.jsqlparser.util.deparser.ExpressionDeParser; 6 | 7 | import java.util.Map; 8 | 9 | public class ReplaceColumnValues extends ExpressionDeParser { 10 | 11 | Map paramsValueMap; 12 | 13 | public void setParamsValueMap(Map paramsValueMap) { 14 | this.paramsValueMap = paramsValueMap; 15 | } 16 | 17 | @Override 18 | public void visit(StringValue stringValue) { 19 | String strValue = stringValue.toString(); 20 | String paramEL = getParamEL(strValue); 21 | if (paramEL == null) { 22 | this.getBuffer().append(stringValue); 23 | } else { 24 | if (paramsValueMap != null && paramsValueMap.get(paramEL.substring(1, paramEL.length() - 1)) != null) { 25 | String mapValue = paramsValueMap.get(paramEL.substring(1, paramEL.length() - 1)).toString(); 26 | this.getBuffer().append(strValue.replace(paramEL, mapValue)); 27 | } else { 28 | this.getBuffer().append(Constant.PARAMS_NO_VALUE_FLAG); 29 | } 30 | } 31 | } 32 | 33 | /* @Override 34 | public void visit(LongValue longValue) { 35 | this.getBuffer().append(longValue); 36 | }*/ 37 | 38 | /** 39 | * @return 40 | */ 41 | public static String getParamEL(String sqlVal) { 42 | if ((sqlVal.startsWith("${") || sqlVal.startsWith("'${") 43 | || sqlVal.startsWith("#{") || sqlVal.startsWith("'#{")) 44 | && sqlVal.endsWith("}")) { 45 | return sqlVal.replaceAll("'", ""); 46 | } 47 | return null; 48 | } 49 | 50 | 51 | } -------------------------------------------------------------------------------- /src/main/java/com/sql/parser/ReplaceParamToMark.java: -------------------------------------------------------------------------------- 1 | package com.sql.parser; 2 | 3 | import com.sql.constant.Constant; 4 | import com.sql.entity.ParamExp; 5 | import net.sf.jsqlparser.expression.StringValue; 6 | import net.sf.jsqlparser.util.deparser.ExpressionDeParser; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * 替换参数到指定的标记 14 | */ 15 | public class ReplaceParamToMark extends ExpressionDeParser { 16 | 17 | /** 18 | * SQL中所有的参数 {@link ParamExp } 19 | */ 20 | List paramExpList; 21 | 22 | /** 23 | * 解析出的参数列表 24 | */ 25 | private List paramList = new ArrayList<>(); 26 | 27 | /** 28 | * 参数对应的值 29 | */ 30 | Map paramsValueMap; 31 | 32 | /** 33 | * 参数转化为的标志 34 | */ 35 | private String mark = " ? "; 36 | 37 | public ReplaceParamToMark() { 38 | } 39 | 40 | public ReplaceParamToMark(String mark, List paramExpList, Map paramsValueMap) { 41 | this.mark = mark; 42 | this.paramExpList = paramExpList; 43 | this.paramsValueMap = paramsValueMap; 44 | } 45 | 46 | public String getMark() { 47 | return mark; 48 | } 49 | 50 | public void setMark(String mark) { 51 | this.mark = mark; 52 | } 53 | 54 | public List getParamList() { 55 | return paramList; 56 | } 57 | 58 | public void setParamList(List paramList) { 59 | this.paramList = paramList; 60 | } 61 | 62 | @Override 63 | public void visit(StringValue stringValue) { 64 | String strValue = stringValue.toString(); 65 | if (paramExpList != null && paramExpList.size() > 0) { 66 | String name = null; 67 | Object value = null; 68 | 69 | for (ParamExp paramExp : paramExpList) { 70 | if (strValue.equals(paramExp.getExp())) { 71 | name = paramExp.getName(); 72 | value = paramsValueMap.get(name); 73 | 74 | if (value != null && paramExp.getExp().contains("%") && paramExp.getExp().contains("${")) {//处理like查询 75 | value = paramExp.getExp().replace("'", "").replace("${" + name + "}", value.toString()); 76 | paramsValueMap.put(name, value); 77 | } 78 | break; 79 | } 80 | } 81 | 82 | if (name != null && value != null) { 83 | //设置了替换为的标记 84 | this.getBuffer().append(" " + this.mark); 85 | this.paramList.add(name); 86 | 87 | } else { 88 | this.getBuffer().append(Constant.PARAMS_NO_VALUE_FLAG); 89 | } 90 | } else { 91 | this.getBuffer().append(Constant.PARAMS_NO_VALUE_FLAG); 92 | } 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /src/main/java/com/sql/parser/ReplaceParamToNamedParam.java: -------------------------------------------------------------------------------- 1 | package com.sql.parser; 2 | 3 | import com.sql.constant.Constant; 4 | import com.sql.entity.ParamExp; 5 | import net.sf.jsqlparser.expression.StringValue; 6 | import net.sf.jsqlparser.util.deparser.ExpressionDeParser; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | /** 13 | * 替换参数到指定的标记 14 | *

15 | * 替换了Spring NamedParameterJdbcTemplate 查询 16 | *

17 | * 将没有值的参数使用没值标志标记下,将有值的参数替换为 :参数名 18 | */ 19 | public class ReplaceParamToNamedParam extends ExpressionDeParser { 20 | 21 | /** 22 | * SQL中所有的参数 {@link ParamExp } 23 | */ 24 | List paramExpList; 25 | 26 | 27 | /** 28 | * 解析出的参数列表 29 | */ 30 | private List paramList = new ArrayList<>(); 31 | 32 | /** 33 | * 参数对应的值 34 | */ 35 | Map paramsValueMap; 36 | 37 | public ReplaceParamToNamedParam() { 38 | } 39 | 40 | public ReplaceParamToNamedParam(Map paramsValueMap) { 41 | this.paramsValueMap = paramsValueMap; 42 | } 43 | 44 | public ReplaceParamToNamedParam(List paramExpList, Map paramsValueMap) { 45 | this.paramsValueMap = paramsValueMap; 46 | this.paramExpList = paramExpList; 47 | } 48 | 49 | public List getParamList() { 50 | return paramList; 51 | } 52 | 53 | public void setParamList(List paramList) { 54 | this.paramList = paramList; 55 | } 56 | 57 | @Override 58 | public void visit(StringValue stringValue) { 59 | String strValue = stringValue.toString(); 60 | if (paramExpList != null && paramExpList.size() > 0) { 61 | String name = null; 62 | Object value = null; 63 | 64 | for (ParamExp paramExp : paramExpList) { 65 | if (strValue.equals(paramExp.getExp())) { 66 | name = paramExp.getName(); 67 | value = paramsValueMap.get(name); 68 | 69 | //处理like查询 70 | if (value != null && paramExp.getExp().contains("%") && paramExp.getExp().contains("${")) { 71 | value = paramExp.getExp().replace("'", "").replace("${" + name + "}", value.toString()); 72 | paramsValueMap.put(name, value); 73 | } 74 | break; 75 | } 76 | } 77 | if (name != null) { 78 | if (value != null) { 79 | //设置了替换为的标记 80 | this.getBuffer().append(" :" + name); 81 | this.paramList.add(name); 82 | }else{ 83 | this.getBuffer().append(Constant.PARAMS_NO_VALUE_FLAG); 84 | } 85 | } else { 86 | //this.getBuffer().append(Constant.PARAMS_NO_VALUE_FLAG); 87 | this.getBuffer().append(stringValue); 88 | } 89 | } else { 90 | //this.getBuffer().append(Constant.PARAMS_NO_VALUE_FLAG); 91 | this.getBuffer().append(stringValue); 92 | } 93 | } 94 | 95 | 96 | } -------------------------------------------------------------------------------- /src/main/java/com/sql/parser/SQLConditionHandle.java: -------------------------------------------------------------------------------- 1 | package com.sql.parser; 2 | 3 | import com.sql.constant.Constant; 4 | import net.sf.jsqlparser.expression.Expression; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * SQL语句空条件表达式处理 10 | */ 11 | public class SQLConditionHandle { 12 | 13 | /** 14 | * 删除SQL语句中带有空值 15 | * 16 | * @param sql 17 | * @param expressionList 18 | * @return 19 | */ 20 | public static String deleteSQLEmptyFlagCondition(String sql, List expressionList) { 21 | 22 | for (Expression expression : expressionList) { 23 | if (expression.toString().contains(Constant.PARAMS_NO_VALUE_FLAG)) { 24 | //需在条件前加空格,否则sql中有id=Constant.PARAMS_NO_VALUE_FLAG and user_id=Constant.PARAMS_NO_VALUE_FLAG会变成 25 | //1=1 and user_1=1 26 | //加空格保证了是一个查询条件 27 | sql = sql.replace(" " + expression.toString(), " " + Constant.SQL_NO_VALUE_EXPRESSION_REPLACE_FLAG); 28 | } 29 | } 30 | //替换1=1标志 31 | for (String s : Constant.SQL_EXPRESSION_DELETE_FLAG) { 32 | sql = sql.replaceAll(s, ""); 33 | } 34 | 35 | sql = sql.trim(); 36 | //替换所有多余的空格 37 | /*while (sql.indexOf(" ") != -1) { 38 | sql = sql.trim().replaceAll(" ", " "); 39 | }*/ 40 | 41 | //检查是不是 where SQL_NO_VALUE_EXPRESSION_REPLACE_FLAG 结尾 是就删除 42 | if (sql.endsWith(("WHERE " + Constant.SQL_NO_VALUE_EXPRESSION_REPLACE_FLAG).trim())) { 43 | sql = sql.replace(("WHERE " + Constant.SQL_NO_VALUE_EXPRESSION_REPLACE_FLAG).trim(), ""); 44 | } 45 | 46 | //替换 47 | for (String key : Constant.SQL_REPLACE_MAP.keySet()) { 48 | sql = sql.replace(key, Constant.SQL_REPLACE_MAP.get(key)); 49 | } 50 | 51 | //将Constant.PARAMS_NO_VALUE_FLAG替换为空字符串 52 | sql = sql.replace(Constant.PARAMS_NO_VALUE_FLAG, "").trim(); 53 | 54 | return sql; 55 | } 56 | 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/sql/parser/SqlParser.java: -------------------------------------------------------------------------------- 1 | package com.sql.parser; 2 | 3 | import net.sf.jsqlparser.JSQLParserException; 4 | import net.sf.jsqlparser.expression.BinaryExpression; 5 | import net.sf.jsqlparser.expression.Expression; 6 | import net.sf.jsqlparser.expression.Parenthesis; 7 | import net.sf.jsqlparser.expression.StringValue; 8 | import net.sf.jsqlparser.expression.operators.relational.*; 9 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 10 | import net.sf.jsqlparser.schema.Column; 11 | import net.sf.jsqlparser.statement.Statement; 12 | import net.sf.jsqlparser.statement.select.*; 13 | import net.sf.jsqlparser.util.deparser.ExpressionDeParser; 14 | import net.sf.jsqlparser.util.deparser.SelectDeParser; 15 | import net.sf.jsqlparser.util.deparser.StatementDeParser; 16 | 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | public class SqlParser { 22 | 23 | /** 24 | * 删除sql的条件中有指定标志flag的查询条件 25 | * 26 | * @param sql 27 | * @return 28 | */ 29 | public static String deleteEmptyValueCondition(String sql) throws JSQLParserException { 30 | List expressionList = new ArrayList<>(); 31 | Statement statement = CCJSqlParserUtil.parse(sql); 32 | if (statement instanceof Select) { 33 | Select select = (Select) statement; 34 | parseSelectExpression(select.getSelectBody(), expressionList); 35 | 36 | } 37 | String realSql = statement.toString(); 38 | String finalSQL = SQLConditionHandle.deleteSQLEmptyFlagCondition(realSql, expressionList); 39 | return finalSQL; 40 | } 41 | 42 | 43 | /** 44 | * 解析SelectBody中的所有表达式 45 | * 46 | * @param selectBody 47 | * @param expressionList 48 | */ 49 | public static void parseSelectExpression(SelectBody selectBody, List expressionList) { 50 | if (selectBody instanceof PlainSelect) { 51 | PlainSelect plainSelect = (PlainSelect) selectBody; 52 | 53 | //处理where条件 54 | if (plainSelect.getWhere() != null) { 55 | Expression expression = plainSelect.getWhere(); 56 | parseExpression(expression, expressionList); 57 | } 58 | 59 | //处理子查询 60 | if (plainSelect.getFromItem() != null) { 61 | FromItem fromItem = plainSelect.getFromItem(); 62 | if (fromItem instanceof SubSelect) { 63 | SubSelect subSelect = (SubSelect) fromItem; 64 | SelectBody subSelectBody = subSelect.getSelectBody(); 65 | parseSelectExpression(subSelectBody, expressionList); 66 | } else if (fromItem instanceof SubJoin) { 67 | SubJoin subJoin = (SubJoin) fromItem; 68 | List joins = subJoin.getJoinList(); 69 | parseJoinExpression(joins, expressionList); 70 | } 71 | } 72 | 73 | //处理join操作 74 | if (plainSelect.getJoins() != null) { 75 | List joins = plainSelect.getJoins(); 76 | parseJoinExpression(joins, expressionList); 77 | } 78 | } else if (selectBody instanceof SetOperationList) { 79 | List selectBodyList = ((SetOperationList) selectBody).getSelects(); 80 | for (SelectBody selectBody1 : selectBodyList) { 81 | parseSelectExpression(selectBody1, expressionList); 82 | } 83 | 84 | } else { 85 | 86 | } 87 | } 88 | 89 | /** 90 | * 查找最小表达式 91 | * 92 | * @param expression 93 | * @param expressionList 94 | */ 95 | public static void parseExpression(Expression expression, List expressionList) { 96 | //如果是简单的查询表达式 97 | if (expression instanceof BinaryExpression) { 98 | BinaryExpression binaryExpression = (BinaryExpression) expression; 99 | 100 | //左边表达式 101 | Expression leftExpression = binaryExpression.getLeftExpression(); 102 | if (leftExpression instanceof Column) { 103 | expressionList.add(expression); 104 | return; 105 | } 106 | 107 | //右边表达式 108 | Expression rightExpression = binaryExpression.getRightExpression(); 109 | if (rightExpression instanceof StringValue) { 110 | expressionList.add(expression); 111 | return; 112 | } 113 | 114 | parseExpression(leftExpression, expressionList); 115 | parseExpression(rightExpression, expressionList); 116 | } else if (expression instanceof InExpression) { 117 | //处理in 118 | InExpression inExpression = (InExpression) expression; 119 | ItemsList itemsList = inExpression.getRightItemsList(); 120 | 121 | //in是列表 122 | if (itemsList instanceof ExpressionList) { 123 | expressionList.add(expression); 124 | } else if (itemsList instanceof MultiExpressionList) { 125 | MultiExpressionList multiExpressionList = (MultiExpressionList) itemsList; 126 | 127 | List exprList = multiExpressionList.getExprList(); 128 | 129 | for (ExpressionList expressionList1 : exprList) { 130 | List expressions = expressionList1.getExpressions(); 131 | 132 | for (Expression expression1 : expressions) { 133 | parseExpression(expression1, expressionList); 134 | } 135 | } 136 | 137 | 138 | } else if (itemsList instanceof SubSelect) {//in是子查询 139 | SubSelect subSelect = (SubSelect) itemsList; 140 | SelectBody selectBody = subSelect.getSelectBody(); 141 | parseSelectExpression(selectBody, expressionList); 142 | } 143 | 144 | } else if (expression instanceof Between) { 145 | //Between between= (Between) expression; 146 | 147 | expressionList.add(expression); 148 | 149 | } else if (expression instanceof Parenthesis) { 150 | Parenthesis parenthesis = (Parenthesis) expression; 151 | parseExpression(parenthesis.getExpression(), expressionList); 152 | } 153 | } 154 | 155 | 156 | /** 157 | * 解析JOIN表达式 158 | * 159 | * @param joins 160 | * @param expressionList 161 | */ 162 | public static void parseJoinExpression(List joins, List expressionList) { 163 | if (joins == null) { 164 | return; 165 | } 166 | for (Join join : joins) { 167 | FromItem rightItem = join.getRightItem(); 168 | if (rightItem instanceof SubJoin) { 169 | 170 | } else if (rightItem instanceof SubSelect) { 171 | 172 | } 173 | 174 | Expression onExpression = join.getOnExpression(); 175 | if (onExpression != null) { 176 | parseExpression(onExpression, expressionList); 177 | } 178 | } 179 | } 180 | 181 | 182 | public static String replactSqlParams(String sql, Map paramsValueMap) throws JSQLParserException { 183 | StringBuilder buffer = new StringBuilder(); 184 | ExpressionDeParser expr = new ReplaceColumnValues(); 185 | 186 | 187 | SelectDeParser selectDeparser = new SelectDeParser(expr, buffer); 188 | expr.setSelectVisitor(selectDeparser); 189 | expr.setBuffer(buffer); 190 | StatementDeParser stmtDeparser = new StatementDeParser(expr, selectDeparser, buffer); 191 | 192 | Statement stmt = CCJSqlParserUtil.parse(sql); 193 | 194 | stmt.accept(stmtDeparser); 195 | return stmtDeparser.getBuffer().toString(); 196 | } 197 | 198 | 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/com/sql/util/ParamsUtil.java: -------------------------------------------------------------------------------- 1 | package com.sql.util; 2 | 3 | import com.sql.constant.Constant; 4 | import com.sql.entity.ParamExp; 5 | 6 | import java.util.*; 7 | import java.util.regex.Matcher; 8 | import java.util.regex.Pattern; 9 | 10 | /** 11 | * 参数工具 12 | */ 13 | public class ParamsUtil { 14 | 15 | 16 | /** 17 | * 查找str值中指定字符串开头和结尾的所有内容 18 | * 19 | * @param str 20 | * @param regParamsPattern 参数的正则表达式 21 | * @param isDistinct 是否去重 22 | * @return 23 | */ 24 | public static List findAllParams(String str, String[] regParamsPattern, boolean isDistinct) { 25 | if (str == null) { 26 | return null; 27 | } 28 | 29 | List paramExpList = new ArrayList<>(); 30 | 31 | Set paramNameSet = new LinkedHashSet<>(); 32 | for (String s : regParamsPattern) { 33 | Pattern pattern = Pattern.compile(s, Pattern.DOTALL); 34 | Matcher matcher = pattern.matcher(str); 35 | while (matcher.find()) { 36 | 37 | String exp = str.substring(matcher.start(), matcher.end()); 38 | String name = exp.substring(exp.indexOf("{")+1,exp.indexOf("}")); 39 | 40 | if (isDistinct && paramNameSet.contains(name)) { 41 | continue; 42 | } 43 | paramNameSet.add(name); 44 | 45 | 46 | ParamExp paramExp = ParamExp.builder().name(name).exp(exp).build(); 47 | paramExpList.add(paramExp); 48 | } 49 | } 50 | 51 | if (paramExpList.size() > 0) { 52 | return paramExpList; 53 | } 54 | return null; 55 | } 56 | 57 | 58 | /** 59 | * 根据参数paramsValueMap替换str中的参数值 60 | * 61 | * @param str 62 | * @param regParamsPattern 参数的正则表达式 63 | * @param paramsValueMap 64 | * @param noValReplaceStr 在paramsValueMap中没有str中的参数对应的值的代替字符 65 | * @return 66 | */ 67 | public static String replaceAllParams(String str, String[] regParamsPattern, Map paramsValueMap, String noValReplaceStr) { 68 | if (str == null) { 69 | return null; 70 | } 71 | List paramExpList = findAllParams(str, regParamsPattern, true); 72 | if (paramExpList != null && paramExpList.size() >0) { 73 | if (paramsValueMap == null) { 74 | paramsValueMap = new HashMap<>(); 75 | } 76 | for (ParamExp paramExp : paramExpList) { 77 | String paramsName =paramExp.getName(); 78 | String paramsExp="${"+paramsName+"}"; 79 | Object v = paramsValueMap.get(paramsName); 80 | if (v != null) { 81 | str = str.replace(paramsExp, String.valueOf(v)); 82 | } else if (noValReplaceStr != null) { 83 | str = str.replace(paramsExp, noValReplaceStr); 84 | } else { 85 | str = str.replace(paramsExp, ""); 86 | } 87 | } 88 | } 89 | return str; 90 | } 91 | 92 | 93 | public static void main(String[] args) { 94 | 95 | String s = "https://www.baidu.com/s?wd='${name}'&rsv_spt=${id}${1234}${ttt}'"; 96 | Map params = new HashMap<>(); 97 | params.put("name", "缪应江"); 98 | params.put("id", "1098"); 99 | params.put("1234", "AA"); 100 | params.put("ttt", "BB"); 101 | 102 | List list = findAllParams(s, Constant.REG_PARAMS_PATTERN, false); 103 | String v = replaceAllParams(s, Constant.REG_PARAMS_PATTERN, params, ""); 104 | System.out.println(list); 105 | System.out.println(v); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/sql/util/SQLUtil.java: -------------------------------------------------------------------------------- 1 | package com.sql.util; 2 | 3 | import com.sql.constant.Constant; 4 | import com.sql.entity.JdbcTemplateQueryParams; 5 | import com.sql.entity.ParamExp; 6 | import com.sql.parser.ReplaceParamToMark; 7 | import com.sql.parser.ReplaceParamToNamedParam; 8 | import com.sql.parser.SqlParser; 9 | import net.sf.jsqlparser.JSQLParserException; 10 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 11 | import net.sf.jsqlparser.statement.Statement; 12 | import net.sf.jsqlparser.util.deparser.SelectDeParser; 13 | import net.sf.jsqlparser.util.deparser.StatementDeParser; 14 | 15 | import java.util.*; 16 | 17 | /** 18 | * 解析SQL工具类 19 | */ 20 | public class SQLUtil { 21 | 22 | 23 | public static String replaceSQLParams(String sql, Map paramsValueMap) throws JSQLParserException { 24 | if (sql == null || sql.trim().length() < 1) { 25 | return null; 26 | } 27 | 28 | //使用正则表达式替换参数 29 | String sqlEp = ParamsUtil.replaceAllParams(sql, Constant.SQL_MARK_REG_PARAMS_PATTERN, paramsValueMap, Constant.PARAMS_NO_VALUE_FLAG); 30 | //处理SQL 31 | String finalSQL = SqlParser.deleteEmptyValueCondition(sqlEp); 32 | 33 | return finalSQL; 34 | 35 | } 36 | 37 | 38 | public static String replaceSQLParams2(String sql, Map paramsValueMap) throws JSQLParserException { 39 | Map map = new HashMap<>(); 40 | for (String key : paramsValueMap.keySet()) { 41 | map.put(key, paramsValueMap.get(key)); 42 | } 43 | return replaceSQLParams(sql, map); 44 | } 45 | 46 | 47 | /** 48 | * 给SQL参数增加单引号,如果已有单引号则不增加单引号 49 | * 50 | * @param sql 51 | * @return 52 | */ 53 | public static String addSQLParamsSingleQuoteMark(String sql) { 54 | List list = ParamsUtil.findAllParams(sql, Constant.SQL_MARK_REG_PARAMS_PATTERN, false); 55 | if (list != null && list.size() > 0) { 56 | for (ParamExp paramExp : list) { 57 | if (!paramExp.getExp().startsWith("'")) { 58 | String noSingleQuoteMark = "";//不带单引号 59 | String singleQuoteMark = "";//带单引号 60 | 61 | noSingleQuoteMark = "\\$\\{" + paramExp.getName() + "\\}"; 62 | singleQuoteMark = "'\\$\\{" + paramExp.getName() + "\\}'"; 63 | 64 | 65 | //先将带单引号的改为无单引号,再将其该我带单引号的,不能直接改是因为带单引号的会出现两个单引号 66 | sql = sql.replaceAll(singleQuoteMark, noSingleQuoteMark).replaceAll(noSingleQuoteMark, singleQuoteMark); 67 | } 68 | } 69 | } 70 | 71 | return sql; 72 | } 73 | 74 | 75 | /** 76 | * 将SQL转化为Spring jdbcTemplate.queryForList(sql, args, argTypes);方法使用的参数 77 | * 78 | * @param sql 79 | * @param paramsValueMap 80 | * @return 81 | * @throws JSQLParserException 82 | */ 83 | public static JdbcTemplateQueryParams sqlToJdbcTemplateQuery(String sql, Map paramsValueMap) throws JSQLParserException { 84 | String addSingleQuoteSql = addSQLParamsSingleQuoteMark(sql); 85 | List sqlAllParams = ParamsUtil.findAllParams(addSingleQuoteSql, Constant.SQL_MARK_REG_PARAMS_PATTERN, false); 86 | 87 | 88 | StringBuilder buffer = new StringBuilder(); 89 | ReplaceParamToMark replaceParamToMark = new ReplaceParamToMark(" ? ", sqlAllParams, paramsValueMap); 90 | 91 | SelectDeParser selectDeparser = new SelectDeParser(replaceParamToMark, buffer); 92 | replaceParamToMark.setSelectVisitor(selectDeparser); 93 | replaceParamToMark.setBuffer(buffer); 94 | StatementDeParser stmtDeparser = new StatementDeParser(replaceParamToMark, selectDeparser, buffer); 95 | 96 | Statement stmt = CCJSqlParserUtil.parse(addSingleQuoteSql); 97 | stmt.accept(stmtDeparser); 98 | 99 | String markSql = stmtDeparser.getBuffer().toString(); 100 | String finalSQL = SqlParser.deleteEmptyValueCondition(markSql); 101 | 102 | JdbcTemplateQueryParams jdbcTemplateQueryParams = JdbcTemplateQueryParams.builder().paramExpList(sqlAllParams).originalSql(sql).sql(finalSQL).build(); 103 | setAndValuesByArgNames(replaceParamToMark.getParamList(), paramsValueMap, jdbcTemplateQueryParams); 104 | 105 | return jdbcTemplateQueryParams; 106 | 107 | } 108 | 109 | public static JdbcTemplateQueryParams sqlToJdbcTemplateQuery2(String sql, Map paramsValueMap) throws JSQLParserException { 110 | Map map = new HashMap<>(); 111 | for (String key : paramsValueMap.keySet()) { 112 | map.put(key, paramsValueMap.get(key)); 113 | } 114 | return sqlToJdbcTemplateQuery(sql, map); 115 | } 116 | 117 | 118 | /** 119 | * 将SQL转化为Spring jdbcTemplate.queryForList(sql, args, argTypes);方法使用的参数 120 | * 121 | * @param sql 122 | * @param paramsValueMap 123 | * @return 124 | * @throws JSQLParserException 125 | */ 126 | public static JdbcTemplateQueryParams sqlToNamedParameterJdbcTemplateQuery(String sql, Map paramsValueMap) throws JSQLParserException { 127 | String addSingleQuoteSql = addSQLParamsSingleQuoteMark(sql); 128 | List sqlAllParams = ParamsUtil.findAllParams(addSingleQuoteSql, Constant.SQL_MARK_REG_PARAMS_PATTERN, false); 129 | System.out.println("所有参数:"+sqlAllParams); 130 | StringBuilder buffer = new StringBuilder(); 131 | ReplaceParamToNamedParam replaceParamToNamedParam = new ReplaceParamToNamedParam(sqlAllParams, paramsValueMap); 132 | 133 | SelectDeParser selectDeparser = new SelectDeParser(replaceParamToNamedParam, buffer); 134 | replaceParamToNamedParam.setSelectVisitor(selectDeparser); 135 | replaceParamToNamedParam.setBuffer(buffer); 136 | StatementDeParser stmtDeparser = new StatementDeParser(replaceParamToNamedParam, selectDeparser, buffer); 137 | 138 | Statement stmt = CCJSqlParserUtil.parse(addSingleQuoteSql); 139 | stmt.accept(stmtDeparser); 140 | 141 | String markSql = stmtDeparser.getBuffer().toString(); 142 | String finalSQL = SqlParser.deleteEmptyValueCondition(markSql); 143 | 144 | JdbcTemplateQueryParams jdbcTemplateQueryParams = JdbcTemplateQueryParams.builder().paramExpList(sqlAllParams).originalSql(sql).sql(finalSQL).build(); 145 | setAndValuesByArgNames(replaceParamToNamedParam.getParamList(), paramsValueMap, jdbcTemplateQueryParams); 146 | 147 | return jdbcTemplateQueryParams; 148 | } 149 | 150 | private static void setAndValuesByArgNames(List paramNameList, Map paramsValueMap, 151 | JdbcTemplateQueryParams jdbcTemplateQueryParams) { 152 | if (paramNameList != null && paramNameList.size() > 0) { 153 | String[] strings = new String[paramNameList.size()]; 154 | jdbcTemplateQueryParams.setArgNames(paramNameList.toArray(strings)); 155 | 156 | List argValueList = new ArrayList<>(paramNameList.size()); 157 | for (int i = 0; i < paramNameList.size(); i++) { 158 | argValueList.add(paramsValueMap.get(paramNameList.get(i))); 159 | } 160 | 161 | jdbcTemplateQueryParams.setArgValues(argValueList.toArray()); 162 | } 163 | } 164 | 165 | 166 | } 167 | -------------------------------------------------------------------------------- /src/test/java/com/test/Test.java: -------------------------------------------------------------------------------- 1 | package com.test; 2 | 3 | import com.sql.constant.Constant; 4 | import com.sql.entity.JdbcTemplateQueryParams; 5 | import com.sql.util.ParamsUtil; 6 | import com.sql.util.SQLUtil; 7 | import net.sf.jsqlparser.JSQLParserException; 8 | import net.sf.jsqlparser.expression.StringValue; 9 | import net.sf.jsqlparser.expression.operators.relational.EqualsTo; 10 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 11 | import net.sf.jsqlparser.statement.select.PlainSelect; 12 | import net.sf.jsqlparser.statement.select.Select; 13 | import net.sf.jsqlparser.util.deparser.ExpressionDeParser; 14 | import net.sf.jsqlparser.util.deparser.SelectDeParser; 15 | 16 | import java.util.*; 17 | import java.util.regex.Matcher; 18 | import java.util.regex.Pattern; 19 | 20 | 21 | public class Test { 22 | 23 | 24 | public static void main(String[] args) throws JSQLParserException { 25 | //test2(); 26 | test6(); 27 | } 28 | 29 | public static void test1() throws JSQLParserException { 30 | 31 | 32 | //String sql="select * from fact_air_cn fac where dt>${dt} and area in (select DISTINCT city from dim_area_cn where quality like ${quality} ) or area LIKE '${areaLike}' and id in (${idIn}) "; 33 | //String sql = "select * from fact_air_cn fac where dt>${dt} and id in (${idIn}) or a like ${like} "; 34 | //String sql = "select * from rpt_old_cus_apply_d where apply_dt between ${startTime} and ${endTime} "; 35 | //String sql = "select * from bi_app_activate_apply_d where s_dt between ${startTime} and ${endTime} limit 10"; 36 | //String sql = "select ttt.* , case when sms_fail_count > 0 then concat(round((sms_fail_count/sms_count)*100,2) , '%') else null end sms_fail_count_rate from (select send_time , send_type , sum(sms_count) sms_count , sum(sms_success_count) sms_success_count , sum(sms_fail_count) sms_fail_count from (select s.sms_count , s.sms_success_count , s.sms_fail_count , substring(s.send_time , 1,11) send_time , sc.send_type from sms s , sms_content sc where s.sms_content_id=sc.id and s.is_send='Y' AND s.send_time>'2018-01-01' and sc.send_type='${sendType}') as cc group by send_time , send_type ) as ttt order by send_time desc "; 37 | String sql = " select group_concat(distinct name separator '||') from sms where id=${smsId} and tel_upload_id=${tel_upload_id} "; 38 | 39 | sql = "SELECT CONCAT(tb1.classify,tb1.id) id_num , tb1.* ,scc.send_type, \n" + 40 | "packNumberCount , sendNumberCount , noSendNumberCount , \n" + 41 | "packSuccessCount , packFailCount\n" + 42 | "FROM (\n" + 43 | "select tu.id , 'A' classify , tu.telCount totalNumberCount , tu.uploadTelTime createTime, tu.queryFlag\n" + 44 | "from tel_upload tu\n" + 45 | "UNION ALL \n" + 46 | "SELECT lqs.id, 'B' classify , lqs.sms_count totalNumberCount, lqs.create_time createTime, lqs.query_flag queryFlag \n" + 47 | "FROM label_query_his lqs \n" + 48 | "WHERE lqs.app_state='审批通过' \n" + 49 | ") tb1 LEFT JOIN \n" + 50 | "\n" + 51 | "(\n" + 52 | "SELECT id , classify , packNumberCount , \n" + 53 | "sendNumberCount , noSendNumberCount , packSuccessCount , packFailCount FROM (\n" + 54 | "SELECT id , classify , \n" + 55 | "sum(packNumberCount) packNumberCount , sum(sendNumberCount) sendNumberCount ,\n" + 56 | "sum(noSendNumberCount) noSendNumberCount , sum(packSuccessCount) packSuccessCount , \n" + 57 | "sum(packFailCount) packFailCount \n" + 58 | "FROM ( \n" + 59 | "SELECT \n" + 60 | "case when sms.tel_upload_id>0 then sms.tel_upload_id when sms.label_query_id >0 then sms.label_query_id ELSE NULL END id , \n" + 61 | "case when sms.tel_upload_id>0 then 'A' when sms.label_query_id >0 then 'B' ELSE '' END classify , \n" + 62 | "sms.is_send isSend , sms.sms_count packNumberCount ,\n" + 63 | "case WHEN sms.is_send='Y' THEN sms.sms_count ELSE 0 END sendNumberCount , \n" + 64 | "case WHEN sms.is_send='N' THEN sms.sms_count ELSE 0 END noSendNumberCount , \n" + 65 | "sms.sms_success_count packSuccessCount , sms.sms_fail_count packFailCount \n" + 66 | "from sms \n" + 67 | ") ts group by id , classify\n" + 68 | ") sm\n" + 69 | ") tb2 on tb1.id=tb2.id and tb1.classify=tb2.classify \n" + 70 | "LEFT JOIN (\n" + 71 | "select\n" + 72 | "case when tel_upload_id>0 then tel_upload_id when label_query_id >0 then label_query_id ELSE NULL END id , \n" + 73 | "case when tel_upload_id>0 then 'A' when label_query_id >0 then 'B' ELSE '' END classify , \n" + 74 | "send_type\n" + 75 | "from (\n" + 76 | "select DISTINCT scc.tel_upload_id , scc.label_query_id , scc.send_type from sms_content scc\n" + 77 | ") scc\n" + 78 | ") scc on tb1.id=scc.id and tb1.classify=scc.classify \n" + 79 | "where 1=1 \n" + 80 | "and scc.send_type='${sendType}'\n" + 81 | "and CONCAT(tb1.classify,tb1.id)='${idNum}'\n" + 82 | "\n" + 83 | "order by tb1.createTime desc , id desc , classify "; 84 | 85 | 86 | Map params = new HashMap<>(); 87 | params.put("dt", 123); 88 | 89 | String realSql = null; 90 | try { 91 | realSql = SQLUtil.replaceSQLParams(sql, params); 92 | } catch (JSQLParserException e) { 93 | e.printStackTrace(); 94 | } 95 | 96 | //realSql =StringEscapeUtils. 97 | System.out.println("替换前SQL:" + CCJSqlParserUtil.parse(sql)); 98 | System.out.println("替换后SQL:" + realSql); 99 | 100 | 101 | } 102 | 103 | 104 | public static void test2() throws JSQLParserException { 105 | //需要解析的SQL语句 106 | String sql = "select * from user where id=${id} and name='${name}'"; 107 | //参数列表 108 | Map params = new HashMap<>(); 109 | params.put("name", "Myron"); 110 | //解析SQL 111 | String realSql = SQLUtil.replaceSQLParams(sql, params); 112 | System.out.println("原SQL: " + sql); 113 | System.out.println("正则替换参数SQL:" + ParamsUtil.replaceAllParams(sql,Constant.SQL_MARK_REG_PARAMS_PATTERN, params, Constant.PARAMS_NO_VALUE_FLAG)); 114 | System.out.println("解析后SQL: " + realSql); 115 | 116 | 117 | Select select = (Select) CCJSqlParserUtil.parse("select * from a where 1=1"); 118 | PlainSelect plainSelect = (PlainSelect) select.getSelectBody(); 119 | 120 | System.out.println(select); 121 | 122 | } 123 | 124 | public static void test3() throws JSQLParserException { 125 | String sql = "SELECT NAME, ADDRESS, COL1 FROM USER WHERE name=${name} and age=12 and SSN IN ('11111111111111', '22222222222222');"; 126 | Select select = (Select) CCJSqlParserUtil.parse(sql); 127 | //Start of value modification 128 | StringBuilder buffer = new StringBuilder(); 129 | ExpressionDeParser expressionDeParser = new ExpressionDeParser() { 130 | 131 | @Override 132 | public void visit(StringValue stringValue) { 133 | System.out.println(stringValue); 134 | this.getBuffer().append("XXXX"); 135 | } 136 | 137 | 138 | @Override 139 | public void visit(EqualsTo equalsTo) { 140 | System.out.println("EqualsTo******"); 141 | 142 | equalsTo.setASTNode(null); 143 | 144 | // equalsTo.accept(null); 145 | 146 | super.visit(equalsTo); 147 | } 148 | }; 149 | SelectDeParser deparser = new SelectDeParser(expressionDeParser, buffer); 150 | expressionDeParser.setSelectVisitor(deparser); 151 | expressionDeParser.setBuffer(buffer); 152 | select.getSelectBody().accept(deparser); 153 | //End of value modification 154 | 155 | 156 | System.out.println(buffer.toString()); 157 | //Result is: SELECT NAME, ADDRESS, COL1 FROM USER WHERE SSN IN (XXXX, XXXX) 158 | } 159 | 160 | 161 | public static void test4() throws JSQLParserException { 162 | //需要解析的SQL语句 163 | String sql = "select * from user where id=${id} and name='${name}' " + 164 | "and age=${age} and address like ${address} "; 165 | //参数列表 166 | Map params = new HashMap<>(); 167 | params.put("name", "Myron"); 168 | params.put("age", "12"); 169 | 170 | JdbcTemplateQueryParams jdbcTemplateQueryParams = SQLUtil.sqlToJdbcTemplateQuery(sql, params); 171 | 172 | System.out.println("解析前SQL:"+sql); 173 | System.out.println("解析后SQL:"+jdbcTemplateQueryParams.getSql()); 174 | } 175 | 176 | public static void test5() throws JSQLParserException { 177 | //需要解析的SQL语句 178 | String sql = "select * from user where id=${id} and name='${name}' " + 179 | "and age=${age} and address like ${address} and sex in (${sex}) "; 180 | 181 | List sexList=new ArrayList<>(); 182 | sexList.add("男"); 183 | 184 | //参数列表 185 | Map params = new HashMap<>(); 186 | params.put("name", "Myron"); 187 | params.put("age", "12"); 188 | params.put("sex",sexList); 189 | 190 | JdbcTemplateQueryParams jdbcTemplateQueryParams = SQLUtil.sqlToNamedParameterJdbcTemplateQuery(sql, params); 191 | 192 | System.out.println("解析前SQL:"+sql); 193 | System.out.println("解析后SQL:"+jdbcTemplateQueryParams.getSql()); 194 | } 195 | 196 | public static void test6() throws JSQLParserException { 197 | 198 | //需要解析的SQL语句 199 | String sql = "select * from user where id=${id} and name='${name}' and age=${age} and address like '${addrLike}%' and age in (${inAge}) "; 200 | //参数列表 201 | Map params = new HashMap<>(); 202 | params.put("name", "Myron"); 203 | params.put("age", "12"); 204 | params.put("addrLike", "GZ"); 205 | 206 | List inAge = new ArrayList<>(); 207 | inAge.add("1"); 208 | inAge.add("2"); 209 | params.put("inAge", inAge); 210 | 211 | 212 | //JdbcTemplateQueryParams jdbcTemplateQueryParams = SQLUtil.sqlToJdbcTemplateQuery(sql, params); 213 | JdbcTemplateQueryParams jdbcTemplateQueryParams = SQLUtil.sqlToNamedParameterJdbcTemplateQuery(sql, params); 214 | System.out.println("原始SQL:"+sql); 215 | System.out.println("解析SQL:"+jdbcTemplateQueryParams.getSql()); 216 | System.out.println("参数:"+params); 217 | if(jdbcTemplateQueryParams.getArgNames() != null && jdbcTemplateQueryParams.getArgNames().length >0){ 218 | System.out.println("argNames:"); 219 | Arrays.asList(jdbcTemplateQueryParams.getArgNames()).stream().forEach(a -> System.out.println("\t"+a)); 220 | 221 | System.out.println("argValues:"); 222 | Arrays.asList(jdbcTemplateQueryParams.getArgValues()).stream().forEach(a -> System.out.println("\t"+a)); 223 | 224 | } 225 | 226 | } 227 | 228 | 229 | public static void test7(){ 230 | 231 | String str="select * from tb where id=${id} and name like '${nameLike}%' "; 232 | boolean isContainRegExp =true; 233 | boolean isDistinct=false; 234 | List params = new ArrayList<>(); 235 | for (String s :Constant.SQL_MARK_REG_PARAMS_PATTERN) { 236 | Pattern pattern = Pattern.compile(s, Pattern.DOTALL); 237 | Matcher matcher = pattern.matcher(str); 238 | while (matcher.find()) { 239 | String val=null; 240 | if (isContainRegExp) {//包涵正则表达式 241 | String regVal = str.substring(matcher.start(), matcher.end()); 242 | //params.add(regVal); 243 | val=regVal; 244 | } else { 245 | //params.add(matcher.group(1)); 246 | val=matcher.group(1); 247 | } 248 | 249 | if(isDistinct && params.indexOf(val) < 0){ 250 | params.add(val); 251 | }else{ 252 | params.add(val); 253 | } 254 | } 255 | } 256 | 257 | System.out.println(params); 258 | } 259 | 260 | } 261 | -------------------------------------------------------------------------------- /src/test/java/com/test/TestReplaceColumnValues.java: -------------------------------------------------------------------------------- 1 | package com.test; 2 | 3 | import com.sql.entity.JdbcTemplateQueryParams; 4 | import com.sql.parser.ReplaceColumnValues; 5 | import com.sql.parser.ReplaceParamToMark; 6 | import com.sql.parser.SqlParser; 7 | import com.sql.util.ParamsUtil; 8 | import net.sf.jsqlparser.JSQLParserException; 9 | import net.sf.jsqlparser.expression.LongValue; 10 | import net.sf.jsqlparser.expression.StringValue; 11 | import net.sf.jsqlparser.parser.CCJSqlParserUtil; 12 | import net.sf.jsqlparser.statement.Statement; 13 | import net.sf.jsqlparser.util.deparser.ExpressionDeParser; 14 | import net.sf.jsqlparser.util.deparser.SelectDeParser; 15 | import net.sf.jsqlparser.util.deparser.StatementDeParser; 16 | 17 | import java.util.ArrayList; 18 | import java.util.HashMap; 19 | import java.util.List; 20 | 21 | import static com.sql.util.SQLUtil.addSQLParamsSingleQuoteMark; 22 | 23 | public class TestReplaceColumnValues { 24 | 25 | static class ReplaceColumnAndLongValues extends ExpressionDeParser { 26 | 27 | @Override 28 | public void visit(StringValue stringValue) { 29 | System.out.println(stringValue.getValue()); 30 | this.getBuffer().append("?"); 31 | } 32 | 33 | 34 | } 35 | 36 | 37 | public static void main(String[] args) throws JSQLParserException { 38 | 39 | String sql="SELECT 'abc', 5 FROM mytable WHERE col='${test}' and stbS in (${in}) and addr like '%{addrLike}%' and name=#{name} and name2=#{name} and id=12 and age between ${age1} and ${age2} and sex like concat('%',${sex},'%') "; 40 | 41 | 42 | JdbcTemplateQueryParams jdbcTemplateQueryParams = new JdbcTemplateQueryParams(); 43 | 44 | StringBuilder buffer = new StringBuilder(); 45 | ReplaceColumnAndLongValues replaceParamToMark = new ReplaceColumnAndLongValues( ); 46 | 47 | 48 | SelectDeParser selectDeparser = new SelectDeParser(replaceParamToMark, buffer); 49 | replaceParamToMark.setSelectVisitor(selectDeparser); 50 | replaceParamToMark.setBuffer(buffer); 51 | StatementDeParser stmtDeparser = new StatementDeParser(replaceParamToMark, selectDeparser, buffer); 52 | 53 | 54 | String addSingleQuoteSql = addSQLParamsSingleQuoteMark(sql); 55 | Statement stmt = CCJSqlParserUtil.parse(addSingleQuoteSql); 56 | stmt.accept(stmtDeparser); 57 | 58 | String markSql = stmtDeparser.getBuffer().toString(); 59 | 60 | System.out.println(sql); 61 | System.out.println(markSql); 62 | 63 | 64 | 65 | } 66 | } --------------------------------------------------------------------------------