动态表单及动态建表实现原理

               

  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(falsetrue);
        }
 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生成表示层页面以及代码来进行展示。
           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/fswhwd/article/details/87630646