一、JFinal相关基础知识
jfinal是一个相对较新的ORM框架,开始配置Jfinal连接KingbaseES之前,先简单介绍一个JFinal框架相关基础知识。
什么是 ORM 框架?
ORM(Object Relational Mapping)框架采用元数据来描述对象与关系映射的细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。
只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。当前ORM框架主要有五种:Hibernate(Nhibernate),iBATIS,mybatis,EclipseLink,JFinal。
ORM是通过使用描述对象和数据库之间映射的元数据,在我们想到描述的时候自然就想到了xml和特性(Attribute).目前的ORM框架中,Hibernate就是典型的使用xml文件作为描述实体对象的映射框架,而大名鼎鼎的Linq则是使用特性(Attribute)来描述的。
JFinal框架简介
JFinal 是基于 Java 语言的极速 WEB + ORM + AOP + Template Engine 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python、php等动态语言的开发效率!
JFinal有如下主要特点:
MVC架构,设计精巧,使用简单
遵循COC原则(Convention over Configuration惯例优于配置原则),支持零配置,无xml
独创Db + Record模式,灵活便利
ActiveRecord支持,使数据库开发极致快速
自动加载修改后的java文件,开发过程中无需重启web server
AOP支持,拦截器配置灵活,功能强大
Plugin体系结构,扩展性强
多视图支持,支持FreeMarker、JSP、Velocity
强大的Validator后端校验功能
功能齐全,拥有struts2的绝大部分功能
体积小仅 723 KB,且无第三方依赖
JFinal ORM和Hibernate简要对比
JFinal采用ActiveRecord实现数据库操作支持,较Hibernate开发效率提升六到十倍。
JFinal ActiveRecord较Hibernate学习成本低,一小时内能上手开发。
JFinal零配置,对数据库支持五个无特点:无xml、无annotation、无getter、无setter、无attribute,极大降低了代码量,统计证实代码量节省70%到95%。
JFinal数据库操作完全采用原生sql,相对Hibernate采用的HQL学习成本低,功能更强大,性能更高,稳定性好。
二、 JFinal使用
Jfinal操作数据库配置相关的几个核心类: JFinalConfig、DruidPlugin、ActiveRecordPlugin、ActiveRecord
JFinalConfig概述
基于JFinal的web项目需要创建一个继承自JFinalConfig类的子类,该类用于对整个web项目进行配置。
JFinalConfig子类需要实现六个抽象方法,如下所示:
public class DemoConfig extends JFinalConfig {
public void configConstant(Constants me) {
}
public void configRoute(Routes me) {
}
public void configEngine(Engine me) {
}
public void configPlugin(Plugins me) {
} //数据库相关DruidPlugin配置
public void configInterceptor(Interceptors me) {
}
public void configHandler(Handlers me) {
}
}
ActiveRecord
ActiveRecord 是 JFinal 最核心的组成部分之一,通过 ActiveRecord 来操作数据库,将极大地减少代码量,极大地提升开发效率。
ActiveRecord 模式的核心是:一个 Model 对象唯一对应数据库表中的一条记录,而对应关系依靠的是数据库表的主键值。
因此,ActiveRecord 模式要求数据库表必须要有主键。当数据库表没有主键时,只能使用 Db + Record 模式来操作数据库。
ActiveRecordPlugin
ActiveRecord是作为JFinal的Plugin而存在的,所以使用时需要在JFinalConfig中配置ActiveRecordPlugin。
以下是Plugin配置示例代码:
public class DemoConfig extends JFinalConfig {
public void configPlugin(Plugins me) {
DruidPlugin dp = new DruidPlugin("jdbc:kingbase8://localhost/db_name", "userName", "password");
//druidPlugin通过Url前缀判定数据库类型,Druid官方配置只适配了V7,只识别前缀jdbc:kingbase,遇见前缀jdbc:kingbase8,会认为是Unknow databaseType导致找不到驱动类, 需要手动指定DriverClass
dp.setDriverClass("com.kingbase8.Driver");
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
me.add(arp);
arp.addMapping("user", User.class);
arp.addMapping("article", "article_id", Article.class);
}
}
以上代码配置了两个插件:DruidPlugin与ActiveRecordPlugin,前者是druid数据源插件,后者是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)。
Model
Model是ActiveRecord中最重要的组件之一,它充当MVC模式中的Model部分。以下是Model定义示例代码:
public class User extends Model<User> {
public static final User dao = new User().dao();
}
以上代码中的User通过继承Model,便立即拥有的众多方便的操作数据库的方法。在User中声明的dao静态对象是为了方便查询操作而定义的,该对象并不是必须的。基于ActiveRecord的Model无需定义属性,无需定义getter、setter方法,无需XML配置,无需Annotation配置,极大降低了代码量。
以下为Model的一些常见用法:
// 创建name属性为James,age属性为25的User对象并添加到数据库
new User().set("name", "James").set("age", 25).save();
// 删除id值为25的User
User.dao.deleteById(25);
// 查询id值为25的User将其name属性改为James并更新到数据库
User.dao.findById(25).set("name", "James").update();
// 查询id值为25的user, 且仅仅取name与age两个字段的值
User user = User.dao.findByIdLoadColumns(25, "name, age");
// 获取user的name属性
String userName = user.getStr("name");
// 获取user的age属性
Integer userAge = user.getInt("age");
// 查询所有年龄大于18岁的user
List<User> users = User.dao.find("select * from user where age>18");
// 分页查询年龄大于18的user,当前页号为1,每页10个user
Page<User> userPage = User.dao.paginate(1, 10, "select *", "from user where age > ?", 18);
Dialect多数据库支持
目前ActiveRecordPlugin提供了MysqlDialect、OracleDialect、PostgresqlDialect、SqlServerDialect、Sqlite3Dialect、AnsiSqlDialect实现类。MysqlDialect与OracleDialect分别实现对Mysql与Oracle的支持,AnsiSqlDialect实现对遵守ANSI SQL数据库的支持。以下是数据库Dialect的配置代码:
金仓数据库KingbaseES V8可以使用PostgresqlDialect
public class DemoConfig extends JFinalConfig {
public void configPlugin(Plugins me) {
ActiveRecordPlugin arp = new ActiveRecordPlugin(…);
me.add(arp);
// 配置kingbase方言,经测试KingbaseES可以使用PostgresqlDialect,需要配置大小写不敏感
arp.setContainerFactory(new CaseInsensitiveContainerFactory(true));
arp.setDialect(new PostgresqlDialect());
}
}
测试工程
测试环境:
开发工具:MyEclipse 2018
JDK版本: 1.8.0_77
Maven版本: 3.6.3
数据库: KingbaseES V8(大小写不敏感)
JFinal版本:4.9
Druid版本:1.1.22
依赖库配置pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.qin</groupId>
<artifactId>JfinalTest</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<jdk.version>1.8</jdk.version>
<junit.version>3.8.1</junit.version>
<jfinal.version>4.9</jfinal.version>
<apachelog4j.version>2.11.1</apachelog4j.version>
<log4j.version>1.2.17</log4j.version>
<druid.version>1.1.22</druid.version>
<postgresql.version>42.2.6</postgresql.version>
</properties>
<dependencies>
<dependency>
<groupId>com.kingbase8</groupId>
<artifactId>kingbase8</artifactId>
<version>8.2.0</version>
<scope>system</scope>
<systemPath>E:/apache-maven-3.6.3/repository/com/kingbase8/kingbase8/kingbase8-8.2.0.jar</systemPath>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal</artifactId>
<version>${jfinal.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
</dependencies>
<build>
<finalName>JFinalTest</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
<!-- java8 保留参数名编译参数 -->
<compilerArgument>-parameters</compilerArgument>
<compilerArguments>
<verbose />
</compilerArguments>
</configuration>
</plugin>
<!-- jar 包中的配置文件优先级高于 config 目录下的 "同名文件" 因此,打包时需要排除掉 jar 包中来自 src/main/resources
目录的 配置文件,否则部署时 config 目录中的同名配置文件不会生效 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<configuration>
<excludes>
<exclude>*.txt</exclude>
<exclude>*.xml</exclude>
<exclude>*.properties</exclude>
</excludes>
</configuration>
</plugin>
<!-- 使用 mvn clean package 打包 更多配置可参考官司方文档:http://maven.apache.org/plugins/maven-assembly-plugin/single-mojo.html -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<!-- 打包生成的文件名 -->
<finalName>${project.artifactId}</finalName>
<!-- jar 等压缩文件在被打包进入 zip、tar.gz 时是否压缩,设置为 false 可加快打包速度 -->
<recompressZippedFiles>false</recompressZippedFiles>
<!-- 打包生成的文件是否要追加 release.xml 中定义的 id 值 -->
<appendAssemblyId>true</appendAssemblyId>
<!-- 指向打包描述文件 package.xml -->
<descriptors>
<descriptor>package.xml</descriptor>
</descriptors>
<!-- 打包结果输出的基础目录 -->
<outputDirectory>${project.build.directory}/</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
测试主程序
import java.util.List;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.CaseInsensitiveContainerFactory;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.dialect.PostgreSqlDialect;
import com.jfinal.plugin.druid.DruidPlugin;
public class JFinalTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
DruidPlugin dp = new DruidPlugin("jdbc:kingbase8://192.168.184.132:54321/TEST", "SYSTEM", "******");
ActiveRecordPlugin arp=new ActiveRecordPlugin(dp);
arp.addMapping("USER1","user_id", User1.class);
dp.setDriverClass("com.kingbase8.Driver");
arp.setContainerFactory(new CaseInsensitiveContainerFactory(true)); //设置应用中字估名大小写不敏感
arp.setDialect(new PostgreSqlDialect()); //kingbase设置大小写不敏感,可以使用postgresqlDialect
dp.start();
arp.start();
// User1 info1=new User1().set("name", "Lilei").set("AGE", 27); //插入数据
// info1.save();
// User1.dao.deleteById(3); //删除数据
// User1.dao.findById("6").set("AGE","30").update();
// User1 user = User1.dao.findByIdLoadColumns(6, "name, age");
// String userName = user.getStr("name");
// Integer userAge = user.getInt("age");
// System.out.println("name="+userName+";userAge="+userAge+";");
Page<User1> userPage = User1.dao.paginate(1, 3, "select *", "from user1 where age > ?", 18);
List<User1> ul=userPage.getList();
for(User1 s: ul){
System.out.println(s.getInt("user_id")+" "+s.getStr("name")+" "+s.getInt("age"));
}
}
}
参考文献:
1、https://jfinal.com/doc
2、https://jfinal.com/project/1
3、https://baike.baidu.com/item/JFinal/9383157?fr=aladdin