上周末应好友之邀写了一个 JF 多租户的 demo。在编写租户ActiveRecordPlugin时出现一个小灵感,以前我们自己使用的是一个模板数据库,用来做 Db启动 映射表字段类关系。
(PS:以前JF低版本有些方法未开放,也有写过一个插件https://jfinal.com/share/2508 )。
在 JF 高版本中这些set 方法已经开放可调用了。废话不多说了,上码:
还是官网的JFinal demo for maven 5.0.0 https://jfinal.com/download/now?file=jfinal_demo_for_maven-5.0.0.zip
1、自定义 mapping_kit_template.jf 模板:
package #(mappingKitPackageName); import com.jfinal.plugin.activerecord.*; /** * Generated by JFinal, do not modify this file. * <pre> * Example: * public void configPlugin(Plugins me) { * arp = new ActiveRecordPlugin(new NullDataSource(){ * public Connection getConnection() throws SQLException { * return dbp.getDataSource().getConnection(); * } * }); * #(mappingKitClassName).mapping(arp); * me.add(arp); * } * </pre> */ @SuppressWarnings("unchecked") public class #(mappingKitClassName) { public static void mapping(ActiveRecordPlugin arp) { Config config = arp.getConfig(); #for (tableMeta : tableMetas) #(tableMeta.name)(config); #end } #for (tableMeta : tableMetas) private static void #(tableMeta.name)(Config config) { #if (tableMeta.primaryKey.contains(",")) // Composite Primary Key order: #(tableMeta.primaryKey) #end Table t = new Table("#(tableMeta.name)", "#(tableMeta.primaryKey)", #(tableMeta.modelName).class); t.setColumnTypeMap(config.getContainerFactory().getAttrsMap()); #for(cm : tableMeta.columnMetas) t.setColumnType("#(cm.name)", #(cm.javaType).class); #end config(config, t); } #end private static void config(Config config, Table t) { TableMapping.me().putTable(t); CPI.addModelToConfigMapping(t.getModelClass(), config); } }
2、修改 _JFinalDemoGenerator.java 设置自定义模板 setMappingKitTemplate
// 自定义 _MappingKit 模板 支持免启动JF映射ColumnType generator.setMappingKitTemplate("/generator/mapping_kit_template.jf"); // 生成 generator.generate();
3、配置ActiveRecordPlugin 的方式:JFinalConfig 子类DemoConfig:
public void configPlugin(Plugins me) { DruidPlugin dp = new DruidPlugin("jdbc:mysql://localhost/db_name", "userName", "password"); me.add(dp); ActiveRecordPlugin arp = new ActiveRecordPlugin(new NullDataSource(){ public Connection getConnection() throws SQLException { return dp.getDataSource().getConnection(); } }); // 所有映射在 MappingKit 中自动化搞定 _MappingKit.mapping(arp); me.add(arp); }
可以看到 以前是 new ActiveRecordPlugin(dp) , 现在是用new NullDataSource包裹了一下。
4、运行 _JFinalDemoGenerator.java 生成新的 _MappingKit 类代码,看效果:
... @SuppressWarnings("unchecked") public class _MappingKit { public static void mapping(ActiveRecordPlugin arp) { Config config = arp.getConfig(); blog(config); } private static void blog(Config config) { Table t = new Table("blog", "id", Blog.class); t.setColumnTypeMap(config.getContainerFactory().getAttrsMap()); t.setColumnType("id", java.lang.Integer.class); t.setColumnType("title", java.lang.String.class); t.setColumnType("content", java.lang.String.class); config(config, t); } private static void config(Config config, Table t) { TableMapping.me().putTable(t); CPI.addModelToConfigMapping(t.getModelClass(), config); } }
可以看到 以前的 arp.addMapping("blog", "id", Blog.class); 被改为了调用 blog(config);方法
(也可把该代码生成到 BlogBaseModel中去,_MappingKit调用类方法,这个看自己喜好了)。
该方法把从数据库查询字段关系类映射到setColumnType,变为了 Java 执行setColumnType 字段与类关系代码。
好处很多,比如启动项目更快了,git代码仓库也有字段记录了,阅读代码更明晰了。。。
PS:https://jfinal.com/app/10057 官网Demo改造的多租户模式代码示例
aifei 也用了这种方式,启动速度更快了