在許多專案中,使用者需在運行時動態建立表單、新增資料模板,甚至動態維護資料表欄位與關聯關係。傳統 Java 靜態實體類難以應對此類需求,因此需要一套動態建表與代碼生成機制。
建立兩張表 Form(表單主檔)與 FormAttribute(表單欄位),一對多關係。Form 記錄表單名稱、分類、CSS 樣式等;FormAttribute 記錄欄位名稱、型別、長度等屬性。
核心類 DbGenerator 協調整個過程:
Form 及其關聯的 FormAttribute 列表。hibernate.ftl 模板,將元資料填入產生 Hibernate 映射 XML。SchemaExport 工具根據映射 XML 在資料庫建立實體表。// 關鍵代碼片段
public void generator() {
Template t = getConfig("/template").getTemplate("hibernate.ftl");
Writer out = new StringWriter();
t.process(getMapContext(), out);
String xml = out.toString();
createTable(xml);
}
public void createTable(String xml) {
Configuration conf = new 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 = new SchemaExport(conf, dataSource.getConnection());
dbExport.create(false, true);
}
<hibernate-mapping>
<class name="${entity.name}" table="`${entity.tableName}`" ...>
<id name="id" column="id" type="java.lang.String">
<generator class="uuid"/>
</id>
<#if entity.formAttributeList?exists>
<#list entity.formAttributeList as attr>
<#if attr.name != "id">
<property name="${attr.name}" type="java.lang.String"
column="`${attr.columnName}`" length="${attr.length}"/>
</#if>
</#list>
</#if>
</class>
</hibernate-mapping>
建表完成後,透過 FormGenerator 依據 FormService.ftl 模板產生 Groovy 類,封裝 CRUD 操作(insert、update、delete、search),並使用 GroovyClassLoader 動態載入編譯。
// 測試代碼示例
GroovyClassLoader loader = new GroovyClassLoader(parent);
Class groovyClass = loader.parseClass(groovycode);
GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
Map map = new HashMap(); map.put("name", "limq");
groovyObject.invokeMethod("insert", map);
List list = (List) groovyObject.invokeMethod("getAll", null);
Groovy 類內部使用 Spring JdbcTemplate 執行 SQL,SQL 語句亦由 SqlHelper 根據元資料動態組裝。