日期:2014-05-16  浏览次数:20458 次

让DbUtils支持NamedParameter方式的sql
DbUtils代码很精悍,很多中小型项目都用它来编写持久层,但是不够强大,平时用习惯了spring jdbc的NamedParameter方式的sql(形如:select * from user where name=:name),总觉得还缺点功能,干脆仿照spring jdbc写个类似的sql处理方法,造个小小小轮子,代码留念:
import java.util.ArrayList;
import java.util.List;

/**
 * 此类封装NamedParameterSql
 * 
 * @author zl
 *
 */
public class ParsedSql {
	
	private String originalSql;
	//参数名
	private List<String> paramNames = new ArrayList<String>();
	//参数在sql中对应的位置
	private List<int[]> paramIndexs = new ArrayList<int[]>();
	//统计参数个数(不包含重复)
	private int namedParamCount;
	//统计sql中?的个数
	private int unnamedParamCount;
	
	private int totalParamCount;
	
	public ParsedSql(String originalSql){
		this.originalSql = originalSql;
	}
	
	public List<String> getParamNames() {
		return paramNames;
	}

	public void addParamNames(String paramName,int startIndex,int endIndex) {
		paramNames.add(paramName);
		paramIndexs.add(new int[]{startIndex,endIndex});
	}

	public int[] getParamIndexs(int position) {
		return paramIndexs.get(position);
	}


	public String getOriginalSql() {
		return originalSql;
	}

	
	public int getNamedParamCount() {
		return namedParamCount;
	}

	public void setNamedParamCount(int namedParamCount) {
		this.namedParamCount = namedParamCount;
	}

	public int getUnnamedParamCount() {
		return unnamedParamCount;
	}

	public void setUnnamedParamCount(int unnamedParamCount) {
		this.unnamedParamCount = unnamedParamCount;
	}

	public int getTotalParamCount() {
		return totalParamCount;
	}

	public void setTotalParamCount(int totalParamCount) {
		this.totalParamCount = totalParamCount;
	}

	public String toString(){
		return this.originalSql;
	}

}


sql处理工具类
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 带参数sql处理工具类
 * 
 * @author zl
 *
 */
public class NamedParameterUtils {
	
	//定义特殊字符(参考spring jdbc N多)
	private static final char[] PARAMETER_SEPARATORS =
		new char[] {'"', '\'', ':', '&', ',', ';', '(', ')', '|', '=', '+', '-', '*', '%', '/', '\\', '<', '>', '^'};
	
	
	/**
	 * 对带参数sql的统计式封装,便于后续肢解拼装(恐怖啊。。。。。)
	 * @param originalSql
	 * @return
	 */
	public static ParsedSql parserSqlStatement(String originalSql) {
		ParsedSql parsedSql = new ParsedSql(originalSql);
		Set<String> paramNames = new HashSet<String>();
		char[] sqlchars = originalSql.toCharArray();
		int namedParamCount = 0;
		int unNamedParamCount = 0;
		int totalParamCount = 0;
		int i = 0;
		while(i<sqlchars.length){
			char statement = sqlchars[i];
			if(statement==':'||statement=='&'){
				int j = i+1;
				while(j<sqlchars.length&&!isSeparatorsChar(sqlchars[j])){
					j++;
				}
				if(j-i>1){
					String paramName = originalSql.substring(i+1, j);
					if(!paramNames.contains(paramName)){
						paramNames.add(paramName);
						namedParamCount++;
					}
					parsedSql.addParamNames(paramName, i, j);
					totalParamCount++;
				}
				i=j-1;
			}else if(statement=='?'){
				unNamedParamCount++;
				totalParamCount++;
			}
			i++;
		}
		parsedSql.setNamedParamCount(namedParamCount);
		parsedSql.setUnnamedParamCount(unNamedParamCount);
		parsedSql.setTotalParamCount(totalParamCount);
		return parsedSql;
	}
	
	/**
	 * 获得不带参数的sql,即替换参数为?
	 * @param parsedSql
	 * @param params
	 * @return
	 */
	public static String substituteNamedParams(ParsedSql parsedSql,Map<String,Object> params){
		String original =parsedSql.getOriginalSql();
		StringBuffer actual = new StringBuffer("");
		int lastIndex = 0;
		List<String> paramNames = parsedSql.getParamNames();
		for(int i=0;i<paramNames.size();i++){
			int[] indexs = parsedSql.getParamIndexs(i);
			int startIndex = indexs[0];
			int endIndex = indexs[1];
			String paramName = paramNames.get(i);
			actual.append(original.substring(lastIndex, startIndex));
			if(params!=null&&params.containsKey(paramName)){
//				if(){}