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

cn.hutool.db.sql.NamedSql Maven / Gradle / Ivy

Go to download

Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。

There is a newer version: 5.8.34
Show newest version
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;
import java.util.List;
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 { private static final char[] NAME_START_CHARS = {':', '@', '?'}; private String sql; private final List params; /** * 构造 * * @param namedSql 命名占位符的SQL * @param paramMap 名和参数的对应Map */ public NamedSql(String namedSql, Map paramMap) { this.params = new LinkedList<>(); parse(namedSql, paramMap); } /** * 获取SQL * * @return SQL */ public String getSql() { return this.sql; } /** * 获取参数列表,按照占位符顺序 * * @return 参数数组 */ public Object[] getParams() { return this.params.toArray(new Object[0]); } /** * 获取参数列表,按照占位符顺序 * * @return 参数列表 */ public List getParamList() { return this.params; } /** * 解析命名占位符的SQL * * @param namedSql 命名占位符的SQL * @param paramMap 名和参数的对应Map */ private void parse(String namedSql, Map paramMap) { if(MapUtil.isEmpty(paramMap)){ this.sql = namedSql; return; } final int len = namedSql.length(); final StrBuilder name = StrUtil.strBuilder(); final StrBuilder sqlBuilder = StrUtil.strBuilder(); 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 (false == name.isEmpty()) { 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 paramMap){ if(name.isEmpty()){ if(null != nameStartChar){ // 类似于:的情况,需要补上: sqlBuilder.append(nameStartChar); } // 无变量,按照普通字符处理 return; } // 变量结束 final String nameStr = name.toString(); if(paramMap.containsKey(nameStr)) { // 有变量对应值(值可以为null),替换占位符为?,变量值放入相应index位置 final Object paramValue = paramMap.get(nameStr); if(ArrayUtil.isArray(paramValue) && StrUtil.containsIgnoreCase(sqlBuilder, "in")){ // 可能为select in (xxx)语句,则拆分参数为多个参数,变成in (?,?,?) final int length = ArrayUtil.length(paramValue); for (int i = 0; i < length; i++) { if(0 != i){ sqlBuilder.append(','); } sqlBuilder.append('?'); this.params.add(ArrayUtil.get(paramValue, i)); } } else{ sqlBuilder.append('?'); this.params.add(paramValue); } } else { // 无变量对应值,原样输出 sqlBuilder.append(nameStartChar).append(name); } //清空变量,表示此变量处理结束 name.clear(); } /** * 是否为标准的字符,包括大小写字母、下划线和数字 * * @param c 字符 * @return 是否标准字符 */ private static boolean isGenerateChar(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9'); } }