利用JAVA动态编译重构系统
一个信息系统查询必不可少,如果是定制化的开发那么查询语句还可能是经常变动的;IBATIS提供了这样的sql配置查询的功能;这里有另一种解决方案:利用JAVA动态编译的方式实现SQL语句的配置化!
?
SQL的拼装有时候会很复杂,这个时候如何使用IBATIS的话,就不得不深入学习他的语法,对于新手来说上手就变得困难啦。如果有一种方案可以配置SQL在XML文件中,同时又使用JAVA的语法来拼SQL,那该多好。
?
?
利用JAVA动态编译的方式实现SQL语句的配置化!!!
?
/** * 编译文件 * * @param file * @throws Exception */private String compileFile(File file) throws Exception {String classPath = getClassPath();String[] arg = {"-classpath", classPath, "-d", classPath,file.getAbsolutePath() };StringWriter writer = new StringWriter(1024);int code = com.sun.tools.javac.Main.compile(arg,new PrintWriter(writer));return code == 0 ? "0" : writer.toString();}/** * 创建实例 * * @param file * @return * @throws Exception */private SqlBuilder createInstance(File file) throws Exception {String filename = file.getName();String classname = filename.substring(0, filename.lastIndexOf('.'));return (SqlBuilder) Class.forName(packageName + "." + classname).newInstance();}/** * 删除临时文件 * * @param file * @throws Exception */private void removeTempFile(File file) throws Exception {String classDir = getClassDir();int last = file.getName().lastIndexOf('.');String name = file.getName().substring(0, last);String classFile = classDir + File.pathSeparator + name + ".java";String javaFile = classDir + File.pathSeparator + name + ".class";new File(javaFile).delete();new File(classFile).delete();}/** * 取得Class路径 * * @return */private String getClassPath() {//URL url = this.getClass().getResource("/");URL url = Thread.currentThread().getContextClassLoader().getResource("/");File file = new File(url.getPath());return file.getAbsolutePath();}/** * 生成 JAVA代码片段 * @param classname * @param sqlCode * @return */private String getJavaCode (String classname ,String sqlCode ){StringBuffer code = new StringBuffer(1024);code.append("\npackage " + packageName + "; \n");code.append("public class " + classname + " implements "+ superClass + "{\n");code.append(" public String getSql(java.util.Map map) throws Exception{ \n");code.append(" " + sqlCode + " \n");// 兼容配置中有return语句的SQLif (!sqlCode.contains("return ")) {code.append(" return sql.toString();\n");}code.append(" }\n");code.append("}\n");return code.toString();}/** * 取得Java路径 * * @return */private String getClassDir() {return getClassPath() + "/" + packageName;}/** * 验证 JAVA语法 * @param sqlCode * @return * @throws Exception */public String validateJavaCode ( String sqlCode) throws Exception {log.info("################ Class Dir[" + getClassDir()+ "] #################");File file = createFile(sqlCode);String classname = file.getName().substring(0, file.getName().lastIndexOf('.'));try {Debug debug = new Debug("Dyna Complie");debug.start("ComplieFile");String result = compileFile(file);if (!"0".equals(result)) {// 保存错误信息return "语法验证不通过:\n【\n" + getJavaCode(classname,sqlCode) + "\n】\n"+"验证信息如下:\n【\n" + result + "\n】\n";}debug.end("ComplieFile");log.info(debug);return "语法验证通过:\n【\n" + getJavaCode(classname,sqlCode) + "\n】\n" ;} catch (Exception e) {log.error(e);return ("\n【\n" + getJavaCode(classname,sqlCode) + "\n】\n");} finally {removeTempFile(file);}}?