|
|
@@ -1,6 +1,8 @@
|
|
|
package cn.hutool.db.sql;
|
|
|
|
|
|
+import cn.hutool.core.map.MapUtil;
|
|
|
import cn.hutool.core.text.StrBuilder;
|
|
|
+import cn.hutool.core.util.ArrayUtil;
|
|
|
import cn.hutool.core.util.StrUtil;
|
|
|
|
|
|
import java.util.LinkedList;
|
|
|
@@ -12,8 +14,8 @@ import java.util.Map;
|
|
|
* 支持的占位符格式为:
|
|
|
* <pre>
|
|
|
* 1、:name
|
|
|
- * 2、?name
|
|
|
- * 3、@name
|
|
|
+ * 2、@name
|
|
|
+ * 3、?name
|
|
|
* </pre>
|
|
|
*
|
|
|
* @author looly
|
|
|
@@ -21,6 +23,8 @@ import java.util.Map;
|
|
|
*/
|
|
|
public class NamedSql {
|
|
|
|
|
|
+ private static final char[] NAME_START_CHARS = {':', '@', '?'};
|
|
|
+
|
|
|
private String sql;
|
|
|
private final List<Object> params;
|
|
|
|
|
|
@@ -69,6 +73,11 @@ public class NamedSql {
|
|
|
* @param paramMap 名和参数的对应Map
|
|
|
*/
|
|
|
private void parse(String namedSql, Map<String, Object> paramMap) {
|
|
|
+ if(MapUtil.isEmpty(paramMap)){
|
|
|
+ this.sql = namedSql;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
int len = namedSql.length();
|
|
|
|
|
|
final StrBuilder name = StrUtil.strBuilder();
|
|
|
@@ -77,52 +86,67 @@ public class NamedSql {
|
|
|
Character nameStartChar = null;
|
|
|
for (int i = 0; i < len; i++) {
|
|
|
c = namedSql.charAt(i);
|
|
|
- if (c == ':' || c == '@' || c == '?') {
|
|
|
+ if (ArrayUtil.contains(NAME_START_CHARS, c)) {
|
|
|
nameStartChar = c;
|
|
|
+
|
|
|
+ // 新的变量开始符出现,要处理之前的变量
|
|
|
+ replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
|
|
} else if (null != nameStartChar) {
|
|
|
// 变量状态
|
|
|
if (isGenerateChar(c)) {
|
|
|
// 变量名
|
|
|
name.append(c);
|
|
|
} else {
|
|
|
- // 变量结束
|
|
|
- String nameStr = name.toString();
|
|
|
- if(paramMap.containsKey(nameStr)) {
|
|
|
- // 有变量对应值(值可以为null),替换占位符
|
|
|
- final Object paramValue = paramMap.get(nameStr);
|
|
|
- sqlBuilder.append('?');
|
|
|
- this.params.add(paramValue);
|
|
|
- } else {
|
|
|
- // 无变量对应值,原样输出
|
|
|
- sqlBuilder.append(nameStartChar).append(name);
|
|
|
- }
|
|
|
+ // 非标准字符也非变量开始的字符出现表示变量名结束,开始替换
|
|
|
+ replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
|
|
nameStartChar = null;
|
|
|
- name.clear();
|
|
|
sqlBuilder.append(c);
|
|
|
}
|
|
|
} else {
|
|
|
+ // 变量以外的字符原样输出
|
|
|
sqlBuilder.append(c);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 收尾,如果SQL末尾存在变量,处理之
|
|
|
if (false == name.isEmpty()) {
|
|
|
- // SQL结束依旧有变量名存在,说明变量位于末尾
|
|
|
- final Object paramValue = paramMap.get(name.toString());
|
|
|
- if (null != paramValue) {
|
|
|
- // 有变量对应值,替换占位符
|
|
|
- sqlBuilder.append('?');
|
|
|
- this.params.add(paramValue);
|
|
|
- } else {
|
|
|
- // 无变量对应值,原样输出
|
|
|
- sqlBuilder.append(nameStartChar).append(name);
|
|
|
- }
|
|
|
- name.clear();
|
|
|
+ replaceVar(nameStartChar, name, sqlBuilder, paramMap);
|
|
|
}
|
|
|
|
|
|
this.sql = sqlBuilder.toString();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * 替换变量,如果无变量,原样输出到SQL中去
|
|
|
+ *
|
|
|
+ * @param nameStartChar 变量开始字符
|
|
|
+ * @param name 变量名
|
|
|
+ * @param sqlBuilder 结果SQL缓存
|
|
|
+ * @param paramMap 变量map(非空)
|
|
|
+ */
|
|
|
+ private void replaceVar(Character nameStartChar, StrBuilder name, StrBuilder sqlBuilder, Map<String, Object> paramMap){
|
|
|
+ if(name.isEmpty()){
|
|
|
+ // 无变量,按照普通字符处理
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 变量结束
|
|
|
+ final String nameStr = name.toString();
|
|
|
+ if(paramMap.containsKey(nameStr)) {
|
|
|
+ // 有变量对应值(值可以为null),替换占位符为?,变量值放入相应index位置
|
|
|
+ final Object paramValue = paramMap.get(nameStr);
|
|
|
+ sqlBuilder.append('?');
|
|
|
+ this.params.add(paramValue);
|
|
|
+ } else {
|
|
|
+ // 无变量对应值,原样输出
|
|
|
+ sqlBuilder.append(nameStartChar).append(name);
|
|
|
+ }
|
|
|
+
|
|
|
+ //清空变量,表示此变量处理结束
|
|
|
+ name.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* 是否为标准的字符,包括大小写字母、下划线和数字
|
|
|
*
|
|
|
* @param c 字符
|