动态表单及动态建表实现原理
生活随笔
收集整理的這篇文章主要介紹了
动态表单及动态建表实现原理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
? 1 應用場景
? 項目中往往需要動態的創建一個表單,或者添加一個新的數據模板,這時候因為需要在運行時動態的創建表以及動態的維護表字段甚至表關系 使得普通java解決方案變得困難重重。?
????2 實現工具
Hibernate + Spring + Groovy +Freemarker
Hibernate 作用很簡單負責創建數據庫表這樣可以避免我們自己去寫復雜的sql和判斷。
Spring 作為橋梁起到連接紐帶的作用。
Groovy做為動態語言,在項目運行時根據模板創建訪問數據庫,或者控制層代碼。
Freamker 可以根據提前定義好的模板生成 hibernate配置文件,以及Groovy代碼。
?????3?實現原理
??首先創建Form 和 FromAttribute 兩張表關系一對多。Form表記錄表單的名稱,類別,甚至是作為在動態生成表單時的css樣式信息。FromAttribute記錄表單字段信息,如名稱,類別等。有了表單以及表單項的信息后就可以創建數據庫表了。
測試代碼:public?void?testGenerator()?{
????????Form?form?=?formService.getAll().get(0);
????????List<FormAttribute>?list?=?formAttributeService
????????????????.getAttributeListByFormId(form.getId());
????????form.setFormAttributeList(list);
????????DbGenerator?dg?=?new?DbGenerator(form,?dataSource);
????????dg.generator();
????}
DbGenerator
import?java.io.IOException;
import?java.io.StringWriter;
import?java.io.Writer;
import?java.sql.SQLException;
import?java.util.HashMap;
import?java.util.Map;
import?java.util.Properties;
import?javax.sql.DataSource;
import?org.hibernate.tool.hbm2ddl.SchemaExport;
import?org.slf4j.Logger;
import?org.slf4j.LoggerFactory;
import?freemarker.template.Configuration;
import?freemarker.template.Template;
import?freemarker.template.TemplateException;
public?class?DbGenerator?{
????
????private?DataSource?dataSource;
????protected?Map?root?=?new?HashMap();
????private?static?Logger?log?=?LoggerFactory.getLogger(FormGenerator.class);
????protected?String?path;
????protected?String?packageName;
????private?Form?form;
????protected?Configuration?getConfig(String?resource)?{
????????Configuration?cfg?=?new?Configuration();
????????cfg.setDefaultEncoding("UTF-8");
????????cfg.setClassForTemplateLoading(this.getClass(),?resource);
????????return?cfg;
????}
????public?DbGenerator(Form?form?,DataSource?dataSource)?{
????????this.form?=?form;
????????this.dataSource?=?dataSource;
????}
????public?void?generator()?{
????????if(null?==?form.getFormAttributeList()?||?form.getFormAttributeList().size()?==?0){
????????????return?;
????????}
????????Template?t;
????????try?{
????????????t?=?getConfig("/template").getTemplate("hibernate.ftl");
????????????Writer?out?=?new?StringWriter();
????????????t.process(getMapContext(),?out);
????????????String?xml?=?out.toString();
????????????createTable(xml);
????????????log.debug(xml);
????????}?catch?(IOException?e)?{
????????????e.printStackTrace();
????????}?catch?(TemplateException?e)?{
????????????e.printStackTrace();
????????}
????}
????@SuppressWarnings("unchecked")
????Map?getMapContext()?{
????????root.put("entity",?form);
????????return?root;
????}
????public?void?createTable(String?xml)?{
????????org.hibernate.cfg.Configuration?conf?=?new?org.hibernate.cfg.Configuration();
????????conf.configure("/hibernate/hibernate.cfg.xml");
????????Properties?extraProperties?=?new?Properties();
????????extraProperties.put("hibernate.hbm2ddl.auto",?"create");
????????conf.addProperties(extraProperties);
????????conf.addXML(xml);
????????SchemaExport?dbExport;
????????try?{
????????????dbExport?=?new?SchemaExport(conf,?dataSource.getConnection());
????????????//?dbExport.setOutputFile(path);
????????????dbExport.create(false,?true);
????????}?catch?(SQLException?e)?{
????????????//?TODO?Auto-generated?catch?block
????????????e.printStackTrace();
????????}
????}
}
class?hibernateGenerator?{
} hibernate.ftl
<?xml?version="1.0"?encoding="UTF-8"?>
<!DOCTYPE?hibernate-mapping?
??PUBLIC?"-//Hibernate/Hibernate?Mapping?DTD?3.0//EN"
?????????"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
????<class
????????name="${entity.name}"
????????table="`${entity.tableName}`"
????????dynamic-update="false"
????????dynamic-insert="false"
????????select-before-update="false"
????????optimistic-lock="version">
????????<id
????????????name="id"
????????????column="id"
????????????type="java.lang.String"
????????????unsaved-value="null">
????????????<generator?class="uuid"?/>
????????</id>
????????<#if?entity.formAttributeList?exists>
????????????<#list?entity.formAttributeList?as?attr>
????????????????<#if?attr.name?==?"id">????????????????
????????????????<#else>
????????<property
????????????name="${attr.name}"
????????????type="java.lang.String"
????????????update="true"
????????????insert="true"
????????????access="property"
????????????column="`${attr.columnName}`"
????????????length="${attr.length}"
????????????not-null="false"
????????????unique="false"
????????/>
????????
????????????????</#if>
????????????</#list>
????????</#if>
???????
????</class>
</hibernate-mapping>
hibernate.cfg.xml
<!DOCTYPE?hibernate-configuration
????PUBLIC?"-//Hibernate/Hibernate?Configuration?DTD?3.0//EN"
????"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
????????<property?name="dialect">org.hibernate.dialect.SQLServerDialect</property>
????<property?name="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
????<property?name="connection.url">jdbc:jtds:sqlserver://127.0.0.1:1433;databasename=struts;SelectMethod=cursor</property>
????<property?name="connection.username">sa</property>
????<property?name="connection.password">sa</property>
????
????<property?name="show_sql">true</property>
????<property?name="hibernate.hbm2ddl.auto">update</property>
<!--??
????<mapping?resource="hibernate/FormAttribute.hbm.xml"?/>
????<mapping?resource="hibernate/Form.hbm.xml"?/>
????-->
</session-factory>
</hibernate-configuration> ? 創建好數據庫后 就要利用groovy動態創建訪問代碼了:先看測試代碼 再看具體實現:
public?void?testGroovy()?{
????????Form?form?=?formService.get("1");
????????List<FormAttribute>?list?=?formAttributeService
????????????????.getAttributeListByFormId(form.getId());
????????form.setFormAttributeList(list);
????????FormGenerator?fg?=?new?FormGenerator(form);
????????String?groovycode?=?fg.generator();
????????ClassLoader?parent?=?getClass().getClassLoader();
????????GroovyClassLoader?loader?=?new?GroovyClassLoader(parent);
????????Class?groovyClass?=?loader.parseClass(groovycode);
????????GroovyObject?groovyObject?=?null;
????????try?{
????????????groovyObject?=?(GroovyObject)?groovyClass.newInstance();
????????}?catch?(InstantiationException?e)?{
????????????e.printStackTrace();
????????}?catch?(IllegalAccessException?e)?{
????????????e.printStackTrace();
????????}
????????//?map中key為formAttribute中描述該表單字段在數據庫中的名稱c_columnName
????????//?具體情況根據formAttribute而定
????????Map?map?=?new?HashMap();
????????map.put("name",?"limq");
????????//?調用insert方法插入數據
????????int?c?=?(Integer)?groovyObject.invokeMethod("insert",?map);
????????//?調用getAll方法獲得所有動態表中的數據
????????Object?o?=?groovyObject.invokeMethod("getAll",?null);
????????List?list2?=?(List)?o;
????????Object?obj?=?list2.get(0);
????????try?{
????????????String?tname?=?(String)?BeanUtils.getDeclaredProperty(obj,?"name");
????????????System.out.println(tname);
????????}?catch?(IllegalAccessException?e)?{
????????????e.printStackTrace();
????????}?catch?(NoSuchFieldException?e)?{
????????????e.printStackTrace();
????????}
????????//?調用search方法查詢動態表
????????List<Map>?returnList?=?(List)?groovyObject.invokeMethod("search",?map);
????????for?(Map?map2?:?returnList)?{
????????????//?同理此處根據FromAttribute而定
????????????System.out.println(map2.get("id"));
????????????System.out.println(map2.get("name"));
????????????System.out.println(map2.get("type"));
????????}
????} FormGenerator : 創建訪問數據庫Groovy代碼
public?class?FormGenerator?{
????protected??Map?root?=?new?HashMap();
????private?static?Logger?log?=?LoggerFactory.getLogger(FormGenerator.class);
????????protected?String?path?;
????????protected?String?packageName?;
????????private?Form?form?;?
????????protected?Configuration?getConfig(String?resource)?{
????????????
?????????????Configuration?cfg?=?new?Configuration();
????????????cfg.setDefaultEncoding("UTF-8");
????????????cfg.setClassForTemplateLoading(this.getClass(),?resource);
????????????return?cfg;
????????}
????????
????????public?FormGenerator(Form?form){
????????????this.form?=?form;
????????}
????????
????????public?String?generator(){
????????????String?returnstr?=?null;
????????????Template?t;
????????????try?{
????????????????t?=?getConfig("/template").getTemplate("FormService.ftl");
????????????????//Writer?out?=?new?OutputStreamWriter(new?FileOutputStream(new?File(path)),"UTF-8");
????????????????Writer?out?=?new?StringWriter();
????????????????t.process(getMapContext(),?out);
????????????????returnstr?=?out.toString();
????????????????log.debug(returnstr);
????????????}?catch?(IOException?e)?{
????????????????e.printStackTrace();
????????????}?catch?(TemplateException?e)?{
????????????????e.printStackTrace();
????????????}
????????????return?returnstr;
????????}
????????
????????@SuppressWarnings("unchecked")
????????Map?getMapContext()?{
????????????root.put("entity",?form);
????????????root.put("insert",?SqlHelper.buildInsertStatement(form));
????????????root.put("update",?SqlHelper.buildUpdateStatement(form));
????????????
????????????root.put("insertParameter",?SqlHelper.buildInsertparameter(form));
????????????root.put("updateParameter",?SqlHelper.buildUpdateparameter(form));
????????????
????????????root.put("delete",?SqlHelper.buildDeleteStatement(form));
????????????root.put("query",??SqlHelper.buildQueryStatement(form));????
????????????return?root;
????????}
} FormService.ftl
import?java.sql.ResultSet
import?java.sql.SQLException
import?java.sql.Types?
import?org.springframework.jdbc.core.RowMapper
import?org.springframework.jdbc.core.RowMapperResultSetExtractor
import?com.glnpu.sige.core.dao.DataSourceFactory
import?org.apache.commons.lang.builder.ToStringBuilder;
import?org.apache.commons.lang.builder.ToStringStyle;
class?${entity.name?cap_first}Dao?{
?????def?insert?=?'${insert}'
?????def?delete?=?'${delete}'
?????def?update?=?'${update}'
?????def?int?insert(?entity){
????????def?Object[]?params?=?[${insertParameter}]
????????<#assign?size?=?entity.formAttributeList?size/>
????????def?int[]?types=[<#list?1..size+1?as?p>Types.VARCHAR,<#rt/></#list>]
????????return?DataSourceFactory.getJdbcTemplate().update(insert,?params,?types)
????}
?????def?int?update(?entity){
????????def?Object[]?params?=?[${updateParameter}]
????????return?DataSourceFactory.getJdbcTemplate().update(update,?params)
????}
?????def?int?delete(String?entityId){
????????def?Object[]?params?=[entityId]
????????return?DataSourceFactory.getJdbcTemplate().update(delete,?params)
????}
????def?search(entity){
????????${query}
????????println(query);
????????return?DataSourceFactory.getJdbcTemplate().queryForList(query);
????????
????}
????
}
?
????以上代碼示意了如何利用 freemarker 生成 Groovy?和 hibernate 相關代碼,以及如何利用Groovy動態的對數據庫進行創建和增刪改查操作,了解以上的原理后就可以方便的在運行時利用freemarker生成表示層頁面以及代碼來進行展示。
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!
總結
以上是生活随笔為你收集整理的动态表单及动态建表实现原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux系统:Centos7下搭建Cl
- 下一篇: 父窗口控制子窗口的行为-打开,关闭,重定