以mysql数据库实现为例,其它的db也可基于这种方式自己实现
大概的思路是这样的,为了简少配置,所以不使用注解的方式
首先需要一个工具类来拿到所有的Model类大体的实现方式如下
package com.nmtx.utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.StrKit;
public class ClassUtils {
public static String classRootPath = null;
public static List<Class<?>> scanPackage(String packageName) throws ClassNotFoundException {
List<Class<?>> classList = new ArrayList<Class<?>>();
String path = getClassRootPath() + "/" + packageName.replace(".", "/");
List<String> fileNameList = getAllFileName(path);
for (String fileName : fileNameList) {
classList.add(Class.forName(fileName));
}
return classList;
}
public static List<String> getAllFileName(String path) {
List<String> fileNameList = new ArrayList<String>();
File rootFile = new File(path);
if (rootFile.isFile()) {
String fileName = rootFile.getPath().replace(PathKit.getRootClassPath(), "").replace(File.separator, ".")
.replaceFirst(".", "");
String prefix = fileName.substring(fileName.lastIndexOf(".") + 1);
if (prefix.equals("class")) {
fileNameList.add(fileName.substring(0, fileName.lastIndexOf(".")));
}
} else {
File[] files = rootFile.listFiles();
if (files != null) {
for (File file : files) {
fileNameList.addAll(getAllFileName(file.getPath()));
}
}
}
return fileNameList;
}
public static String getClassRootPath() {
if (StrKit.isBlank(classRootPath))
classRootPath = PathKit.getRootClassPath();
return classRootPath;
}
public static void setClassRootPath(String classRootPath) {
ClassUtils.classRootPath = classRootPath;
}
}
有了工具类,就去处理自动扫描插件,大概实现是这样的
package com.nmtx.plugins.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.IPlugin;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.c3p0.C3p0Plugin;
import com.nmtx.plugins.db.impl.TableToModelByUnderline;
import com.nmtx.utils.ClassUtils;
public class AutoTabelPlugin implements IPlugin {
private String db;
private ActiveRecordPlugin arp;
private String pacekageName;
private String idKey;
private ITableToModelFormat tableToModelFormate;
private C3p0Plugin c3p0Plugin;
public AutoTabelPlugin(C3p0Plugin erpC3p0, ActiveRecordPlugin arp, String db, String packageName, String idKey,
ITableToModelFormat tableToModelFormate) {
this.db = db;
this.arp = arp;
this.idKey = idKey;
this.tableToModelFormate = tableToModelFormate;
this.c3p0Plugin = erpC3p0;
}
public AutoTabelPlugin(C3p0Plugin erpC3p0, ActiveRecordPlugin arp, String db, String packageName, String idKey) {
this.db = db;
this.arp = arp;
this.idKey = idKey;
this.pacekageName = packageName;
this.tableToModelFormate = new TableToModelByUnderline();
this.c3p0Plugin = erpC3p0;
}
@SuppressWarnings({ "unchecked" })
public List<Class<? extends Model<?>>> getModelClass() throws ClassNotFoundException {
List<Class<?>> classes = ClassUtils.scanPackage(pacekageName);
List<Class<? extends Model<?>>> modelClasses = new ArrayList<Class<? extends Model<?>>>();
for (Class<?> classer : classes) {
modelClasses.add((Class<? extends Model<?>>) classer);
}
return modelClasses;
}
public boolean start() {
try {
HashMap<String, String> tableMap = getTableMap();
List<Class<? extends Model<?>>> modelClasses = getModelClass();
for (Class<? extends Model<?>> modelClass : modelClasses) {
String tableName = tableMap.get(modelClass.getSimpleName());
if (tableName != null) {
if (StrKit.notBlank(idKey)) {
arp.addMapping(tableName, idKey, modelClass);
} else {
arp.addMapping(tableName, modelClass);
}
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException("auto table mappming is exception" + e);
}
return true;
}
/**
* 获取Model和表名的映射
*
* @return
*/
private HashMap<String, String> getTableMap() {
HashMap<String, String> map = new HashMap<String, String>();
Connection connection = null;
PreparedStatement preStatement = null;
ResultSet resultSet = null;
try {
c3p0Plugin.start();
connection = c3p0Plugin.getDataSource().getConnection();
preStatement = connection.prepareStatement(
"select table_name as tableName from information_schema.tables where table_schema='" + db
+ "' and table_type='base table'");
resultSet = preStatement.executeQuery();
while (resultSet.next()) {
String tableName = resultSet.getString(1);
map.put(tableToModelFormate.getTableByModel(tableName), tableName);
}
} catch (Exception e) {
closeConnection(connection, preStatement, resultSet);
throw new RuntimeException("auto table mappming is exception" + e);
} finally {
closeConnection(connection, preStatement, resultSet);
}
return map;
}
private void closeConnection(Connection connection, PreparedStatement preStatement, ResultSet resultSet) {
try {
if (resultSet != null) {
resultSet.close();
}
if (preStatement != null) {
preStatement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
throw new RuntimeException("auto close db connection is exception" + e);
}
}
public boolean stop() {
return true;
}
}
因为java里的属性一般都是驼峰规则,代码看起来舒服一点,这里以数据库中以大写字母为例,表名为T_USER,对应Model名为User实现如下
接口定义
package com.nmtx.plugins.db;
public interface ITableToModelFormat {
public String generateTableNameToModelName(String tableName);
}
实现如下
package com.nmtx.plugins.db.impl;
import com.nmtx.plugins.db.ITableToModelFormat;
public class TableToModelByUnderline implements ITableToModelFormat{
public String generateTableNameToModelName(String tableName) {
StringBuilder modelName = new StringBuilder();
tableName = tableName.substring(2).toLowerCase();
String tableNames[] = tableName.split("_");
for(String tableNameTemp:tableNames){
modelName.append(fisrtStringToUpper(tableNameTemp));
}
return modelName.toString();
}
private String fisrtStringToUpper(String string){
return string.replaceFirst(string.substring(0, 1),string.substring(0, 1).toUpperCase());
}
}
如果不同的格式可以实现不同的方法,根据自己的需求,这样就完成了自动扫描插件,使用起来也方便如下
C3p0Plugin spuC3p0= new C3p0Plugin(getProperty("jdbc.mysql.url"),
getProperty("jdbc.mysql.username").trim(), getProperty("jdbc.mysql.password").trim(),
getProperty("jdbc.mysql.driverClass"));
spuC3p0.setMaxPoolSize(Integer.parseInt(getProperty("jdbc.mysql.maxPool")));
spuC3p0.setMinPoolSize(Integer.parseInt(getProperty("jdbc.mysql.minPool")));
spuC3p0.setInitialPoolSize(Integer.parseInt(getProperty("jdbc.mysql.initialPoolSize")));
ActiveRecordPlugin spuArp = new ActiveRecordPlugin(DbConfigName.SPU, spuC3p0);
AutoTabelPlugin spuAutoTabelPlugin = new AutoTabelPlugin(spuC3p0, spuArp, getProperty("jdbc.mysql.spu.db"),
"com.nmtx.manager.model", "ID");
me.add(spuAutoTabelPlugin);
me.add(spuArp);
如果有多个就可以配置多个插件,而无需在管映射了,新增Model直接新增即可,不要再管映射