Browse Source

添加是否取出字段自增属性功能

James 3 years ago
parent
commit
ba7cb5ceac
1 changed files with 78 additions and 65 deletions
  1. 78 65
      src/main/java/com/jfinal/plugin/activerecord/generator/MetaBuilder.java

+ 78 - 65
src/main/java/com/jfinal/plugin/activerecord/generator/MetaBuilder.java

@@ -39,47 +39,55 @@ import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
  * MetaBuilder
  */
 public class MetaBuilder {
-	
+
 	protected DataSource dataSource;
 	protected Dialect dialect = new MysqlDialect();
-	
+
 	// 白名单 + 黑名单选择过滤的 tableName 集合,白名单优先于黑名单
 	protected Set<String> whitelist = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
 	protected Set<String> blacklist = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
-	
+
 	protected Predicate<String> tableSkip = null;
-	
+
 	protected Connection conn = null;
 	protected DatabaseMetaData dbMeta = null;
-	
+
 	protected String[] removedTableNamePrefixes = null;
-	
+
 	protected TypeMapping typeMapping = new TypeMapping();
-	
+
 	protected boolean generateRemarks = false;	// 是否生成备注
 	protected boolean generateView = false;		// 是否生成 view
-	
+	protected boolean fetchFieldAutoIncrement = false;	// 是否取出字段的自增属性
+
 	public MetaBuilder(DataSource dataSource) {
 		if (dataSource == null) {
 			throw new IllegalArgumentException("dataSource can not be null.");
 		}
 		this.dataSource = dataSource;
 	}
-	
+
 	public void setGenerateRemarks(boolean generateRemarks) {
 		this.generateRemarks = generateRemarks;
 	}
-	
+
 	public void setGenerateView(boolean generateView) {
 		this.generateView = generateView;
 	}
-	
+
+	/**
+	 * 配置是否取出字段的自增属性
+	 */
+	public void setFetchFieldAutoIncrement(boolean fetchFieldAutoIncrement) {
+		this.fetchFieldAutoIncrement = fetchFieldAutoIncrement;
+	}
+
 	public void setDialect(Dialect dialect) {
 		if (dialect != null) {
 			this.dialect = dialect;
 		}
 	}
-	
+
 	/**
 	 * 添加要生成的 tableName 到白名单
 	 */
@@ -94,13 +102,13 @@ public class MetaBuilder {
 			}
 		}
 	}
-	
+
 	public void removeWhitelist(String tableName) {
 		if (tableName != null) {
 			this.whitelist.remove(tableName.trim());
 		}
 	}
-	
+
 	/**
 	 * 添加要排除的 tableName 到黑名单
 	 */
@@ -115,17 +123,17 @@ public class MetaBuilder {
 			}
 		}
 	}
-	
+
 	public void removeBlacklist(String tableName) {
 		if (tableName != null) {
 			this.blacklist.remove(tableName.trim());
 		}
 	}
-	
+
 	public void addExcludedTable(String... excludedTables) {
 		addBlacklist(excludedTables);
 	}
-	
+
 	/**
 	 * 设置需要被移除的表名前缀,仅用于生成 modelName 与  baseModelName
 	 * 例如表名  "osc_account",移除前缀 "osc_" 后变为 "account"
@@ -133,19 +141,19 @@ public class MetaBuilder {
 	public void setRemovedTableNamePrefixes(String... removedTableNamePrefixes) {
 		this.removedTableNamePrefixes = removedTableNamePrefixes;
 	}
-	
+
 	public void setTypeMapping(TypeMapping typeMapping) {
 		if (typeMapping != null) {
 			this.typeMapping = typeMapping;
 		}
 	}
-	
+
 	public List<TableMeta> build() {
 		System.out.println("Build TableMeta ...");
 		try {
 			conn = dataSource.getConnection();
 			dbMeta = conn.getMetaData();
-			
+
 			List<TableMeta> ret = new ArrayList<TableMeta>();
 			buildTableNames(ret);
 			for (TableMeta tableMeta : ret) {
@@ -164,7 +172,7 @@ public class MetaBuilder {
 			}
 		}
 	}
-	
+
 	// 移除没有主键的 table
 	protected void removeNoPrimaryKeyTable(List<TableMeta> ret) {
 		for (java.util.Iterator<TableMeta> it = ret.iterator(); it.hasNext();) {
@@ -188,13 +196,13 @@ public class MetaBuilder {
 	protected boolean isSkipTable(String tableName) {
 		return false;
 	}
-	
+
 	/**
 	 * 跳过不需要生成器处理的 table
-	 * 
+	 *
 	 * 由于 setMetaBuilder 将置换掉 MetaBuilder,所以 Generator.addExcludedTable(...)
 	 * 需要放在 setMetaBuilder 之后调用,否则 addExcludedTable 将无效
-	 * 
+	 *
 	 * 示例:
 		Generator gen = new Generator(...);
 		gen.setMetaBuilder(new MetaBuilder(dataSource).skip(
@@ -204,13 +212,13 @@ public class MetaBuilder {
 		);
 		gen.addExcludedTable("error_log");	// 注意这行代码要放在上面的之后调用
 		gen.generate();
-		
+
 	 */
 	public MetaBuilder skip(Predicate<String> tableSkip) {
 		this.tableSkip = tableSkip;
 		return this;
 	}
-	
+
 	/**
 	 * 构造 modelName,mysql 的 tableName 建议使用小写字母,多单词表名使用下划线分隔,不建议使用驼峰命名
 	 * oracle 之下的 tableName 建议使用下划线分隔多单词名,无论 mysql还是 oralce,tableName 都不建议使用驼峰命名
@@ -225,22 +233,22 @@ public class MetaBuilder {
 				}
 			}
 		}
-		
+
 		// 将 oralce 大写的 tableName 转成小写,再生成 modelName
 		if (dialect.isOracle()) {
 			tableName = tableName.toLowerCase();
 		}
-		
+
 		return StrKit.firstCharToUpperCase(StrKit.toCamelCase(tableName));
 	}
-	
+
 	/**
 	 * 使用 modelName 构建 baseModelName
 	 */
 	protected String buildBaseModelName(String modelName) {
 		return "Base" + modelName;
 	}
-	
+
 	/**
 	 * 不同数据库 dbMeta.getTables(...) 的 schemaPattern 参数意义不同
 	 * 1:oracle 数据库这个参数代表 dbMeta.getUserName()
@@ -257,12 +265,12 @@ public class MetaBuilder {
 			return dbMeta.getTables(conn.getCatalog(), schemaPattern, null, new String[]{"TABLE"});	// 不支持 view 生成
 		}
 	}
-	
+
 	protected void buildTableNames(List<TableMeta> ret) throws SQLException {
 		ResultSet rs = getTablesResultSet();
 		while (rs.next()) {
 			String tableName = rs.getString("TABLE_NAME");
-			
+
 			// 如果使用白名单(size>0),则不在白名单之中的都将被过滤
 			if (whitelist.size() > 0 && !whitelist.contains(tableName)) {
 				System.out.println("Skip table :" + tableName);
@@ -273,68 +281,68 @@ public class MetaBuilder {
 				System.out.println("Skip table :" + tableName);
 				continue ;
 			}
-			
+
 			// isSkipTable 为最早期的过滤机制,建议使用白名单、黑名单过滤
 			if (isSkipTable(tableName)) {
 				System.out.println("Skip table :" + tableName);
 				continue ;
 			}
-			
+
 			// jfinal 4.3 新增过滤 table 机制
 			if (tableSkip != null && tableSkip.test(tableName)) {
 				System.out.println("Skip table :" + tableName);
 				continue ;
 			}
-			
+
 			TableMeta tableMeta = new TableMeta();
 			tableMeta.name = tableName;
 			tableMeta.remarks = rs.getString("REMARKS");
-			
+
 			tableMeta.modelName = buildModelName(tableName);
 			tableMeta.baseModelName = buildBaseModelName(tableMeta.modelName);
 			ret.add(tableMeta);
 		}
 		rs.close();
 	}
-	
+
 	protected void buildPrimaryKey(TableMeta tableMeta) throws SQLException {
 		ResultSet rs = dbMeta.getPrimaryKeys(conn.getCatalog(), null, tableMeta.name);
-		
+
 		String primaryKey = "";
 		int index = 0;
 		while (rs.next()) {
 			String cn = rs.getString("COLUMN_NAME");
-			
+
 			// 避免 oracle 驱动的 bug 生成重复主键,如:ID,ID
 			if (primaryKey.equals(cn)) {
 				continue ;
 			}
-			
+
 			if (index++ > 0) {
 				primaryKey += ",";
 			}
 			primaryKey += cn;
 		}
-		
+
 		// 无主键的 table 将在后续的 removeNoPrimaryKeyTable() 中被移除,不再抛出异常
 		// if (StrKit.isBlank(primaryKey)) {
 			// throw new RuntimeException("primaryKey of table \"" + tableMeta.name + "\" required by active record pattern");
 		// }
-		
+
 		tableMeta.primaryKey = primaryKey;
 		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 改变此映射规则
 	 */
@@ -344,8 +352,8 @@ public class MetaBuilder {
 		ResultSet rs = stm.executeQuery(sql);
 		ResultSetMetaData rsmd = rs.getMetaData();
 		int columnCount = rsmd.getColumnCount();
-		
-		
+
+
 		Map<String, ColumnMeta> columnMetaMap = new HashMap<>();
 		if (generateRemarks) {
 			ResultSet colMetaRs = null;
@@ -365,13 +373,13 @@ public class MetaBuilder {
 				}
 			}
 		}
-		
-		
+
+
 		for (int i=1; i<=columnCount; i++) {
 			ColumnMeta cm = new ColumnMeta();
 			// 备忘:getColumnName 获取字段真实名称而非 sql as 子句指定的名称
 			cm.name = rsmd.getColumnName(i);
-			
+
 			String typeStr = null;
 			if (dialect.isKeepByteAndShort()) {
 				int type = rsmd.getColumnType(i);
@@ -381,12 +389,12 @@ public class MetaBuilder {
 					typeStr = "java.lang.Short";
 				}
 			}
-			
+
 			if (typeStr == null) {
 				String colClassName = rsmd.getColumnClassName(i);
 				typeStr = typeMapping.getType(colClassName);
 			}
-			
+
 			if (typeStr == null) {
 				int type = rsmd.getColumnType(i);
 				if (type == Types.BINARY || type == Types.VARBINARY || type == Types.LONGVARBINARY || type == Types.BLOB) {
@@ -406,34 +414,39 @@ public class MetaBuilder {
 					typeStr = "java.lang.String";
 				}
 			}
-			
+
 			typeStr = handleJavaType(typeStr, rsmd, i);
-			
+
 			cm.javaType = typeStr;
-			
+
 			// 构造字段对应的属性名 attrName
 			cm.attrName = buildAttrName(cm.name);
-			
+
 			// 备注字段赋值
 			if (generateRemarks && columnMetaMap.containsKey(cm.name)) {
 				cm.remarks = columnMetaMap.get(cm.name).remarks;
 			}
-			
+
+			// 是否取出字段的自增属性
+			if (fetchFieldAutoIncrement) {
+				cm.isAutoIncrement = rsmd.isAutoIncrement(i);
+			}
+
 			tableMeta.columnMetas.add(cm);
 		}
-		
+
 		rs.close();
 		stm.close();
 	}
-	
+
 	/**
 	 * handleJavaType(...) 方法是用于处理 java 类型的回调方法,当 jfinal 默认
 	 * 处理规则无法满足需求时,用户可以通过继承 MetaBuilder 并覆盖此方法定制自己的
 	 * 类型转换规则
-	 * 
+	 *
 	 * 当前实现只处理了 Oracle 数据库的 NUMBER 类型,根据精度与小数位数转换成 Integer、
 	 * Long、BigDecimal。其它数据库直接返回原值 typeStr
-	 * 
+	 *
 	 * Oracle 数据库 number 类型对应 java 类型:
 	 *  1:如果不指定number的长度,或指定长度 n > 18
 	 *     number 对应 java.math.BigDecimal
@@ -441,7 +454,7 @@ public class MetaBuilder {
 	 *     number(n) 对应 java.lang.Long
 	 *  3:如果number的长度在1 <= n <= 9
 	 *     number(n) 对应 java.lang.Integer 类型
-	 * 
+	 *
 	 * 社区分享:《Oracle NUMBER 类型映射改进》https://jfinal.com/share/1145
 	 */
 	protected String handleJavaType(String typeStr, ResultSetMetaData rsmd, int column) throws SQLException {
@@ -449,7 +462,7 @@ public class MetaBuilder {
 		if ( ! dialect.isOracle() ) {
 			return typeStr;
 		}
-		
+
 		// 默认实现只处理 BigDecimal 类型
 		if ("java.math.BigDecimal".equals(typeStr)) {
 			int scale = rsmd.getScale(column);			// 小数点右边的位数,值为 0 表示整数
@@ -467,10 +480,10 @@ public class MetaBuilder {
 				typeStr = "java.math.BigDecimal";
 			}
 		}
-		
+
 		return typeStr;
 	}
-	
+
 	/**
 	 * 构造 colName 所对应的 attrName,mysql 数据库建议使用小写字段名或者驼峰字段名
 	 * Oralce 反射将得到大写字段名,所以不建议使用驼峰命名,建议使用下划线分隔单词命名法