使用JFinal后,发现JFinal的实体类不需要get,set方法,通过使用实体类,就可以进行数据的CRUD,这是如何实现的呢?
com.jfinal.plugin.activerecord.Model,一切都是这个类的功劳。写实体类时,只要实现Model这个类,就可以轻松做到上面所说的功能。
其中
attrs 是 Map 类型,用来存储实体属性的键值对;
modifyFlag 是用来存储需要修改字段名的集合;
configName 是用来设置不同数据源名称,达到切换数据源的目的。
回到上面的问题,为什么我们写得实体可以不需要get、set 方法呢?
这是因为Model中定义了相应的 set 、 put和get 方法。
set和put方法类似,都是将指定的字段名和值存储到attrs中,不同的是set方法需要检查数据库表中是否存在相应的字段名。
get方法则是从attrs中取出相应字段名对应的值。
Model中的CURD
要保证数据库的CURD正常执行,需要 实体到表的关系映射、需要数据库的连接,当然也需要相应的实体数据。
实体数据是通过set 方式保存在 attrs中,做相应改变的字段保存在modifyFlag中。
数据库的连接是在过滤器启动的时候将数据源DataSource赋给了com.jfinal.plugin.activerecord.Config 并持有在DbKit的静态属性config中(可以参见上一篇文章)。
实体到表的关系映射上一篇文章没有详细讲,这里,来详细讲下:
主要涉及到3个类, Table、TableMapping、TableBuilder。
Table 存储了表名,主键,字段名和类型对应关系,实体类型。
表明和实体类型(name、modelClass)是在JFinalConfig类中设置ActiveRecordPlugin的时候添加的。
ActiveRecordPlugin arp = new ActiveRecordPlugin(cp);
me.add(arp);
arp.addMapping("t_user", User.class);
Table 中的字段名和类型对应关系主要是通过 TableBuilder 类中的build方法实现的。这个方法在ActiveRecordPlugin启动的时候被调用。
new TableBuilder().build(tableList, config);
build方法中,会查询数据库,使用的查询语句是
"select * from `" + tableName + "` where 1 = 2"
这种方式,可以查询出指定表的所有字段名和类型。
ResultSetMetaData rsmd = rs.getMetaData();
表字段名称和类型的对应关系建立后,会将Table存储到TableMapping的单例对象中。
Dialect对象
为了兼容多种数据库,定义了Dailect抽象类,其中定义了一些通用的抽象方法。不同的数据库分别对应它的一个子类,如下图,分别实现了这些抽象方法。
默认情况下,数据库是使用Mysql,我们可以在JFinalConfig配置类中修改数据库的Dialect。如:
@Override
public void configPlugin(Plugins me) {
C3p0Plugin cp = new C3p0Plugin("jdbc:mysql://localhost:3306/db_jfinal",
"root", "admin");
me.add(cp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(cp);
me.add(arp);
arp.addMapping("t_user", User.class);
arp.setDialect(new OracleDialect());
}