最近在使用generator生成model代码的时候,发现三个可以考虑考虑一下的点。
第一个是无主键的表想生成一个model方便操作(但不使用model的save/delete/update等隐含使用了primary key的方法),就当作POJO使用,这时候生成器默认是不生成的,需要继承MetaBuilder,覆盖removeNoPrimaryKeyTable方法来实现,如果可以给一个开关,比如在generator上加上一个allowNoPrimaryKey(boolean allow),这样就简单多了。
@Override
protected void removeNoPrimaryKeyTable(List<TableMeta> ret) {
// allow no primary key tables to generate
}
第二个是数据库为postgresql,且字段为jsonb的时候,目前generator生成的BaseModel代码里,字段java类型会为java.lang.String,而不是期待的PGobject(Record里取出来的值类型就是PGobject),如果jdbc url里不添加参数stringtype=unspecified的话,插入/更新jsonb字段会失败,而加上这个参数可能会有一些未知的影响,但我没有深入去调研。所以我就继续继承MetaBuilder类,覆盖buildColumnMetas(TableMeta tableMeta)方法,在以下这几行代码
if (typeStr == null) {
String colClassName = rsmd.getColumnClassName(i);
typeStr = typeMapping.getType(colClassName);
}
前面(jfinal 5.0.0 版本源码 MetaBuilder 的385行代码前)添加如下代码:
if (typeStr == null) {
String type = rsmd.getColumnTypeName(i);
if ("jsonb".equalsIgnoreCase(type)) {
typeStr = "org.postgresql.util.PGobject";
}
}
这样生成的代码里,jsonb字段就可以直接生成为PGobject的字段了,当然,这个Model就限制了只能用postgresql数据库了,如果项目限制了只使用postgresql的话,那就不是什么问题。如果在JFinal源码里直接加上面那代码代码,或者不是什么好主意,但是MetaBuilder可以添加一个protected的空方法,入参为ResultSetMetaData,在
if (typeStr == null) {
String colClassName = rsmd.getColumnClassName(i);
typeStr = typeMapping.getType(colClassName);
}
前调用,这样就可以让代码生成的业务方有机会自己处理像jsonb这样的特殊字段类型了。
第三个是关于绑定,Model在调用ActiveRecordPlugin.addMapping前是不可用的,但对于一些特殊情况,如一些分库分表的规则下,表名是变的,也不是绑定时就可以确定的,但这种情况下,如果语句是程序写好的,不需要model自动确定表名、primary key等,只使用find(String sql)这类方法方便操作,model就当成是升级版的Record的情况来使用,保存或者修改的时候,则使用model.toRecord()变成Record来处理,这种情况下,如果想使用Model就不那么容易了,有以下两个方法:
1. 使用model前,调用model.use("main")绑定数据源
2. 更改生成模板,让每个BaseModel添加以下方法:
@Override
protected Config _getConfig() {
Config config = super._getConfig();
if (config == null) {
config = DbKit.getConfig("main");
}
return config;
}
如果可以,其实是否可以让Model的_getConfig()方法内就实现这个找不到配置就用main配置作保底呢?
generator.setGenerateView(true);
第二个问题,jsonb 的处理,可以添加一个 labmda 回调来处理,麻烦在 gitee 添加一个 issue:
https://gitee.com/jfinal/jfinal/issues
第三个问题,不太好做,字段名与 base model 中的 setter、getter 方法是相对应的。这种需求正好是 Db + Record 的应用场景