告別無止境的增刪改查:Java代碼生成器
有感于馬上要做個(gè)比較大的業(yè)務(wù)系統(tǒng),想到那無止境的增刪改查、粘貼復(fù)制,頓時(shí)腦后升起一陣涼風(fēng)。于是想到個(gè)找或者寫一個(gè)Java代碼的生成器,這樣在正常開發(fā)進(jìn)度下,也能余下更多的時(shí)間去做些別的事情。
閑話少說,首先總結(jié)下需求:
我需要的這個(gè)工具能夠讀取數(shù)據(jù)庫表結(jié)構(gòu),通過對(duì)字段類型、名稱等分析得到需要的各種變量,根據(jù)模板生成相應(yīng)的pojo類、hibernate的xml配置文件、dao和service的接口和類。
需求看起來很簡(jiǎn)單,但是一是沒搞過這樣的小工具,二是技術(shù)不過關(guān),所以還是想到了找找有沒有開源的代碼拿過來根據(jù)自己的需求改。
于是找到了rapid-generator這個(gè)開源工具,同學(xué)們可以下載rapid-generator直接使用,根據(jù)自己的需求寫好模板就行了。
由于自己項(xiàng)目中的特殊情況和公司規(guī)范等因素,另外也是想學(xué)習(xí)下別人的設(shè)計(jì),所以我對(duì)源碼進(jìn)行了刪減和功能的修改。
來看下主要的類:
Table:根據(jù)表結(jié)構(gòu)建立的對(duì)象。
Column:根據(jù)表中每列建立的對(duì)象。
Generator:生成器核心類,主要負(fù)責(zé)根據(jù)表對(duì)象和讀取FreeMarker模板生成最后的java代碼文件。
GeneratorControl:控制生成過程等的一些參數(shù),例如文件是否覆蓋、文件編碼等。
GeneratorProperties:讀取配置文件的類,配置文件包括數(shù)據(jù)庫連接信息和一些基本的參數(shù)配置。
下面來看一下模板的編寫:
pojo模板:
- <#include "/java_copyright.include">
- <#assign className = table.className>
- <#assign classNameLower = className?uncap_first>
- package ${basepackage}.pojo.${mpackage}.${table.classNameFirstLower};
- <#include "/java_imports.include">
- import com.linkage.agri.pojo.base.BaseEntity;
- public class ${className} extends BaseEntity {
- private static final long serialVersionUID = 5454155825314635342L;
- <#list table.columns as column>
- /**
- * ${column.remarks}
- */
- private ${column.simpleJavaType} ${column.columnNameLower};
- </#list>
- <@generateJavaColumns/>
- <#macro generateJavaColumns>
- <#list table.columns as column>
- <#if column.isDateTimeColumn>
- public String get${column.columnName}String() {
- return DateConvertUtils.format(get${column.columnName}(), FORMAT_${column.constantName});
- }
- public void set${column.columnName}String(String ${column.columnNameLower}) {
- set${column.columnName}(DateConvertUtils.parse(${column.columnNameLower}, FORMAT_${column.constantName},${column.simpleJavaType}.class));
- }
- </#if>
- public void set${column.columnName}(${column.simpleJavaType} ${column.columnNameLower}) {
- this.${column.columnNameLower} = ${column.columnNameLower};
- }
- public ${column.simpleJavaType} get${column.columnName}() {
- return this.${column.columnNameLower};
- }
- </#list>
- </#macro>
FreeMarker的基本語法可以看下FreeMarker中文手冊(cè)。
${}可以引用很多變量,這些變量包括:環(huán)境變量、table對(duì)象、配置變量等,這些變量都裝在一個(gè)map里,如果自己有特殊需求,當(dāng)然可以修改源碼來裝載更多的變量值。
注意:當(dāng)變量為對(duì)象時(shí),訪問對(duì)象的屬性是通過get方法來訪問的。例如${table.classNameFirstLower},是引用 table對(duì)象的getNameFirstLower()方法,即使table對(duì)象中沒有nameFirstLower這個(gè)屬性也能夠引用。
再看下我寫的dao的模板:
- <#include "/java_copyright.include">
- <#assign className = table.className>
- <#assign classNameLower = className?uncap_first>
- package ${basepackage}.dao.${mpackage}.${table.classNameFirstLower};
- import java.math.BigDecimal;
- import java.util.List;
- import java.util.Map;
- import com.linkage.agri.dao.base.AbstractHibernateDAO;
- import com.linkage.agri.exception.DAOException;
- import ${basepackage}.pojo.${mpackage}.${classNameLower}.${className};
- <#include "/java_imports.include">
- public Class ${className}DAOImpl extends AbstractHibernateDAO implements ${className}DAO
- {
- /**
- * <query all>
- * @param paramMap
- * @param orderMap
- * @param pageNum
- * @param pageSize
- * @return
- * @throws DAOException
- */
- @SuppressWarnings
- public List<${className}> queryList${className}ByAttr(Map<String, Object> paramMap, Map<String, String> orderMap, int pageNum,
- int pageSize)
- throws DAOException
- {
- return super.listInstances(${className}.class, paramMap, orderMap, pageNum, pageSize);
- }
- /**
- *
- * <find one by id>
- * @param serial
- * @throws DAOException
- */
- public ${className} find${className}By${table.pkColumn.columnName}(${table.pkColumn.simpleJavaType} ${table.pkColumn.columnNameFirstLower})
- throws DAOException
- {
- return (${className})super.findById(${className}.class, ${table.pkColumn.columnNameFirstLower});
- }
- /**
- *
- * <save one>
- * @param ${table.classNameFirstLower}
- * @throws DAOException
- */
- public ${table.pkColumn.simpleJavaType} save${className}(${className} ${table.classNameFirstLower})
- throws DAOException
- {
- return (${table.pkColumn.simpleJavaType})super.saveInstance(${table.classNameFirstLower});
- }
- /**
- *
- * <update one>
- * @param ${table.classNameFirstLower}
- * @throws DAOException
- */
- public void update${className}(${className} ${table.classNameFirstLower})
- throws DAOException
- {
- super.updateInstance(${className});
- }
- /**
- * <check one is have?>
- * @param paramMap
- * @return
- * @throws DAOException
- */
- public boolean check${className}IsHaveByAttr(Map<String, Object> paramMap)
- throws DAOException
- {
- StringBuffer sqlBuffer = new StringBuffer();
- sqlBuffer.append("SELECT COUNT(*) FROM ${table.sqlName} T ");
- sqlBuffer.append("WHERE T.${table.pkColumn.sqlName} = ? ");
- BigDecimal big = (BigDecimal)super.findUniqueResultBySQLWithParams(sqlBuffer.toString(), paramMap.get("${table.pkColumn.columnNameFirstLower}"));
- return big.intValue() > 0 ? false : true;
- }
- /**
- * <update some>
- * @param ${table.classNameFirstLower}List
- * @return
- * @throws DAOException
- */
- public void update${className}Batch(List<${className}> ${table.classNameFirstLower}List)
- throws DAOException
- {
- super.updateBatchInstance(${table.classNameFirstLower}List);
- }
- /**
- *
- * <delete one>
- * @param ${table.classNameFirstLower}
- * @throws DAOException
- */
- public void delete${className}(${className} ${table.classNameFirstLower})
- throws DAOException
- {
- super.deleteInstance(${table.classNameFirstLower});
- }
- }
建立模板是能否解決自己?jiǎn)栴}的關(guān)鍵,在摸索出門道以后寫模板變的十分簡(jiǎn)單。其實(shí)原理很簡(jiǎn)單,就是用一系列占位符來替換實(shí)際的變量值。
模板路徑可以按照實(shí)際項(xiàng)目中的路徑來拜訪,生成器可以讀取某個(gè)路徑下所有模板進(jìn)行生成,結(jié)果如下圖:
接口和實(shí)現(xiàn):
就說這么多吧,感興趣的可以研究下這個(gè)工具的源碼,也DIY出一套自己代碼生成工具。不感興趣的直接寫模板就能用。
我只是走在路上,偶爾駐足觀賞,偶爾回頭看看。
原文鏈接:http://www.cnblogs.com/zhuYears/archive/2012/02/29/2373491.html
【編輯推薦】