JFinal极速开发框架使用笔记(三) 分析Model和ActiveRecord

时间:2023-03-09 05:58:38
JFinal极速开发框架使用笔记(三)  分析Model和ActiveRecord

JFinal框架的一些新发现的用法:

在JFinal框架中,实体类并不需要设置属性,更不需要配置getset方法就可以很方便的操作数据库,如果需要设置或者获取属性,可以直接使用一下方式:

User user = new User().set("id", "MY_SEQ.nextval").set("age", 18);
user.save();
// 获取id值
Integer id = user.get("id");

但是,如果有需要使用getset方法的情况,就可以使用JFinal框架中的生成器来方便的生成方法。

JFinal框架中的实体类以及getset方法生成器:

package com.demo.common.model;

import javax.sql.DataSource;
import com.demo.common.DemoConfig;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.generator.Generator;
import com.jfinal.plugin.druid.DruidPlugin; /**
* 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
* 详见 JFinal 俱乐部: http://jfinal.com/club
*
* 在数据库表有任何变动时,运行一下 main 方法,极速响应变化进行代码重构
*/
public class _JFinalDemoGenerator { public static DataSource getDataSource() {
PropKit.use("a_little_config.txt");
DruidPlugin druidPlugin = DemoConfig.createDruidPlugin();
druidPlugin.start();
return druidPlugin.getDataSource();
} public static void main(String[] args) {
// base model 所使用的包名
String baseModelPackageName = "com.demo.common.model.base";
// base model 文件保存路径
String baseModelOutputDir = PathKit.getWebRootPath() + "/../src/com/demo/common/model/base"; // model 所使用的包名 (MappingKit 默认使用的包名)
String modelPackageName = "com.demo.common.model";
// model 文件保存路径 (MappingKit 与 DataDictionary 文件默认保存路径)
String modelOutputDir = baseModelOutputDir + "/.."; // 创建生成器
Generator generator = new Generator(getDataSource(), baseModelPackageName, baseModelOutputDir, modelPackageName, modelOutputDir);
// 设置是否生成链式 setter 方法
generator.setGenerateChainSetter(false);
// 添加不需要生成的表名
generator.addExcludedTable("adv");
// 设置是否在 Model 中生成 dao 对象
generator.setGenerateDaoInModel(true);
// 设置是否生成链式 setter 方法
generator.setGenerateChainSetter(true);
// 设置是否生成字典文件
generator.setGenerateDataDictionary(false);
// 设置需要被移除的表名前缀用于生成modelName。例如表名 "osc_user",移除前缀 "osc_"后生成的model名为 "User"而非 OscUser
generator.setRemovedTableNamePrefixes("t_");
// 生成
generator.generate();
}
}

还需要在继承了JFinalConfig的主文件中设置:

    public static DruidPlugin createDruidPlugin() {
return new DruidPlugin(PropKit.get("jdbcUrl"), PropKit.get("user"), PropKit.get("password").trim());
}

JFinal框架向接受前台表单传过来的参数并增加有两种方法,一种是getBean方式,一种是getModel方式。

getModel方式用来接收表单域传过来的Model对象,表单域名称以”modelName.attrName”方式命名, getModel 使用的 attrName 必须与数据表字段名完全一样。

getBean 方法用于支持传统 Java Bean, 包括支持使用 jfnal 生成器生成了 getter、 setter 方法的 Model, 页面表单传参时使用与 setter 方法相一致的 attrName,而非数据表字段名。getModel 与 getBean 区别在于前者使用数表字段名而后者使用与 setter 方法一致的属性名进行数据注入。

除了这个之外,JFinal还可以通过使用空字符串“”实现,表单域中使用正常方式提交,不用加前缀,在后台接受时,使用getModel方法,加一个“”,就可以正常接收数据了。

   @Before(StudentTestValidator2.class)
public void savebeanscore(){
StudentTest st=getModel(StudentTest.class,"");
st.save();
redirect("/student/layui");
}

同样的,JFinal这种方式也可以在表单域中设置专门的前缀,然后再后台用同样的方式用该前缀参数使用getModel方式接受。

ActiveRecord

ActiveRecord 是 JFinal 最核心的组成部分之一,通过 ActiveRecord 来操作数据库, 将极大地减少代码量,极大地提升开发效率。

ActiveRecord 是作为 JFinal 的 Plugin 而存在的,所以使用时需要在 JFinalConfig 中配置ActiveRecordPlugin。

    public void configPlugin(Plugins me) {

//        C3p0Plugin  cp  =  new  C3p0Plugin("jdbc:mysql://localhost/db_name",
// "userName", "password");
// me.add(cp); loadPropertyFile("a_little_config.txt"); DruidPlugin dp = new DruidPlugin(getProperty("jdbcUrl"),
getProperty("user"), getProperty("password"));
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
me.add(arp);
arp.setDialect(new MysqlDialect()); arp.addMapping("blog","id", Blog.class);
arp.addMapping("student","studentid", Student.class);
arp.addMapping("studenttest","id", StudentTest.class);
/*DruidPlugin dp = new DruidPlugin(getProperty("jdbcUrl"),
getProperty("user"), getProperty("password"));
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
me.add(arp);
//arp.addMapping("blog", "id", Blog.class);
arp.addMapping("student", "studentid", Student.class);
//arp.addMapping("studenttest", "id", StudentTest.class);
*/
// 此方法用来配置JFinal的Plugin,如下代码配置了Druid数据库连接池插件与ActiveRecord
// 数据库访问插件。通过以下的配置,可以在应用中使用 ActiveRecord 非常方便地操作数据库。
}

DruidPlugin是druid数据源插件,

ActiveRecordPlugin后者是ActiveRecrod 支持插件。

ActiveReceord 中定义了 addMapping(String tableName, Class<?extends Model> modelClass>)方法,该方法建立了数据库表名到 Model 的映射关系。

另外,以上代码中 arp.addMapping(“user”, User.class),表的主键名为默认为“id”,如果主键名称为 “user_id”则需要手动指定,如: arp.addMapping(“user”, “user_id”, User.class)。

ActiveRecord中的Model

Model 是 ActiveRecord 中最重要的组件之一, 它充当 MVC 模式中的 Model 部分。

public class StudentTest extends Model<StudentTest> {
/**
*
*/
private static final long serialVersionUID = 1L;
public static final StudentTest dao = new StudentTest();
}

以上代码中继承 Model,便立即拥有的众多方便的操作数据库的方法。在类中声明的 dao 静态对象是为了方便查询操作而定义的,该对象并不是必须的。基于 ActiveRecord的 Model 无需定义属性, 无需定义 getter、 setter 方法,无需 XML 配置,无需 Annotation 配置,极大降低了代码量。

JFinal极速开发框架使用笔记(三)  分析Model和ActiveRecord

特别注意: User 中定义的 public static final User dao 对象是全局共享的, 只能用于数据库查询,不能用于数据承载对象。 数据承载需要使用 new User().set(…)来实现。

JFinal 独创 Db + Record 模式

Db 类及其配套的 Record 类, 提供了在 Model 类之外更为丰富的数据库操作功能。 使用Db 与 Record 类时,无需对数据库表进行映射, Record 相当于一个通用的 Model。 以下为 Db +Record 模式的一些常见用法:

JFinal极速开发框架使用笔记(三)  分析Model和ActiveRecord

JFinal极速开发框架使用笔记(三)  分析Model和ActiveRecord

Dialect 多数据库支持 

目 前 ActiveRecordPlugin 提 供 了 MysqlDialect 、 OracleDialect 、 PostgresqlDialect 、SqlServerDialect、 Sqlite3Dialect、 AnsiSqlDialect 实现类。 MysqlDialect 与 OracleDialect 分别实现对 Mysql 与 Oracle 的支持, AnsiSqlDialect 实现对遵守 ANSI SQL 数据库的支持。 以下是数据库 Dialect 的配置代码:

    public void configPlugin(Plugins me) {

//        C3p0Plugin  cp  =  new  C3p0Plugin("jdbc:mysql://localhost/db_name",
// "userName", "password");
// me.add(cp); loadPropertyFile("a_little_config.txt"); DruidPlugin dp = new DruidPlugin(getProperty("jdbcUrl"),
getProperty("user"), getProperty("password"));
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
me.add(arp);
arp.setDialect(new MysqlDialect()); arp.addMapping("blog","id", Blog.class);
arp.addMapping("student","studentid", Student.class);
arp.addMapping("studenttest","id", StudentTest.class);
/*DruidPlugin dp = new DruidPlugin(getProperty("jdbcUrl"),
getProperty("user"), getProperty("password"));
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
me.add(arp);
//arp.addMapping("blog", "id", Blog.class);
arp.addMapping("student", "studentid", Student.class);
//arp.addMapping("studenttest", "id", StudentTest.class);
*/
// 此方法用来配置JFinal的Plugin,如下代码配置了Druid数据库连接池插件与ActiveRecord
// 数据库访问插件。通过以下的配置,可以在应用中使用 ActiveRecord 非常方便地操作数据库。
}

表关联操作

JFinal ActiveRecord 天然支持表关联操作,并不需要学习新的东西, 此为无招胜有招。 表关联操作主要有两种方式:一是直接使用 sql 得到关联数据;二是在 Model 中添加获取关联数据的方法。

假定现有两张数据库表: user、 blog,并且 user 到 blog 是一对多关系, blog 表中使用 user_id关联到 user 表。如下代码演示使用第一种方式得到 user_name:

public void relation() {
String sql = "select b.*, u.user_name from blog b inner
join user u on b.user_id=u.id where b.id=?";
Blog blog = Blog.dao.findFirst(sql, 123);
String name = blog.getStr("user_name");
}

以下代码演示第二种方式在 Blog 中获取相关联的 User 以及在 User 中获取相关联的 Blog:

public class Blog extends Model<Blog>{
public static final Blog dao = new Blog();
public User getUser() {
return User.dao.findById(get("user_id"));
}
}
public class User extends Model<User>{
public static final User dao = new User();
public List<Blog> getBlogs() {
return Blog.dao.find("select * from blog where user_id=?",
get("id"));
}
}

复合主键

JFinal ActiveRecord 从 2.0 版本开始, 采用极简设计支持复合主键,对于 Model 来说需要在映射时指定复合主键名称,以下是具体例子:

ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
// 多数据源的配置仅仅是如下第二个参数指定一次复合主键名称
arp.addMapping("user_role", "userId, roleId", UserRole.class);
//同时指定复合主键值即可查找记录
UserRole.dao.findById(123, 456);
//同时指定复合主键值即可删除记录
UserRole.dao.deleteById(123, 456);

如上代码所示,对于 Model 来说,只需要在添加 Model 映射时指定复合主键名称即可开始使用复合主键, 在后续的操作中 JFinal 会对复合主键支持的个数进行检测,当复合主键数量不正确时会报异常,尤其是复合主键数量不够时能够确保数据安全。 复合主键不限定只能有两个,可以是数据库支持下的任意多个。对于 Db + Record 模式来说,复合主键的使用不需要配置,直接用即可:

Db.findById("user_role", "roleId, userId", 123, 456);
Db.deleteById("user_role", "roleId, userId", 123, 456);

其他的JFinal的ActiveRecord得用法,如分页等等,就不一一记录了,可以参考JFinal官方文档。