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

来源:互联网 发布:excel03显示重复数据 编辑:程序博客网 时间:2024/05/22 23:34
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 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();nfigure("/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

  hibernate.cfg.xml

  org.hibernate.dialect.SQLServerDialect

  net.sourceforge.jtds.jdbc.Driver

  jdbc:jtds:sqlserver://127.0.0.1:1433;databasename=struts;SelectMethod=cursor

  sa

  sa

  true

  update

  ——>

  创建好数据库后就要利用groovy动态创建访问代码了:先看测试代码再看具体实现:

  public void testGroovy(){

  Form form = formService.get("1");

  List 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 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.sprire.RowMapper import org.sprire.RowMapperResultSetExtractor import re.dao.DataSourceFactory import mons.lang.builder.ToStringBuilder;import mons.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}]

  def int[] types=[Types.VARCHAR,] 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生成表示层页面以及代码来进行展示。


  

原文地址:http://www.educity.cn/java/504830.html


0 0
原创粉丝点击