应用场景 项目中往往需要动态的创建一个表单或者添加一个新的数据模板这时候因为需要在运行时动态的创建表以及动态的维护表字段甚至表关系 使得普通java解决方案变得困难重重 实现工具 Hibernate + Spring + Groovy +Freemarker Hibernate 作用很简单负责创建数据库表这样可以避免我们自己去写复杂的sql和判断 Spring 作为桥梁起到连接纽带的作用 Groovy做为动态语言在项目运行时根据模板创建访问数据库或者控制层代码 Freamker 可以根据提前定义好的模板生成 hibernate配置文件以及Groovy代码 实现原理 首先创建Form 和 FromAttribute 两张表关系一对多Form表记录表单的名称类别甚至是作为在动态生成表单时的css样式信息FromAttribute记录表单字段信息如名称类别等有了表单以及表单项的信息后就可以创建数据库表了 测试代码 public void testGenerator(){ Form form = formServicegetAll()get() List list = formAttributeService getAttributeListByFormId(formgetId())formsetFormAttributeList(list)DbGenerator dg = new DbGenerator(form dataSource)dggenerator() } DbGenerator import javaioIOExceptionimport javaioStringWriterimport javaioWriterimport javasqlSQLExceptionimport javautilHashMapimport javautilMapimport javautilProperties import javaxsqlDataSource import orghibernatetoolhbmddlSchemaExportimport orgslfjLoggerimport orgslfjLoggerFactory import freemarkertemplateConfigurationimport freemarkertemplateTemplateimport freemarkertemplateTemplateException public class DbGenerator { private DataSource dataSource protected Map root = new HashMap() private static Logger log = LoggerFactorygetLogger(FormGeneratorclass) protected String path protected String packageName private Form form protected Configuration getConfig(String resource){ Configuration cfg = new Configuration() cfgsetDefaultEncoding(UTF)cfgsetClassForTemplateLoading(thisgetClass() resource) return cfg } public DbGenerator(Form form DataSource dataSource) { thisform = formthisdataSource = dataSource } public void generator(){ if(null == formgetFormAttributeList() || formgetFormAttributeList()size() == ){ return } Template t try { t = getConfig(/template)getTemplate(hibernateftl) Writer out = new StringWriter() tprocess(getMapContext() out)String xml = outtoString() createTable(xml) logdebug(xml) } catch(IOException e){ eprintStackTrace() } catch(TemplateException e){ eprintStackTrace() } @SuppressWarnings(unchecked) Map getMapContext(){ rootput(entity form) return root } public void createTable(String xml){ orghibernatecfgConfiguration conf = new orghibernatecfgConfiguration()nfigure(/hibernate/hibernatecfgxml) Properties extraProperties = new Properties() extraPropertiesput(hibernatehbmddlauto create)confaddProperties(extraProperties) confaddXML(xml) SchemaExport dbExport try { dbExport = new SchemaExport(conf dataSourcegetConnection())// dbExportsetOutputFile(path)dbExportcreate(false true) } catch(SQLException e){ // TODO Autogenerated catch block eprintStackTrace() } } class hibernateGenerator { }hibernateftl hibernatecfgxml orghibernatedialectSQLServerDialect netsourceforgejtdsjdbcDriver jdbcjtdssqlserver://databasename=strutsSelectMethod=cursor sa sa true update ——> 创建好数据库后就要利用groovy动态创建访问代码了先看测试代码再看具体实现 public void testGroovy(){ Form form = formServiceget() List list = formAttributeService getAttributeListByFormId(formgetId())formsetFormAttributeList(list) FormGenerator fg = new FormGenerator(form) String groovycode = fggenerator()ClassLoader parent = getClass()getClassLoader() GroovyClassLoader loader = new GroovyClassLoader(parent) Class groovyClass = loaderparseClass(groovycode) GroovyObject groovyObject = null try { groovyObject = (GroovyObject) groovyClassnewInstance() } catch(InstantiationException e){ eprintStackTrace() } catch(IllegalAccessException e){ eprintStackTrace() } // map中key为formAttribute中描述该表单字段在数据库中的名称c_columnName //具体情况根据formAttribute而定 Map map = new HashMap() mapput(name limq) //调用insert方法插入数据 int c = (Integer) groovyObjectinvokeMethod(insert map) //调用getAll方法获得所有动态表中的数据 Object o = groovyObjectinvokeMethod(getAll null) List list =(List)o Object obj = listget() try { String tname = (String) BeanUtilsgetDeclaredProperty(obj name)Systemoutprintln(tname) } catch(IllegalAccessException e){ eprintStackTrace() } catch(NoSuchFieldException e){ eprintStackTrace() } //调用search方法查询动态表 List returnList = (List) groovyObjectinvokeMethod(search map) for(Map mapreturnList){ //同理此处根据FromAttribute而定 Systemoutprintln(mapget(id))Systemoutprintln(mapget(name))Systemoutprintln(mapget(type)) } }FormGenerator创建访问数据库Groovy代码 public class FormGenerator { protected Map root = new HashMap() private static Logger log = LoggerFactorygetLogger(FormGeneratorclass) protected String path protected String packageName private Form form protected Configuration getConfig(String resource){ Configuration cfg = new Configuration() cfgsetDefaultEncoding(UTF)cfgsetClassForTemplateLoading(thisgetClass() resource) return cfg } public FormGenerator(Form form){ thisform = form } public String generator(){ String returnstr = null Template t try { t = getConfig(/template)getTemplate(FormServiceftl)//Writer out = new OutputStreamWriter(new FileOutputStream(new File(path))UTF) Writer out = new StringWriter() tprocess(getMapContext() out)returnstr = outtoString()logdebug(returnstr) } catch(IOException e){ eprintStackTrace() } catch(TemplateException e){ eprintStackTrace() } return returnstr } @SuppressWarnings(unchecked) Map getMapContext(){ rootput(entity form)rootput(insert SqlHelperbuildInsertStatement(form))rootput(update SqlHelperbuildUpdateStatement(form)) rootput(insertParameter SqlHelperbuildInsertparameter(form))rootput(updateParameter SqlHelperbuildUpdateparameter(form)) rootput(delete SqlHelperbuildDeleteStatement(form))rootput(query SqlHelperbuildQueryStatement(form)) return root } }FormServiceftl import javasqlResultSet import javasqlSQLException import javasqlTypes import orgsprireRowMapper import orgsprireRowMapperResultSetExtractor import redaoDataSourceFactory import monslangbuilderToStringBuilderimport monslangbuilderToStringStyle class ${entityname?cap_first}Dao { def insert = ${insert} def delete = ${delete} def update = ${update} def int insert(entity){ def Object[] params = [${insertParameter}] def int[] types=[TypesVARCHAR] return DataSourceFactorygetJdbcTemplate()update(insert params types) } def int update(entity){ def Object[] params = [${updateParameter}] return DataSourceFactorygetJdbcTemplate()update(update params) } def int delete(String entityId){ def Object[] params =[entityId] return DataSourceFactorygetJdbcTemplate()update(delete params) } def search(entity){ ${query} println(query) return DataSourceFactorygetJdbcTemplate()queryForList(query) } } 以上代码示意了如何利用 freemarker 生成 Groovy 和 hibernate 相关代码以及如何利用Groovy动态的对数据库进行创建和增删改查操作了解以上的原理后就可以方便的在运行时利用freemarker生成表示层页面以及代码来进行展示 |