ソースを参照

jfinal 2.1 release ^_^

James 10 年 前
コミット
28b82489d6

+ 8 - 0
src/com/jfinal/plugin/activerecord/Db.java

@@ -351,6 +351,10 @@ public class Db {
 		return dbPro.paginate(pageNumber, pageSize, sql, paras);
 	}
 	
+	public static Page<Record> paginate(int pageNumber, int pageSize, String[] selectAndSqlExceptSelect, Object... paras) {
+		return dbPro.paginate(pageNumber, pageSize, selectAndSqlExceptSelect, paras);
+	}
+	
 	/**
 	 * @see #paginate(String, int, int, String, Object...)
 	 */
@@ -502,6 +506,10 @@ public class Db {
 		return dbPro.paginateByCache(cacheName, key, pageNumber, pageSize, sql, paras);
 	}
 	
+	public static Page<Record> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, String[] selectAndSqlExceptSelect, Object... paras) {
+		return dbPro.paginateByCache(cacheName, key, pageNumber, pageSize, selectAndSqlExceptSelect, paras);
+	}
+	
 	/**
 	 * @see #paginateByCache(String, Object, int, int, String, Object...)
 	 */

+ 34 - 6
src/com/jfinal/plugin/activerecord/DbPro.java

@@ -453,16 +453,20 @@ public class DbPro {
 	}
 	
 	Page<Record> paginate(Config config, Connection conn, int pageNumber, int pageSize, String sql, Object... paras) throws SQLException {
-		if (pageNumber < 1 || pageSize < 1)
-			throw new ActiveRecordException("pageNumber and pageSize must be more than 0");
-		
-		if (config.dialect.isTakeOverDbPaginate())
-			return config.dialect.takeOverDbPaginate(conn, pageNumber, pageSize, sql, paras);
-		
 		Object[] actualSqlParas = new Object[2];
 		String totalRowSql = config.dialect.forTotalRow(actualSqlParas, sql, paras);
 		sql = (String)actualSqlParas[0];
 		paras = (Object[])actualSqlParas[1];
+		return doPaginate(config, conn, pageNumber, pageSize, totalRowSql, sql, paras);
+	}
+	
+	Page<Record> doPaginate(Config config, Connection conn, int pageNumber, int pageSize, String totalRowSql, String sql, Object... paras) throws SQLException {
+		if (pageNumber < 1 || pageSize < 1) {
+			throw new ActiveRecordException("pageNumber and pageSize must be more than 0");
+		}
+		if (config.dialect.isTakeOverDbPaginate()) {
+			return config.dialect.takeOverDbPaginate(conn, pageNumber, pageSize, totalRowSql, sql, paras);
+		}
 		
 		long totalRow;
 		List result = query(config, conn, totalRowSql, paras);
@@ -510,6 +514,20 @@ public class DbPro {
 		}
 	}
 	
+	public Page<Record> paginate(int pageNumber, int pageSize, String[] selectAndSqlExceptSelect, Object... paras) {
+		Connection conn = null;
+		try {
+			String totalRowSql = "select count(*) " + config.dialect.replaceOrderBy(selectAndSqlExceptSelect[1]);
+			String sql = selectAndSqlExceptSelect[0] + " " + selectAndSqlExceptSelect[1];
+			conn = config.getConnection();
+			return doPaginate(config, conn, pageNumber, pageSize, totalRowSql, sql, paras);
+		} catch (Exception e) {
+			throw new ActiveRecordException(e);
+		} finally {
+			config.close(conn);
+		}
+	}
+	
 	/**
 	 * @see #paginate(String, int, int, String, Object...)
 	 */
@@ -794,6 +812,16 @@ public class DbPro {
 		return result;
 	}
 	
+	public Page<Record> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, String[] selectAndSqlExceptSelect, Object... paras) {
+		ICache cache = config.getCache();
+		Page<Record> result = cache.get(cacheName, key);
+		if (result == null) {
+			result = paginate(pageNumber, pageSize, selectAndSqlExceptSelect, paras);
+			cache.put(cacheName, key, result);
+		}
+		return result;
+	}
+	
 	/**
 	 * @see #paginateByCache(String, Object, int, int, String, Object...)
 	 */

+ 2 - 2
src/com/jfinal/plugin/activerecord/JavaType.java

@@ -39,8 +39,8 @@ public class JavaType {
 		// bigint
 		put("java.lang.Long", java.lang.Long.class);
 		
-		// java.util.Data can not be returned
-		// java.sql.Date, java.sql.Time, java.sql.Timestamp all extends java.util.Data so getDate can return the three types data
+		// java.util.Date can not be returned
+		// java.sql.Date, java.sql.Time, java.sql.Timestamp all extends java.util.Date so getDate can return the three types data
 		// put("java.util.Date", java.util.Date.class);
 		
 		// date, year

+ 43 - 6
src/com/jfinal/plugin/activerecord/Model.java

@@ -292,17 +292,44 @@ public abstract class Model<M extends Model> implements Serializable {
 		}
 	}
 	
+	/**
+	 * 支持 select 中带有嵌套 select 语句的 sql,避免正则解析拖慢性能
+	 * 将 sql 分成 select 部分与 非 select 部分来写,并传入 selectAndSqlExceptSelect 数组中
+	 * <pre>
+	 * 举例:
+	 * paginate(1, 10, new String[]{"select *", "from user where id>?"} , 123);
+	 * </pre>
+	 */
+	public Page<M> paginate(int pageNumber, int pageSize, String[] selectAndSqlExceptSelect, Object... paras) {
+		Config config = getConfig();
+		Connection conn = null;
+		try {
+			String totalRowSql = "select count(*) " + config.dialect.replaceOrderBy(selectAndSqlExceptSelect[1]);
+			String sql = selectAndSqlExceptSelect[0] + " " + selectAndSqlExceptSelect[1];
+			conn = config.getConnection();
+			return doPaginate(config, conn, pageNumber, pageSize, totalRowSql, sql, paras);
+		} catch (Exception e) {
+			throw new ActiveRecordException(e);
+		} finally {
+			config.close(conn);
+		}
+	}
+	
 	private Page<M> paginate(Config config, Connection conn, int pageNumber, int pageSize, String sql, Object... paras) throws Exception {
-		if (pageNumber < 1 || pageSize < 1)
-			throw new ActiveRecordException("pageNumber and pageSize must be more than 0");
-		
-		if (config.dialect.isTakeOverModelPaginate())
-			return config.dialect.takeOverModelPaginate(conn, getUsefulClass(), pageNumber, pageSize, sql, paras);
-		
 		Object[] actualSqlParas = new Object[2];
 		String totalRowSql = config.dialect.forTotalRow(actualSqlParas, sql, paras);
 		sql = (String)actualSqlParas[0];
 		paras = (Object[])actualSqlParas[1];
+		return doPaginate(config, conn, pageNumber, pageSize, totalRowSql, sql, paras);
+	}
+	
+	private Page<M> doPaginate(Config config, Connection conn, int pageNumber, int pageSize, String totalRowSql, String sql, Object... paras) throws Exception {
+		if (pageNumber < 1 || pageSize < 1) {
+			throw new ActiveRecordException("pageNumber and pageSize must be more than 0");
+		}
+		if (config.dialect.isTakeOverModelPaginate()) {
+			return config.dialect.takeOverModelPaginate(conn, getUsefulClass(), pageNumber, pageSize, totalRowSql, sql, paras);
+		}
 		
 		long totalRow;
 		List result = Db.query(config, conn, totalRowSql, paras);
@@ -849,6 +876,16 @@ public abstract class Model<M extends Model> implements Serializable {
 		return result;
 	}
 	
+	public Page<M> paginateByCache(String cacheName, Object key, int pageNumber, int pageSize, String[] selectAndSqlExceptSelect, Object... paras) {
+		ICache cache = getConfig().getCache();
+		Page<M> result = cache.get(cacheName, key);
+		if (result == null) {
+			result = paginate(pageNumber, pageSize, selectAndSqlExceptSelect, paras);
+			cache.put(cacheName, key, result);
+		}
+		return result;
+	}
+	
 	/**
 	 * @see #paginateByCache(String, Object, int, int, String, Object...)
 	 */

+ 2 - 12
src/com/jfinal/plugin/activerecord/dialect/AnsiSqlDialect.java

@@ -202,12 +202,7 @@ public class AnsiSqlDialect extends Dialect {
 	}
 	
 	@SuppressWarnings("rawtypes")
-	public Page<Record> takeOverDbPaginate(Connection conn, int pageNumber, int pageSize, String sql, Object... paras) throws SQLException {
-		Object[] actualSqlParas = new Object[2];
-		String totalRowSql = forTotalRow(actualSqlParas, sql, paras);
-		sql = (String)actualSqlParas[0];
-		paras = (Object[])actualSqlParas[1];
-		
+	public Page<Record> takeOverDbPaginate(Connection conn, int pageNumber, int pageSize, String totalRowSql, String sql, Object... paras) throws SQLException {
 		long totalRow;
 		List result = CPI.query(conn, totalRowSql, paras);
 		if (isGroupBySql(sql)) {
@@ -289,12 +284,7 @@ public class AnsiSqlDialect extends Dialect {
 	}
 	
 	@SuppressWarnings({"rawtypes", "unchecked"})
-	public Page<? extends Model> takeOverModelPaginate(Connection conn, Class<? extends Model> modelClass, int pageNumber, int pageSize, String sql, Object... paras) throws Exception {
-		Object[] actualSqlParas = new Object[2];
-		String totalRowSql = forTotalRow(actualSqlParas, sql, paras);
-		sql = (String)actualSqlParas[0];
-		paras = (Object[])actualSqlParas[1];
-		
+	public Page<? extends Model> takeOverModelPaginate(Connection conn, Class<? extends Model> modelClass, int pageNumber, int pageSize, String totalRowSql, String sql, Object... paras) throws Exception {
 		long totalRow;
 		List result = CPI.query(conn, totalRowSql, paras);
 		if (isGroupBySql(sql)) {

+ 2 - 4
src/com/jfinal/plugin/activerecord/dialect/Dialect.java

@@ -58,7 +58,7 @@ public abstract class Dialect {
 		return false;
 	}
 	
-	public Page<Record> takeOverDbPaginate(Connection conn, int pageNumber, int pageSize, String sql, Object... paras) throws SQLException {
+	public Page<Record> takeOverDbPaginate(Connection conn, int pageNumber, int pageSize, String totalRowSql, String sql, Object... paras) throws SQLException {
 		throw new RuntimeException("You should implements this method in " + getClass().getName());
 	}
 	
@@ -67,7 +67,7 @@ public abstract class Dialect {
 	}
 	
 	@SuppressWarnings("rawtypes")
-	public Page takeOverModelPaginate(Connection conn, Class<? extends Model> modelClass, int pageNumber, int pageSize, String sql, Object... paras) throws Exception {
+	public Page takeOverModelPaginate(Connection conn, Class<? extends Model> modelClass, int pageNumber, int pageSize, String totalRowSql, String sql, Object... paras) throws Exception {
 		throw new RuntimeException("You should implements this method in " + getClass().getName());
 	}
 	
@@ -118,10 +118,8 @@ public abstract class Dialect {
 			Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
 		
 		// "(^\\s*select\\s+[\\s\\S]+?(\\s+|\\)))from\\b";
-		// "(^\\s*select\\s+(\\s*\\S*\\([\\s\\S]+\\)\\s*as\\s+\\S+|\\s*\\S+(\\s+as\\s+\\S+)?)+?\\s*)from"
 		private static final Pattern SELECT_PATTERN = Pattern.compile(
 			"(^\\s*select\\s+[\\s\\S]+?(\\s+|\\)))from",
-			// "(^\\s*select\\s+(\\s*\\S*\\([\\s\\S]+\\)\\s*as\\s+\\S+|\\s*\\S+(\\s+as\\s+\\S+)?)+?\\s*)from",
 			Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);
 		
 		private static final Pattern GROUP_BY_PATTERN = Pattern.compile(

+ 9 - 6
src/com/jfinal/plugin/activerecord/generator/BaseModelGenerator.java

@@ -50,6 +50,8 @@ public class BaseModelGenerator {
 	protected String baseModelPackageName;
 	protected String baseModelOutputDir;
 	
+	protected JavaKeyword javaKeyword = new JavaKeyword();
+	
 	public BaseModelGenerator(String baseModelPackageName, String baseModelOutputDir) {
 		if (StrKit.isBlank(baseModelPackageName))
 			throw new IllegalArgumentException("baseModelPackageName can not be blank.");
@@ -65,11 +67,11 @@ public class BaseModelGenerator {
 	public void generate(List<TableMeta> tableMetas) {
 		System.out.println("Generate base model ...");
 		for (TableMeta tableMeta : tableMetas)
-			genBaseModel(tableMeta);
+			genBaseModelContent(tableMeta);
 		wirtToFile(tableMetas);
 	}
 	
-	protected void genBaseModel(TableMeta tableMeta) {
+	protected void genBaseModelContent(TableMeta tableMeta) {
 		StringBuilder ret = new StringBuilder();
 		genPackage(ret);
 		genImport(ret);
@@ -95,14 +97,15 @@ public class BaseModelGenerator {
 	}
 	
 	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, setterMethodName, columnMeta.javaType, attrName, columnMeta.name, attrName);
+		String setterMethodName = "set" + StrKit.firstCharToUpperCase(columnMeta.attrName);
+		// 如果 setter 参数名为 java 语言关键字,则添加下划线前缀 "_"
+		String argName = javaKeyword.contains(columnMeta.attrName) ? "_" + columnMeta.attrName : columnMeta.attrName;
+		String setter = String.format(setterTemplate, setterMethodName, columnMeta.javaType, argName, columnMeta.name, argName);
 		ret.append(setter);
 	}
 	
 	protected void genGetMethodName(ColumnMeta columnMeta, StringBuilder ret) {
-		String getterMethodName = "get" + StrKit.firstCharToUpperCase(StrKit.toCamelCase(columnMeta.name));
+		String getterMethodName = "get" + StrKit.firstCharToUpperCase(columnMeta.attrName);
 		String getter = String.format(getterTemplate, columnMeta.javaType, getterMethodName, columnMeta.name);
 		ret.append(getter);
 	}

+ 1 - 0
src/com/jfinal/plugin/activerecord/generator/ColumnMeta.java

@@ -23,6 +23,7 @@ public class ColumnMeta {
 	
 	public String name;				// 字段名
 	public String javaType;			// 字段对应的 java 类型
+	public String attrName;			// 字段对应的属性名
 	
 	// ---------
 	

+ 33 - 16
src/com/jfinal/plugin/activerecord/generator/Generator.java

@@ -62,10 +62,12 @@ public class Generator {
 	}
 	
 	public Generator(DataSource dataSource, BaseModelGenerator baseModelGenerator) {
-		if (dataSource == null)
+		if (dataSource == null) {
 			throw new IllegalArgumentException("dataSource can not be null.");
-		if (baseModelGenerator == null)
+		}
+		if (baseModelGenerator == null) {
 			throw new IllegalArgumentException("baseModelGenerator can not be null.");
+		}
 		
 		this.metaBuilder = new MetaBuilder(dataSource);
 		this.baseModelGenerator = baseModelGenerator;
@@ -79,12 +81,15 @@ public class Generator {
 	 * 生成 BaseModel、Model、MappingKit 三类文件,其中 MappingKit 输出目录与包名与 Model相同
 	 */
 	public Generator(DataSource dataSource, BaseModelGenerator baseModelGenerator, ModelGenerator modelGenerator) {
-		if (dataSource == null)
+		if (dataSource == null) {
 			throw new IllegalArgumentException("dataSource can not be null.");
-		if (baseModelGenerator == null)
+		}
+		if (baseModelGenerator == null) {
 			throw new IllegalArgumentException("baseModelGenerator can not be null.");
-		if (modelGenerator == null)
+		}
+		if (modelGenerator == null) {
 			throw new IllegalArgumentException("modelGenerator can not be null.");
+		}
 		
 		this.metaBuilder = new MetaBuilder(dataSource);
 		this.baseModelGenerator = baseModelGenerator;
@@ -97,8 +102,9 @@ public class Generator {
 	 * 设置 MetaBuilder,便于扩展自定义 MetaBuilder
 	 */
 	public void setMetaBuilder(MetaBuilder metaBuilder) {
-		if (metaBuilder != null)
+		if (metaBuilder != null) {
 			this.metaBuilder = metaBuilder;
+		}
 	}
 	
 	public void setTypeMapping(TypeMapping typeMapping) {
@@ -109,16 +115,18 @@ public class Generator {
 	 * 设置 MappingKitGenerator,便于扩展自定义 MappingKitGenerator
 	 */
 	public void setMappingKitGenerator(MappingKitGenerator mappingKitGenerator) {
-		if (mappingKitGenerator != null)
+		if (mappingKitGenerator != null) {
 			this.mappingKitGenerator = mappingKitGenerator;
+		}
 	}
 	
 	/**
 	 * 设置 DataDictionaryGenerator,便于扩展自定义 DataDictionaryGenerator
 	 */
 	public void setDataDictionaryGenerator(DataDictionaryGenerator dataDictionaryGenerator) {
-		if (dataDictionaryGenerator != null)
+		if (dataDictionaryGenerator != null) {
 			this.dataDictionaryGenerator = dataDictionaryGenerator;
+		}
 	}
 	
 	/**
@@ -164,8 +172,9 @@ public class Generator {
 	 * 在设置此变量的同时需要设置 mappingKitPackageName
 	 */
 	public void setMappingKitOutputDir(String mappingKitOutputDir) {
-		if (this.mappingKitGenerator != null)
+		if (this.mappingKitGenerator != null) {
 			this.mappingKitGenerator.setMappingKitOutputDir(mappingKitOutputDir);
+		}
 	}
 	
 	/**
@@ -173,27 +182,31 @@ public class Generator {
 	 * 在设置此变的同时需要设置 mappingKitOutputDir
 	 */
 	public void setMappingKitPackageName(String mappingKitPackageName) {
-		if (this.mappingKitGenerator != null)
+		if (this.mappingKitGenerator != null) {
 			this.mappingKitGenerator.setMappingKitPackageName(mappingKitPackageName);
+		}
 	}
 	
 	/**
 	 * 设置数据字典 DataDictionary 文件输出目录,默认与 modelOutputDir 相同
 	 */
 	public void setDataDictionaryOutputDir(String dataDictionaryOutputDir) {
-		if (this.dataDictionaryGenerator != null)
+		if (this.dataDictionaryGenerator != null) {
 			this.dataDictionaryGenerator.setDataDictionaryOutputDir(dataDictionaryOutputDir);
+		}
 	}
 	
 	/**
 	 * 设置数据字典 DataDictionary 文件输出目录,默认值为 "_DataDictionary.txt"
 	 */
 	public void setDataDictionaryFileName(String dataDictionaryFileName) {
-		if (dataDictionaryGenerator != null)
+		if (dataDictionaryGenerator != null) {
 			dataDictionaryGenerator.setDataDictionaryFileName(dataDictionaryFileName);
+		}
 	}
 	
 	public void generate() {
+		long start = System.currentTimeMillis();
 		List<TableMeta> tableMetas = metaBuilder.build();
 		if (tableMetas.size() == 0) {
 			System.out.println("TableMeta 数量为 0,不生成任何文件");
@@ -202,16 +215,20 @@ public class Generator {
 		
 		baseModelGenerator.generate(tableMetas);
 		
-		if (modelGenerator != null)	
+		if (modelGenerator != null) {
 			modelGenerator.generate(tableMetas);
+		}
 		
-		if (mappingKitGenerator != null)
+		if (mappingKitGenerator != null) {
 			mappingKitGenerator.generate(tableMetas);
+		}
 		
-		if (dataDictionaryGenerator != null && generateDataDictionary)
+		if (dataDictionaryGenerator != null && generateDataDictionary) {
 			dataDictionaryGenerator.generate(tableMetas);
+		}
 		
-		System.out.println("Generate complete.");
+		long usedTime = (System.currentTimeMillis() - start) / 1000;
+		System.out.println("Generate complete in " + usedTime + " seconds.");
 	}
 }
 

+ 106 - 0
src/com/jfinal/plugin/activerecord/generator/JavaKeyword.java

@@ -0,0 +1,106 @@
+/**
+ * Copyright (c) 2011-2016, James Zhan 詹波 (jfinal@126.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.jfinal.plugin.activerecord.generator;
+
+import java.util.HashSet;
+import java.util.Set;
+import com.jfinal.kit.StrKit;
+
+/**
+ * JavaKeyword.
+ */
+public class JavaKeyword {
+	
+	private String[] keywordArray = {
+		"abstract",
+		"assert",
+		"boolean",
+		"break",
+		"byte",
+		"case",
+		"catch",
+		"char",
+		"class",
+		"const",
+		"continue",
+		"default",
+		"do",
+		"double",
+		"else",
+		"enum",
+		"extends",
+		"final",
+		"finally",
+		"float",
+		"for",
+		"goto",
+		"if",
+		"implements",
+		"import",
+		"instanceof",
+		"int",
+		"interface",
+		"long",
+		"native",
+		"new",
+		"package",
+		"private",
+		"protected",
+		"public",
+		"return",
+		"strictfp",
+		"short",
+		"static",
+		"super",
+		"switch",
+		"synchronized",
+		"this",
+		"throw",
+		"throws",
+		"transient",
+		"try",
+		"void",
+		"volatile",
+		"while"
+	};
+	
+	private Set<String> set = initKeyword();
+	
+	public void addKeyword(String keyword) {
+		if (StrKit.notBlank(keyword)) {
+			set.add(keyword);
+		}
+	}
+	
+	private Set<String> initKeyword() {
+		HashSet<String> ret = new HashSet<String>();
+		for (String keyword : keywordArray) {
+			ret.add(keyword);
+		}
+		return ret;
+	}
+	
+	public boolean contains(String str) {
+		return set.contains(str);
+	}
+}
+
+
+
+
+
+

+ 80 - 23
src/com/jfinal/plugin/activerecord/generator/MetaBuilder.java

@@ -31,6 +31,7 @@ import javax.sql.DataSource;
 import com.jfinal.kit.StrKit;
 import com.jfinal.plugin.activerecord.dialect.Dialect;
 import com.jfinal.plugin.activerecord.dialect.MysqlDialect;
+import com.jfinal.plugin.activerecord.dialect.OracleDialect;
 
 /**
  * MetaBuilder
@@ -106,36 +107,78 @@ public class MetaBuilder {
 		}
 	}
 	
+	/**
+	 * 通过继承并覆盖此方法,跳过一些不希望处理的 table,定制更加灵活的 table 过滤规则
+	 * @return 返回 true 时将跳过当前 tableName 的处理
+	 */
+	protected boolean isSkipTable(String tableName) {
+		return false;
+	}
+	
+	/**
+	 * 构造 modelName,mysql 的 tableName 建议使用小写字母,多单词表名使用下划线分隔,不建议使用驼峰命名
+	 * oracle 之下的 tableName 建议使用下划线分隔多单词名,无论 mysql还是 oralce,tableName 都不建议使用驼峰命名
+	 */
+	protected String buildModelName(String tableName) {
+		// 移除表名前缀仅用于生成 modelName、baseModelName,而 tableMeta.name 表名自身不能受影响
+		if (removedTableNamePrefixes != null) {
+			for (String prefix : removedTableNamePrefixes) {
+				if (tableName.startsWith(prefix)) {
+					tableName = tableName.replaceFirst(prefix, "");
+					break;
+				}
+			}
+		}
+		
+		// 将 oralce 大写的 tableName 转成小写,再生成 modelName
+		if (dialect instanceof OracleDialect) {
+			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()
+	 * 2:postgresql 数据库中需要在 jdbcUrl中配置 schemaPatter,例如:
+	 *   jdbc:postgresql://localhost:15432/djpt?currentSchema=public,sys,app
+	 *   最后的参数就是搜索schema的顺序,DruidPlugin 下测试成功
+	 * 3:开发者若在其它库中发现工作不正常,可通过继承 MetaBuilder并覆盖此方法来实现功能
+	 */
+	protected ResultSet getTablesResultSet() throws SQLException {
+		String schemaPattern = dialect instanceof OracleDialect ? dbMeta.getUserName() : null;
+		return dbMeta.getTables(conn.getCatalog(), schemaPattern, null, new String[]{"TABLE", "VIEW"});
+	}
+	
 	protected void buildTableNames(List<TableMeta> ret) throws SQLException {
-		String userName = dialect.isOracle() ? dbMeta.getUserName() : null;
-		ResultSet rs = dbMeta.getTables(conn.getCatalog(), userName, null, new String[]{"TABLE", "VIEW"});
+		ResultSet rs = getTablesResultSet();
 		while (rs.next()) {
 			String tableName = rs.getString("TABLE_NAME");
 			
 			if (excludedTables.contains(tableName)) {
-				System.out.println("Skip excluded table :" + tableName);
+				System.out.println("Skip table :" + tableName);
+				continue ;
 			}
-			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;
-						}
-					}
-				}
-				if (dialect.isOracle()) {
-					tableName = tableName.toLowerCase();
-				}
-				tableMeta.modelName = StrKit.firstCharToUpperCase(StrKit.toCamelCase(tableName));
-				tableMeta.baseModelName = "Base" + tableMeta.modelName;
-				ret.add(tableMeta);
+			if (isSkipTable(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();
 	}
@@ -195,12 +238,26 @@ public class MetaBuilder {
 				}
 			}
 			
+			// 构造字段对应的属性名 attrName
+			cm.attrName = buildAttrName(cm.name);
+			
 			tableMeta.columnMetas.add(cm);
 		}
 		
 		rs.close();
 		stm.close();
 	}
+	
+	/**
+	 * 构造 colName 所对应的 attrName,mysql 数据库建议使用小写字段名或者驼峰字段名
+	 * Oralce 反射将得到大写字段名,所以不建议使用驼峰命名,建议使用下划线分隔单词命名法
+	 */
+	protected String buildAttrName(String colName) {
+		if (dialect instanceof OracleDialect) {
+			colName = colName.toLowerCase();
+		}
+		return StrKit.toCamelCase(colName);
+	}
 }
 
 

+ 2 - 2
src/com/jfinal/plugin/activerecord/generator/ModelGenerator.java

@@ -69,11 +69,11 @@ public class ModelGenerator {
 	public void generate(List<TableMeta> tableMetas) {
 		System.out.println("Generate model ...");
 		for (TableMeta tableMeta : tableMetas)
-			genBaseModel(tableMeta);
+			genModelContent(tableMeta);
 		wirtToFile(tableMetas);
 	}
 	
-	protected void genBaseModel(TableMeta tableMeta) {
+	protected void genModelContent(TableMeta tableMeta) {
 		StringBuilder ret = new StringBuilder();
 		genPackage(ret);
 		genImport(tableMeta, ret);