1 应用场景
项目中往往需要动态的创建一个表单,或者添加一个新的数据模板,这时候因为需要在运行时动态的创建表以及动态的维护表字段甚至表关系 使得普通java解决方案变得困难重重。
2 实现工具
Hibernate + Spring + Groovy +Freemarker
Hibernate 作用很简单负责创建数据库表这样可以避免我们自己去写复杂的sql和判断。
Spring 作为桥梁起到连接纽带的作用。
Groovy做为动态语言,在项目运行时根据模板创建访问数据库,或者控制层代码。
Freamker 可以根据提前定义好的模板生成 hibernate配置文件,以及Groovy代码。
3实现原理
首先创建Form 和 FromAttribute 两张表关系一对多。Form表记录表单的名称,类别,甚至是作为在动态生成表单时的css样式信息。FromAttribute记录表单字段信息,如名称,类别等。有了表单以及表单项的信息后就可以创建数据库表了。
测试代码:
publicvoidtestGenerator()
{
Formform=formService.getAll().get(0);
List<FormAttribute>list=formAttributeService
.getAttributeListByFormId(form.getId());
form.setFormAttributeList(list);
DbGeneratordg=newDbGenerator(form,dataSource);
dg.generator();
}

importjava.io.IOException;
importjava.io.StringWriter;
importjava.io.Writer;
importjava.sql.SQLException;
importjava.util.HashMap;
importjava.util.Map;
importjava.util.Properties;
importjavax.sql.DataSource;
importorg.hibernate.tool.hbm2ddl.SchemaExport;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;


importfreemarker.template.Configuration;
importfreemarker.template.Template;
importfreemarker.template.TemplateException;

publicclassDbGenerator
{
privateDataSourcedataSource;
protectedMaproot=newHashMap();
privatestaticLoggerlog=LoggerFactory.getLogger(FormGenerator.class);
protectedStringpath;
protectedStringpackageName;
privateFormform;

protectedConfigurationgetConfig(Stringresource)
{
Configurationcfg=newConfiguration();
cfg.setDefaultEncoding("UTF-8");
cfg.setClassForTemplateLoading(this.getClass(),resource);
returncfg;
}

publicDbGenerator(Formform,DataSourcedataSource)
{
this.form=form;
this.dataSource=dataSource;
}

publicvoidgenerator()
{
if(null==form.getFormAttributeList()||form.getFormAttributeList().size()==0)
{
return;
}
Templatet;
try
{
t=getConfig("/template").getTemplate("hibernate.ftl");
Writerout=newStringWriter();
t.process(getMapContext(),out);
Stringxml=out.toString();
createTable(xml);
log.debug(xml);
}catch(IOExceptione)
{
e.printStackTrace();
}catch(TemplateExceptione)
{
e.printStackTrace();
}
}
@SuppressWarnings("unchecked")
MapgetMapContext()
{
root.put("entity",form);
returnroot;
}

publicvoidcreateTable(Stringxml)
{
org.hibernate.cfg.Configurationconf=neworg.hibernate.cfg.Configuration();
conf.configure("/hibernate/hibernate.cfg.xml");
PropertiesextraProperties=newProperties();
extraProperties.put("hibernate.hbm2ddl.auto","create");
conf.addProperties(extraProperties);
conf.addXML(xml);
SchemaExportdbExport;
try
{
dbExport=newSchemaExport(conf,dataSource.getConnection());
//dbExport.setOutputFile(path);
dbExport.create(false,true);
}catch(SQLExceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}

classhibernateGenerator
{
}
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEhibernate-mapping
PUBLIC"-//Hibernate/HibernateMappingDTD3.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">
<generatorclass="uuid"/>
</id>
<#ifentity.formAttributeList?exists>
<#listentity.formAttributeListasattr>
<#ifattr.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>
<!DOCTYPEhibernate-configuration
PUBLIC"-//Hibernate/HibernateConfigurationDTD3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<propertyname="dialect">org.hibernate.dialect.SQLServerDialect</property>
<propertyname="connection.driver_class">net.sourceforge.jtds.jdbc.Driver</property>
<propertyname="connection.url">jdbc:jtds:sqlserver://127.0.0.1:1433;databasename=struts;SelectMethod=cursor</property>
<propertyname="connection.username">sa</property>
<propertyname="connection.password">sa</property>
<propertyname="show_sql">true</property>
<propertyname="hibernate.hbm2ddl.auto">update</property>
<!--
<mappingresource="hibernate/FormAttribute.hbm.xml"/>
<mappingresource="hibernate/Form.hbm.xml"/>
-->
</session-factory>
</hibernate-configuration>

publicvoidtestGroovy()
{
Formform=formService.get("1");
List<FormAttribute>list=formAttributeService
.getAttributeListByFormId(form.getId());
form.setFormAttributeList(list);
FormGeneratorfg=newFormGenerator(form);
Stringgroovycode=fg.generator();
ClassLoaderparent=getClass().getClassLoader();
GroovyClassLoaderloader=newGroovyClassLoader(parent);
ClassgroovyClass=loader.parseClass(groovycode);
GroovyObjectgroovyObject=null;
try
{
groovyObject=(GroovyObject)groovyClass.newInstance();
}catch(InstantiationExceptione)
{
e.printStackTrace();
}catch(IllegalAccessExceptione)
{
e.printStackTrace();
}
//map中key为formAttribute中描述该表单字段在数据库中的名称c_columnName
//具体情况根据formAttribute而定
Mapmap=newHashMap();
map.put("name","limq");
//调用insert方法插入数据
intc=(Integer)groovyObject.invokeMethod("insert",map);
//调用getAll方法获得所有动态表中的数据
Objecto=groovyObject.invokeMethod("getAll",null);
Listlist2=(List)o;
Objectobj=list2.get(0);
try
{
Stringtname=(String)BeanUtils.getDeclaredProperty(obj,"name");
System.out.println(tname);
}catch(IllegalAccessExceptione)
{
e.printStackTrace();
}catch(NoSuchFieldExceptione)
{
e.printStackTrace();
}
//调用search方法查询动态表
List<Map>returnList=(List)groovyObject.invokeMethod("search",map);
for(Mapmap2:returnList)
{
//同理此处根据FromAttribute而定
System.out.println(map2.get("id"));
System.out.println(map2.get("name"));
System.out.println(map2.get("type"));
}
}


publicclassFormGenerator
{
protectedMaproot=newHashMap();
privatestaticLoggerlog=LoggerFactory.getLogger(FormGenerator.class);
protectedStringpath;
protectedStringpackageName;
privateFormform;
protectedConfigurationgetConfig(Stringresource)
{
Configurationcfg=newConfiguration();
cfg.setDefaultEncoding("UTF-8");
cfg.setClassForTemplateLoading(this.getClass(),resource);
returncfg;
}

publicFormGenerator(Formform)
{
this.form=form;
}

publicStringgenerator()
{
Stringreturnstr=null;
Templatet;
try
{
t=getConfig("/template").getTemplate("FormService.ftl");
//Writerout=newOutputStreamWriter(newFileOutputStream(newFile(path)),"UTF-8");
Writerout=newStringWriter();
t.process(getMapContext(),out);
returnstr=out.toString();
log.debug(returnstr);
}catch(IOExceptione)
{
e.printStackTrace();
}catch(TemplateExceptione)
{
e.printStackTrace();
}
returnreturnstr;
}
@SuppressWarnings("unchecked")
MapgetMapContext()
{
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));
returnroot;
}
}
importjava.sql.ResultSet
importjava.sql.SQLException
importjava.sql.Types
importorg.springframework.jdbc.core.RowMapper
importorg.springframework.jdbc.core.RowMapperResultSetExtractor
importcom.glnpu.sige.core.dao.DataSourceFactory
importorg.apache.commons.lang.builder.ToStringBuilder;
importorg.apache.commons.lang.builder.ToStringStyle;

class$
{entity.name?cap_first}Dao
{
definsert='${insert}'
defdelete='${delete}'
defupdate='${update}'
defintinsert(entity)
{
defObject[]params=[$
{insertParameter}]
<#assignsize=entity.formAttributeList?size/>
defint[]types=[<#list1..size+1asp>Types.VARCHAR,<#rt/></#list>]
returnDataSourceFactory.getJdbcTemplate().update(insert,params,types)
}
defintupdate(entity)
{
defObject[]params=[$
{updateParameter}]
returnDataSourceFactory.getJdbcTemplate().update(update,params)
}
defintdelete(StringentityId)
{
defObject[]params=[entityId]
returnDataSourceFactory.getJdbcTemplate().update(delete,params)
}

defsearch(entity)
{
$
{query}
println(query);
returnDataSourceFactory.getJdbcTemplate().queryForList(query);
}
}
以上代码示意了如何利用 freemarker 生成 Groovy和 hibernate 相关代码,以及如何利用Groovy动态的对数据库进行创建和增删改查操作,了解以上的原理后就可以方便的在运行时利用freemarker生成表示层页面以及代码来进行展示。
本文介绍了一种使用Hibernate、Spring、Groovy和Freemarker在Java项目中动态创建表单和数据库表的方法,并展示了如何利用Groovy进行动态的数据库操作。
1983

被折叠的 条评论
为什么被折叠?



