package com.nlm.web.generator; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.sql.DataSource; import com.jfinal.kit.StrKit; import com.jfinal.plugin.activerecord.generator.ColumnMeta; import com.jfinal.plugin.activerecord.generator.MetaBuilder; import com.jfinal.plugin.activerecord.generator.TableMeta; import com.jfinal.plugin.activerecord.generator.TypeMapping; public class MyMetaBuilder extends MetaBuilder { protected Set<String> includedTableNamePrefixes = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); protected TypeMapping typeMapping = new TypeMapping(); public MyMetaBuilder(DataSource dataSource) { super(dataSource); } public void addIncludedTableNamePrefixes(String... includedTableNamePrefixes) { if (includedTableNamePrefixes != null) { for (String tableNamePrefix : includedTableNamePrefixes) { this.includedTableNamePrefixes.add(tableNamePrefix); } } } public void setMyTypeMapping(TypeMapping typeMapping) { this.typeMapping = typeMapping; } protected void buildTableNames(List<TableMeta> ret) throws SQLException { ResultSet rs = dbMeta.getTables(conn.getCatalog(), null, null, new String[]{"TABLE", "VIEW"}); boolean included = true; int i = 0; while (rs.next()) { included = false; i = 0; String tableName = rs.getString("TABLE_NAME"); for(String prefix : includedTableNamePrefixes){ i++; if(tableName.startsWith(prefix)){ included = true; break; } } if(!included && i > 0){ continue; } if (excludedTables.contains(tableName)) { System.out.println("Skip excluded table :" + tableName); } else { TableMeta tableMeta = new TableMeta(); tableMeta.name = tableName; tableMeta.remarks = rs.getString("REMARKS"); // 移除表名前缀仅用于生成 modelName、baseModelName。tableMeta.name 表名自身不受影响 if (removedTableNamePrefixes != null) { for (String prefix : removedTableNamePrefixes) { if (tableName.startsWith(prefix)) { tableName = tableName.replaceFirst(prefix, ""); break; } } } tableMeta.modelName = StrKit.firstCharToUpperCase(StrKit.toCamelCase(tableName)); tableMeta.baseModelName = "Base" + tableMeta.modelName; ret.add(tableMeta); } } rs.close(); } /** * 文档参考: * http://dev.mysql.com/doc/connector-j/en/connector-j-reference-type-conversions.html * * JDBC 与时间有关类型转换规则,mysql 类型到 java 类型如下对应关系: * DATE java.sql.Date * DATETIME java.sql.Timestamp * TIMESTAMP[(M)] java.sql.Timestamp * TIME java.sql.Time * * 对数据库的 DATE、DATETIME、TIMESTAMP、TIME 四种类型注入 new java.util.Date()对象保存到库以后可以达到“秒精度” * 为了便捷性,getter、setter 方法中对上述四种字段类型采用 java.util.Date,可通过定制 TypeMapping 改变此映射规则 */ protected void buildColumnMetas(TableMeta tableMeta) throws SQLException { Map<String,String> remarksMap = new HashMap<String,String>(); ResultSet rs = dbMeta.getColumns(conn.getCatalog(), null, tableMeta.name, null); String name = null; String remarks = null; while (rs.next()) { name = rs.getString("COLUMN_NAME"); // 名称 remarks = rs.getString("REMARKS"); // 备注 if (null == remarks) remarks = ""; remarksMap.put(name, remarks); } rs.close(); String sql = dialect.forTableBuilderDoBuild(tableMeta.name); Statement stm = conn.createStatement(); rs = stm.executeQuery(sql); ResultSetMetaData rsmd = rs.getMetaData(); for (int i=1; i<=rsmd.getColumnCount(); i++) { ColumnMeta cm = new ColumnMeta(); cm.name = rsmd.getColumnName(i); String colClassName = rsmd.getColumnClassName(i); String typeStr = typeMapping.getType(colClassName); if (typeStr != null) { cm.javaType = typeStr; } else { int type = rsmd.getColumnType(i); if (type == Types.BINARY || type == Types.VARBINARY || type == Types.BLOB) { cm.javaType = "byte[]"; } else if (type == Types.CLOB || type == Types.NCLOB) { cm.javaType = "java.lang.String"; } else { cm.javaType = "java.lang.String"; } } if(remarksMap.containsKey(cm.name)){ cm.remarks = remarksMap.get(cm.name); } tableMeta.columnMetas.add(cm); } rs.close(); stm.close(); } }
注意:要是MetaBuilder类的typeMapping修饰为protected就能更完美了
package com.nlm.web.generator; import com.jfinal.kit.StrKit; import com.jfinal.plugin.activerecord.generator.BaseModelGenerator; import com.jfinal.plugin.activerecord.generator.ColumnMeta; import com.jfinal.plugin.activerecord.generator.TableMeta; public class MyBaseModelGenerator extends BaseModelGenerator { public MyBaseModelGenerator(String baseModelPackageName, String baseModelOutputDir) { super(baseModelPackageName, baseModelOutputDir); importTemplate = "import com.nlm.web.model.BaseModel;%n" + "import com.jfinal.plugin.activerecord.IBean;%n%n"; classDefineTemplate = "/**%n" + " * Generated by JFinal, do not modify this file.%n" + " * tableName: %s,remarks: %s%n" + " */%n" + "@SuppressWarnings(\"serial\")%n" + "public abstract class %s<M extends %s<M>> extends BaseModel<M> implements IBean {%n%n"; setterTemplate = "\t/**%n" + "\t * %s%n"+ "\t * @param %s%n" + "\t */%n" + "\tpublic void %s(%s %s) {%n" + "\t\tset(\"%s\", %s);%n" + "\t}%n%n"; getterTemplate = "\t/**%n" + "\t * %s%n"+ "\t * @return %n" + "\t */%n" + "\tpublic %s %s() {%n" + "\t\treturn get(\"%s\");%n" + "\t}%n%n"; } protected void genClassDefine(TableMeta tableMeta, StringBuilder ret) { ret.append(String.format(classDefineTemplate, tableMeta.name,tableMeta.remarks,tableMeta.baseModelName, tableMeta.baseModelName)); } protected void genSetMethodName(ColumnMeta columnMeta, StringBuilder ret) { String setterMethodName = "set" + StrKit.firstCharToUpperCase(StrKit.toCamelCase(columnMeta.name)); String attrName = StrKit.toCamelCase(columnMeta.name); String setter = String.format(setterTemplate, columnMeta.remarks,attrName,setterMethodName, columnMeta.javaType, attrName, columnMeta.name, attrName); ret.append(setter); } protected void genGetMethodName(ColumnMeta columnMeta, StringBuilder ret) { String getterMethodName = "get" + StrKit.firstCharToUpperCase(StrKit.toCamelCase(columnMeta.name)); String getter = String.format(getterTemplate, columnMeta.remarks,columnMeta.javaType, getterMethodName, columnMeta.name); ret.append(getter); } }
package com.nlm.web.generator; import java.util.List; import javax.sql.DataSource; import com.jfinal.plugin.activerecord.dialect.Dialect; import com.jfinal.plugin.activerecord.generator.BaseModelGenerator; import com.jfinal.plugin.activerecord.generator.DataDictionaryGenerator; import com.jfinal.plugin.activerecord.generator.MappingKitGenerator; import com.jfinal.plugin.activerecord.generator.ModelGenerator; import com.jfinal.plugin.activerecord.generator.TableMeta; import com.jfinal.plugin.activerecord.generator.TypeMapping; public class MyGenerator { protected MyMetaBuilder metaBuilder; protected BaseModelGenerator baseModelGenerator; protected ModelGenerator modelGenerator; protected MappingKitGenerator mappingKitGenerator; protected DataDictionaryGenerator dataDictionaryGenerator; protected boolean generateDataDictionary = false; /** * 构造 Generator,生成 BaseModel、Model、MappingKit 三类文件,其中 MappingKit 输出目录与包名与 Model相同 * @param dataSource 数据源 * @param baseModelPackageName base model 包名 * @param baseModelOutputDir base mode 输出目录 * @param modelPackageName model 包名 * @param modelOutputDir model 输出目录 */ public MyGenerator(DataSource dataSource, String baseModelPackageName, String baseModelOutputDir, String modelPackageName, String modelOutputDir) { this(dataSource, new MyBaseModelGenerator(baseModelPackageName, baseModelOutputDir),new ModelGenerator(modelPackageName, baseModelPackageName, modelOutputDir)); this.mappingKitGenerator = new MappingKitGenerator(modelPackageName, modelOutputDir); this.dataDictionaryGenerator = new DataDictionaryGenerator(dataSource, modelOutputDir); } /** * 构造 Generator,只生成 baseModel * @param dataSource 数据源 * @param baseModelPackageName base model 包名 * @param baseModelOutputDir base mode 输出目录 */ public MyGenerator(DataSource dataSource, String baseModelPackageName, String baseModelOutputDir) { this(dataSource, new MyBaseModelGenerator(baseModelPackageName, baseModelOutputDir)); } public MyGenerator(DataSource dataSource, BaseModelGenerator baseModelGenerator) { if (dataSource == null) throw new IllegalArgumentException("dataSource can not be null."); if (baseModelGenerator == null) throw new IllegalArgumentException("baseModelGenerator can not be null."); this.metaBuilder = new MyMetaBuilder(dataSource); this.baseModelGenerator = baseModelGenerator; this.modelGenerator = null; this.mappingKitGenerator = null; this.dataDictionaryGenerator = null; } /** * 使用指定 BaseModelGenerator、ModelGenerator 构造 Generator * 生成 BaseModel、Model、MappingKit 三类文件,其中 MappingKit 输出目录与包名与 Model相同 */ public MyGenerator(DataSource dataSource, BaseModelGenerator baseModelGenerator, ModelGenerator modelGenerator) { if (dataSource == null) throw new IllegalArgumentException("dataSource can not be null."); if (baseModelGenerator == null) throw new IllegalArgumentException("baseModelGenerator can not be null."); if (modelGenerator == null) throw new IllegalArgumentException("modelGenerator can not be null."); this.metaBuilder = new MyMetaBuilder(dataSource); this.baseModelGenerator = baseModelGenerator; this.modelGenerator = modelGenerator; this.mappingKitGenerator = null; this.dataDictionaryGenerator = null; } /** * 设置 MetaBuilder,便于扩展自定义 MetaBuilder */ public void setMetaBuilder(MyMetaBuilder metaBuilder) { if (metaBuilder != null) this.metaBuilder = metaBuilder; } public void setTypeMapping(TypeMapping typeMapping) { this.metaBuilder.setTypeMapping(typeMapping); } /** * 设置 MappingKitGenerator,便于扩展自定义 MappingKitGenerator */ public void setMappingKitGenerator(MappingKitGenerator mappingKitGenerator) { if (mappingKitGenerator != null) this.mappingKitGenerator = mappingKitGenerator; } /** * 设置 DataDictionaryGenerator,便于扩展自定义 DataDictionaryGenerator */ public void setDataDictionaryGenerator(DataDictionaryGenerator dataDictionaryGenerator) { if (dataDictionaryGenerator != null) this.dataDictionaryGenerator = dataDictionaryGenerator; } /** * 设置数据库方言,默认为 MysqlDialect */ public void setDialect(Dialect dialect) { metaBuilder.setDialect(dialect); } /** * 设置需要被移除的表名前缀,仅用于生成 modelName 与 baseModelName * 例如表名 "osc_account",移除前缀 "osc_" 后变为 "account" */ public void setRemovedTableNamePrefixes(String... removedTableNamePrefixes) { metaBuilder.setRemovedTableNamePrefixes(removedTableNamePrefixes); } /** * 添加不需要处理的数据表 */ public void addExcludedTable(String... excludedTables) { metaBuilder.addExcludedTable(excludedTables); } /** * 添加需要处理的数据表的前缀 */ public void addIncludedTableNamePrefixes(String... includedTableNamePrefixes) { metaBuilder.addIncludedTableNamePrefixes(includedTableNamePrefixes); } /** * 设置是否在 Model 中生成 dao 对象,默认生成 */ public void setGenerateDaoInModel(boolean generateDaoInModel) { if (modelGenerator != null) modelGenerator.setGenerateDaoInModel(generateDaoInModel); } /** * 设置是否生成数据字典 Dictionary 文件,默认不生成 */ public void setGenerateDataDictionary(boolean generateDataDictionary) { this.generateDataDictionary = generateDataDictionary; } /** * 设置 MappingKit 文件输出目录,默认与 modelOutputDir 相同, * 在设置此变量的同时需要设置 mappingKitPackageName */ public void setMappingKitOutputDir(String mappingKitOutputDir) { if (this.mappingKitGenerator != null) this.mappingKitGenerator.setMappingKitOutputDir(mappingKitOutputDir); } /** * 设置 MappingKit 文件包名,默认与 modelPackageName 相同, * 在设置此变的同时需要设置 mappingKitOutputDir */ public void setMappingKitPackageName(String mappingKitPackageName) { if (this.mappingKitGenerator != null) this.mappingKitGenerator.setMappingKitPackageName(mappingKitPackageName); } /** * 设置 MappingKit 文件名,默认为_ MappingKit */ public void setMappingKitClassName(String mappingKitClassName) { if (this.mappingKitGenerator != null) this.mappingKitGenerator.setMappingKitClassName(mappingKitClassName); } /** * 设置数据字典 DataDictionary 文件输出目录,默认与 modelOutputDir 相同 */ public void setDataDictionaryOutputDir(String dataDictionaryOutputDir) { if (this.dataDictionaryGenerator != null) this.dataDictionaryGenerator.setDataDictionaryOutputDir(dataDictionaryOutputDir); } /** * 设置数据字典 DataDictionary 文件输出目录,默认值为 "_DataDictionary.txt" */ public void setDataDictionaryFileName(String dataDictionaryFileName) { if (dataDictionaryGenerator != null) dataDictionaryGenerator.setDataDictionaryFileName(dataDictionaryFileName); } public void generate() { List<TableMeta> tableMetas = metaBuilder.build(); if (tableMetas.size() == 0) { System.out.println("TableMeta 数量为 0,不生成任何文件"); return ; } baseModelGenerator.generate(tableMetas); if (modelGenerator != null) modelGenerator.generate(tableMetas); if (mappingKitGenerator != null) mappingKitGenerator.generate(tableMetas); if (dataDictionaryGenerator != null && generateDataDictionary) dataDictionaryGenerator.generate(tableMetas); System.out.println("Generate complete."); } }
生成例子如下:
package com.nlm.model.base; import com.nlm.web.model.BaseModel; import com.jfinal.plugin.activerecord.IBean; /** * Generated by JFinal, do not modify this file. * tableName: t_sys_org,remarks: 组织机构表 */ @SuppressWarnings("serial") public abstract class BaseOrg<M extends BaseOrg<M>> extends BaseModel<M> implements IBean { /** * 主键 * @param id */ public void setId(java.lang.Integer id) { set("id", id); } /** * 主键 * @return */ public java.lang.Integer getId() { return get("id"); } /** * 父节点 * @param parentId */ public void setParentId(java.lang.Integer parentId) { set("parentId", parentId); } /** * 父节点 * @return */ public java.lang.Integer getParentId() { return get("parentId"); } /** * 机构名称 * @param name */ public void setName(java.lang.String name) { set("name", name); } /** * 机构名称 * @return */ public java.lang.String getName() { return get("name"); } /** * 图标 * @param icon */ public void setIcon(java.lang.String icon) { set("icon", icon); } /** * 图标 * @return */ public java.lang.String getIcon() { return get("icon"); } /** * 左支 * @param leftVal */ public void setLeftVal(java.lang.Integer leftVal) { set("leftVal", leftVal); } /** * 左支 * @return */ public java.lang.Integer getLeftVal() { return get("leftVal"); } /** * 右支 * @param rightVal */ public void setRightVal(java.lang.Long rightVal) { set("rightVal", rightVal); } /** * 右支 * @return */ public java.lang.Long getRightVal() { return get("rightVal"); } /** * 排序号 * @param orderNo */ public void setOrderNo(java.lang.Integer orderNo) { set("orderNo", orderNo); } /** * 排序号 * @return */ public java.lang.Integer getOrderNo() { return get("orderNo"); } /** * 显示标志 1-显示 0-隐藏 * @param show */ public void setShow(java.lang.String show) { set("show", show); } /** * 显示标志 1-显示 0-隐藏 * @return */ public java.lang.String getShow() { return get("show"); } /** * 状态 1-有效 0-无效 * @param status */ public void setStatus(java.lang.String status) { set("status", status); } /** * 状态 1-有效 0-无效 * @return */ public java.lang.String getStatus() { return get("status"); } }