JFinal SQL脚本插件

//SQLScriptPlugin JFinal插件类
//SQL脚本目录:/WEB-INF/sql-script
public class SQLScriptPlugin implements IPlugin {
	
	private static final Log log = Log.getLog(SQLScriptPlugin.class);
	
	private static final String LOADPATH = PathKit.getWebRootPath()
			+ File.separator + "WEB-INF" + File.separator + "sql-script";

	public SQLScriptPlugin() {
		try {
			File file = new File(LOADPATH);
			if(!file.exists()) {
				file.mkdirs();
			}
			SQLScript.init(new File(LOADPATH));
		} catch (IOException e) {
			log.error("SQLScriptPlugin Load Fail");
			log.error(ErrorKit.toString(e));
		}
	}

	@Override
	public boolean start() {
		return true;
	}

	@Override
	public boolean stop() {
		return true;
	}
}
//SQLScript 核心类主要完成语句的解析功能
//加载文件需要依赖apache.commons.io
public class SQLScript {

	private static Pattern SQLID_REG = Pattern.compile("(?:^/[*][+][*]\\s+[(])([\\w.]+)(?:[)]\\s+[*][+][*]/$)");
	
	private static Pattern SQLKEY_REG = Pattern.compile("(?<=(?:^|[^\\w@:?]))[@:?]([\\w]+)(?=(?:[^\\w@:?]|$))");
	
	private static Pattern SPLITIN_REG = Pattern.compile("(?<=\\bin\\b)(?:\\s*[(]\\s*)[@:?]([\\w]+)(?:\\s*[)])", 
			Pattern.CASE_INSENSITIVE);
	
	private static Pattern REPLACE_REG = Pattern.compile("(?<=(?:^|\\s))#INS#(?=(?:\\s|$))",
			Pattern.CASE_INSENSITIVE);
	
	private static String[] EXTENSIONS = new String[] { "sql", "SQL" };
	
	private static Map<String, String> SQL_MAP = new HashMap<String, String>();
	
	private SQLScript() {}
	
	public static synchronized void init(File input) throws IOException {
		SQL_MAP.clear();
		Collection<File> sqlFiles = FileUtils.listFiles(input, EXTENSIONS, true);
		
		if (sqlFiles != null && sqlFiles.size() > 0) {
			for (File file : sqlFiles) {
				List<String> lines = FileUtils.readLines(file, "UTF-8");
				
				String sql_id = null;
				boolean append = false;
				StringBuilder sql = null;
				
				if (lines != null && lines.size() > 0) {
					for (int i = 0; i < lines.size(); i++) {
						String line = lines.get(i);
						if (line == null) continue;

						Matcher matcher = SQLID_REG.matcher(line.trim());
						if (matcher.matches()) {
							if (sql_id != null && sql != null) {
								if (!StrKit.isBlank(sql.toString())) {
									if (SQL_MAP.containsKey(sql_id)) {
										throw new RuntimeException("脚本加载异常: 存在相同的SQL_ID: " + sql_id);
									}
									SQL_MAP.put(sql_id, sql.toString().trim());
									append = false;
								}
							}
							
							sql_id = matcher.group(1);
							sql = new StringBuilder();
							append = true;
							
						} else if (append) {
							sql.append(line).append("\r\n");
						}
						
						if (lines.size() == i + 1) {
							if (sql_id != null && sql != null) {
								if (!StrKit.isBlank(sql.toString())) {
									if (SQL_MAP.containsKey(sql_id)) {
										throw new RuntimeException("脚本加载异常: 存在相同的SQL_ID: " + sql_id);
									}
									SQL_MAP.put(sql_id, sql.toString().trim());
									append = false;
								}
							}
						}
					}
				}
			}
		}
	}
	
	public static synchronized void load(File input) throws IOException {
		List<String> lines = FileUtils.readLines(input, "UTF-8");
		
		String sql_id = null;
		boolean append = false;
		StringBuilder sql = null;
		
		if (lines != null && lines.size() > 0) {
			for (int i = 0; i < lines.size(); i++) {
				String line = lines.get(i);
				if (line == null) continue;

				Matcher matcher = SQLID_REG.matcher(line.trim());
				if (matcher.matches()) {
					if (sql_id != null && sql != null) {
						if (!StrKit.isBlank(sql.toString())) {
							SQL_MAP.put(sql_id, sql.toString().trim());
							append = false;
						}
					}
					
					sql_id = matcher.group(1);
					sql = new StringBuilder();
					append = true;
					
				} else if (append) {
					sql.append(line).append("\r\n");
				}
				
				if (lines.size() == i + 1) {
					if (sql_id != null && sql != null) {
						if (!StrKit.isBlank(sql.toString())) {
							SQL_MAP.put(sql_id, sql.toString().trim());
							append = false;
						}
					}
				}
			}
		}
	}

	public static SQLBean parse(String sqlid) {
		return parse(sqlid, null, null);
	}
	
	public static SQLBean parse(String sqlid, String replace) {
		return parse(sqlid, replace, null);
	}

	public static SQLBean parse(String sqlid, SQLParam param) {
		return parse(sqlid, null, param);
	}
	
	public static SQLBean parse(String sqlid, String replace, SQLParam params) {
		String sqlText = SQL_MAP.get(sqlid);
		if (StrKit.isBlank(sqlText)) {
			return null;
		}

		Matcher matcher = REPLACE_REG.matcher(sqlText);
		if (matcher.find()) {
			if (StrKit.isBlank(replace)) {
				sqlText = matcher.replaceAll("");
			} else {
				sqlText = matcher.replaceAll(replace);
			}
		}

		matcher = SQLKEY_REG.matcher(sqlText);
		Map<String, Integer> psmap = null;
		List<Object> value = null;

		if (params != null) {
			while (matcher.find()) {
				if (value == null) {
					value = new ArrayList<Object>();
				}
				String key = matcher.group(1);
				Object val = params.get(key);

				if (val instanceof Object[]) {
					if (psmap == null) {
						psmap = new HashMap<String, Integer>();
					}
					Object[] obj = (Object[]) val;
					psmap.put(key, obj.length);
					if (obj.length > 0) {
						for (Object item : obj) {
							value.add(item);
						}
					} else {
						value.add(null);
					}
				} else if (val instanceof List) {
					if (psmap == null) {
						psmap = new HashMap<String, Integer>();
					}
					List<?> obj = (List<?>) val;
					psmap.put(key, obj.size());
					if (obj.size() > 0) {
						for (Object item : obj) {
							value.add(item);
						}
					} else {
						value.add(null);
					}
				} else {
					value.add(val);
				}
			}
		}
		
		if (psmap != null) {
			matcher = SPLITIN_REG.matcher(sqlText);
			while (matcher.find()) {
				String key = matcher.group(1);
				String str = inSqlString(psmap.get(key));
				sqlText = matcher.replaceFirst(str);
				matcher = matcher.reset(sqlText);
			}
			matcher = SQLKEY_REG.matcher(sqlText);
		}

		String sql = matcher.replaceAll("?");
		if (value == null) {
			return new SQLBean(sql.trim(), new Object[0]);
		}
		return new SQLBean(sql.trim(), value.toArray());
	}
	
	public static SQLBean parseSql(String sqlText) {
		return parseSql(sqlText, null);
	}
	
	public static SQLBean parseSql(String sqlText, SQLParam params) {
		Matcher matcher = SQLKEY_REG.matcher(sqlText);
		Map<String, Integer> psmap = null;
		List<Object> value = null;

		if (params != null) {
			while (matcher.find()) {
				if (value == null) {
					value = new ArrayList<Object>();
				}
				String key = matcher.group(1);
				Object val = params.get(key);

				if (val instanceof Object[]) {
					if (psmap == null) {
						psmap = new HashMap<String, Integer>();
					}
					Object[] obj = (Object[]) val;
					psmap.put(key, obj.length);
					if (obj.length > 0) {
						for (Object item : obj) {
							value.add(item);
						}
					} else {
						value.add(null);
					}
				} else if (val instanceof List) {
					if (psmap == null) {
						psmap = new HashMap<String, Integer>();
					}
					List<?> obj = (List<?>) val;
					psmap.put(key, obj.size());
					if (obj.size() > 0) {
						for (Object item : obj) {
							value.add(item);
						}
					} else {
						value.add(null);
					}
				} else {
					value.add(val);
				}
			}
		}
		
		if (psmap != null) {
			matcher = SPLITIN_REG.matcher(sqlText);
			while (matcher.find()) {
				String key = matcher.group(1);
				String str = inSqlString(psmap.get(key));
				sqlText = matcher.replaceFirst(str);
				matcher = matcher.reset(sqlText);
			}
			matcher = SQLKEY_REG.matcher(sqlText);
		}

		String sql = matcher.replaceAll("?");
		if (value == null) {
			return new SQLBean(sql.trim(), new Object[0]);
		}
		return new SQLBean(sql.trim(), value.toArray());
	}
	
	public static String getSqlString(String sqlid) {
		SQLBean bean = parse(sqlid, null, null);
		if (bean != null) {
			return bean.sql;
		}
		return null;
	}
	
	public static String getSqlString(String sqlid, String replace) {
		SQLBean bean = parse(sqlid, replace, null);
		if (bean != null) {
			return bean.sql;
		}
		return null;
	}
	
	public static String getSqlString(String sqlid, SQLParam params) {
		SQLBean bean = parse(sqlid, null, params);
		if (bean != null) {
			return bean.sql;
		}
		return null;
	}
	
	public static String getSqlString(String sqlid, String replace, SQLParam params) {
		SQLBean bean = parse(sqlid, replace, params);
		if (bean != null) {
			return bean.sql;
		}
		return null;
	}
	
	public static String getSqlSource(String sqlid) {
		return SQL_MAP.get(sqlid);
	}

	private static String inSqlString(Integer size) {
		if (size == null || size == 0) {
			return " (?)";
		}
		StringBuffer sb = new StringBuffer();
		sb.append(" (");
		for (int i = 0; i < size; i++) {
			if (i > 0) sb.append(", ");
			sb.append("?");
		}
		sb.append(")");
		return sb.toString();
	}
}
//SQLBean 解析后生成的对象
public class SQLBean implements Serializable {
	private static final long serialVersionUID = 1L;
	
	public String sql;
	public Object[] params;
	
	public SQLBean() {}

	public SQLBean(String sql, Object[] params) {
		this.sql = sql;
		this.params = params;
	}

	@Override
	public String toString() {
		return "{\r\n" + sql + ";\r\n" + Arrays.toString(params) + "\r\n}";
	}
}
//SQLParam 绑定参数传入对象
public class SQLParam implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private Map<String, Object> columns = new HashMap<String, Object>();
	
	public SQLParam() {}

	public SQLParam(String key, Object value) {
		set(key, value);
	}
	
	public SQLParam(Map<String, Object> columns) {
		setColumns(columns);
	}
	
	public Map<String, Object> getColumns() {
		return columns;
	}
	
	public SQLParam setColumns(Map<String, Object> columns) {
		getColumns().putAll(columns);
		return this;
	}
	
	public SQLParam set(String column, Object value) {
		getColumns().put(column, value);
		return this;
	}
	
	@SuppressWarnings("unchecked")
	public <T> T get(String column) {
		return (T)getColumns().get(column);
	}
	
	@SuppressWarnings("unchecked")
	public <T> T get(String column, Object defaultValue) {
		Object result = getColumns().get(column);
		return (T)(result != null ? result : defaultValue);
	}
}
//使用方法
SQLBean bean1 = SQLScript.parse("Test.sql_1", "order by 1,2,3");
System.out.println(bean1);
Db.find(bean1.sql, 110100, 110100, 1);
		
SQLBean bean2 = SQLScript.parse("Test.sql_2", "order by 1,2,3", 
                new SQLParam("id", 110100).set("status", 1));
System.out.println(bean2);
Db.find(bean2.sql, bean2.params);
		
SQLBean bean3 = SQLScript.parse("Test.sql_3", "order by 1,2,3", 
                new SQLParam("id", new Object[]{110100,110200,110300}).set("status", 1));
System.out.println(bean3);
Db.find(bean2.sql, bean2.params);
/WEB-INF/sql-script/Test.sql 

/*+* (Test.sql_1) *+*/
select t.* 
from g_area t
where t.id = ?
  and t.parent_id <> ?
#INS#


/*+* (Test.sql_2) *+*/
select t.* 
from g_area t
where t.id = :id
  and t.parent_id <> :id
  and t.status = :status
#INS#


/*+* (Test.sql_3) *+*/
select t.* 
from g_area t
where t.id in (:id)
  and t.parent_id not in (:id)
  and t.status = :status
#INS#


//脚本文件格式说明:
1、/*+* (sqlid) *+*/ 
每条SQL以这样的格式作为开头(注意括号外面有空格),
括号里面的sqlid是sql语句的唯一标识。

2、@id、:id、?id 命名参数占位符
绑定变量参数占位符,支持以上3种

3、#INS# 文本替换占位符
可以在调用语句时追加额外语句进来


你可能感兴趣的:(JFinal SQL脚本插件)