All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dromara.hutool.db.sql.NamedSql Maven / Gradle / Ivy

There is a newer version: 6.0.0.M3
Show newest version
/*
 * Copyright (c) 2013-2024 Hutool Team and hutool.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.dromara.hutool.db.sql;

import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.text.StrUtil;

import java.util.Collection;
import java.util.Map;

/**
 * 使用命名占位符的SQL,例如:select * from table where field1=:name1
* 支持的占位符格式为: *
 * 1、:name
 * 2、@name
 * 3、?name
 * 
* * @author looly * @since 4.0.10 */ public class NamedSql extends BoundSql { private static final char[] NAME_START_CHARS = {':', '@', '?'}; private final String namedSql; private final Map paramMap; /** * 构造 * * @param namedSql 命名占位符的SQL * @param paramMap 名和参数的对应Map */ public NamedSql(final String namedSql, final Map paramMap) { this.namedSql = namedSql; this.paramMap = paramMap; parse(namedSql, paramMap); } /** * 获取原始地带名称占位符的SQL语句 * * @return 名称占位符的SQL */ public String getNamedSql() { return namedSql; } /** * 获取原始参数名和参数值对应关系参数表 * * @return 参数名和参数值对应关系参数表 */ public Map getParamMap() { return paramMap; } /** * 解析命名占位符的SQL * * @param namedSql 命名占位符的SQL * @param paramMap 名和参数的对应Map */ private void parse(final String namedSql, final Map paramMap) { if (MapUtil.isEmpty(paramMap)) { setSql(namedSql); return; } final int len = namedSql.length(); final StringBuilder name = new StringBuilder(); final StringBuilder sqlBuilder = new StringBuilder(); char c; Character nameStartChar = null; for (int i = 0; i < len; i++) { c = namedSql.charAt(i); if (ArrayUtil.contains(NAME_START_CHARS, c)) { // 新的变量开始符出现,要处理之前的变量 replaceVar(nameStartChar, name, sqlBuilder, paramMap); nameStartChar = c; } else if (null != nameStartChar) { // 变量状态 if (isGenerateChar(c)) { // 变量名 name.append(c); } else { // 非标准字符也非变量开始的字符出现表示变量名结束,开始替换 replaceVar(nameStartChar, name, sqlBuilder, paramMap); nameStartChar = null; sqlBuilder.append(c); } } else { // 变量以外的字符原样输出 sqlBuilder.append(c); } } // 收尾,如果SQL末尾存在变量,处理之 if (name.length() > 0) { replaceVar(nameStartChar, name, sqlBuilder, paramMap); } setSql(sqlBuilder.toString()); } /** * 替换变量,如果无变量,原样输出到SQL中去 * * @param nameStartChar 变量开始字符 * @param name 变量名 * @param sqlBuilder 结果SQL缓存 * @param paramMap 变量map(非空) */ private void replaceVar(final Character nameStartChar, final StringBuilder name, final StringBuilder sqlBuilder, final Map paramMap) { if (name.length() == 0) { if (null != nameStartChar) { // 类似于:的情况,需要补上: sqlBuilder.append(nameStartChar); } // 无变量,按照普通字符处理 return; } // 变量结束 final String nameStr = name.toString(); if (paramMap.containsKey(nameStr)) { // 有变量对应值(值可以为null),替换占位符为?,变量值放入相应index位置 Object paramValue = paramMap.get(nameStr); if ((paramValue instanceof Collection || ArrayUtil.isArray(paramValue)) && StrUtil.containsIgnoreCase(sqlBuilder, "in")) { if (paramValue instanceof Collection) { // 转为数组 paramValue = ((Collection) paramValue).toArray(); } // 可能为select in (xxx)语句,则拆分参数为多个参数,变成in (?,?,?) final int length = ArrayUtil.length(paramValue); for (int i = 0; i < length; i++) { if (0 != i) { sqlBuilder.append(','); } sqlBuilder.append('?'); addParam(ArrayUtil.get(paramValue, i)); } } else { sqlBuilder.append('?'); addParam(paramValue); } } else { // 无变量对应值,原样输出 sqlBuilder.append(nameStartChar).append(name); } //清空变量,表示此变量处理结束 name.setLength(0); } /** * 是否为标准的字符,包括大小写字母、下划线和数字 * * @param c 字符 * @return 是否标准字符 */ private static boolean isGenerateChar(final char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9'); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy