<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    limq

    rainman
    隨筆 - 19, 文章 - 2, 評論 - 115, 引用 - 1
    數據加載中……

    動態表單及動態建表實現原理

     

        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生成表示層頁面以及代碼來進行展示。

    posted on 2009-09-19 21:12 limq 閱讀(8536) 評論(4)  編輯  收藏 所屬分類: 編程技巧

    評論

    # re: 動態表單及動態建表實現原理  回復  更多評論   

    有時間試試 我們公司也有表單定義 但是確實在開發過程中使用
    正式發布后不能定義表單了
    沒有多態性可言
    2009-09-19 23:06 | wangchangbing

    # re: 動態表單及動態建表實現原理  回復  更多評論   

    表、代碼生成其實不難,關鍵點就是Groovy避免了熱部署問題
    2009-09-20 08:54 | 路人甲

    # re: 動態表單及動態建表實現原理  回復  更多評論   

    sdkf睡得很死都會發生地方
    2009-09-20 11:39 | 99讀書人

    # re: 動態表單及動態建表實現原理[未登錄]  回復  更多評論   

    這個解決方案非常好。
    2010-04-27 18:21 | adam
    主站蜘蛛池模板: 老汉色老汉首页a亚洲| 亚洲伊人久久大香线蕉在观| 一级做a爱过程免费视频高清| 国产男女猛烈无遮挡免费视频网站| 亚洲色偷精品一区二区三区| 成人免费视频小说| 亚洲第一se情网站| 亚洲人成电影网站国产精品| 国产特黄特色的大片观看免费视频| 亚洲精品美女久久777777| 日韩电影免费观看| 亚洲喷奶水中文字幕电影| 性一交一乱一视频免费看| 羞羞漫画登录页面免费| 亚洲中文字幕久久精品无码喷水 | 337P日本欧洲亚洲大胆精品| 婷婷综合缴情亚洲狠狠尤物| 成在线人免费无码高潮喷水| 亚洲人成影院在线| 免费无码AV片在线观看软件| 无码天堂亚洲国产AV| 亚洲欧洲∨国产一区二区三区| 99久在线国内在线播放免费观看| 中文字幕亚洲综合久久综合| 亚洲高清成人一区二区三区 | 亚洲中文字幕无码日韩| 91精品免费不卡在线观看| 亚洲人成网站在线在线观看| 亚洲精品一级无码鲁丝片| 99久久99久久精品免费观看 | 免费不卡在线观看AV| 亚洲真人无码永久在线观看| 亚洲人成网站在线观看青青| 69av免费观看| 国产亚洲精品成人久久网站| 无码专区—VA亚洲V天堂| 岛国大片免费在线观看| 久久一区二区三区免费| 麻豆狠色伊人亚洲综合网站 | 免费国产va在线观看| 精品亚洲成AV人在线观看|