1. 程式人生 > 其它 >JFinal極速開發框架使用筆記(三) 分析Model和ActiveRecord

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 配置,極大降低了程式碼量。

特別注意: User 中定義的 public static final User dao 物件是全域性共享的, 只能用於資料庫查詢,不能用於資料承載物件。 資料承載需要使用 new User().set(…)來實現。

JFinal 獨創 Db + Record 模式 

Db 類及其配套的 Record 類, 提供了在 Model 類之外更為豐富的資料庫操作功能。 使用Db 與 Record 類時,無需對資料庫表進行對映, Record 相當於一個通用的 Model。 以下為 Db +Record 模式的一些常見用法: 

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官方文件。