//SQLScriptPlugin JFinal插件类//SQL脚本目录:/WEB-INF/sql-scriptpublic 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.iopublic 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 MapSQL_MAP = new HashMap (); private SQLScript() {} public static synchronized void init(File input) throws IOException { SQL_MAP.clear(); Collection sqlFiles = FileUtils.listFiles(input, EXTENSIONS, true); if (sqlFiles != null && sqlFiles.size() > 0) { for (File file : sqlFiles) { List 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 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 psmap = null; List
//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 Mapcolumns = new HashMap (); public SQLParam() {} public SQLParam(String key, Object value) { set(key, value); } public SQLParam(Map columns) { setColumns(columns); } public Map getColumns() { return columns; } public SQLParam setColumns(Map columns) { getColumns().putAll(columns); return this; } public SQLParam set(String column, Object value) { getColumns().put(column, value); return this; } @SuppressWarnings("unchecked") public T get(String column) { return (T)getColumns().get(column); } @SuppressWarnings("unchecked") public 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 twhere t.id = ? and t.parent_id <> ?#INS#/*+* (Test.sql_2) *+*/select t.* from g_area twhere t.id = :id and t.parent_id <> :id and t.status = :status#INS#/*+* (Test.sql_3) *+*/select t.* from g_area twhere 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# 文本替换占位符可以在调用语句时追加额外语句进来