關於Android數據庫orm工具庫對比的幾點思考(四)

一、ActiveAndroid的簡介

ActiveAndroid
Android Sqlite orm 的 db 工具類
項目地址:https://github.com/pardom/ActiveAndroid
文檔介紹:https://github.com/pardom/ActiveAndroid/wiki/_pages

ActiveAndroid算是一個輕量級的ORM框架,簡單地通過如save()和delete()等方法來做到增刪改查等操作。配置起來也還算簡單。但是有心的人會發現,進入github會看到,這個框架最後提交是在2014年7月,也就是說已經距離現在已經兩年沒有更新了,那,有人又會奇怪了,爲什麼已經沒有更新的框架我還要拿來寫文,原因無他,它之前火過,我們總是追求更快更好更新順應時代的事物,然而這些都是源於之前的對比,纔會不斷推陳出新,所以,今天的主角我選擇它。

二、ActiveAndroid的使用

(一)配置

在AndroidManifest.xml中需要添加數據庫名和版本號。

  • AA_DB_NAME (數據庫名,這個name不能改,但是是可選的,如果不寫的話 是默認的”Application.db”這個值)
  • AA_DB_VERSION (默認是1)
<manifest ...>
    <application android:name="com.activeandroid.app.Application" ...>

        ...

        <meta-data android:name="AA_DB_NAME" android:value="Pickrand.db" />
        <meta-data android:name="AA_DB_VERSION" android:value="5" />
    </application>
</manifest>

在AndroidManifest.xml文件中指定application元素的name爲 com.activeandroid.app.Application,如果需要自定義Application,需要讓你的Application對象繼 承自com.activeandroid.app.Application而不是android.app.Application。

public class MyApplication extends SomeLibraryApplication {
    @Override
    public void onCreate() {
        super.onCreate();
        ActiveAndroid.initialize(this);
    }
    @Override
    public void onTerminate() {
        super.onTerminate();
        ActiveAndroid.dispose();
    }
}

如果你需要繼承其他庫 的Application,則需要在Application中初始化和處理ActiveAndroid。如上,ActiveAndroid.initialize(this);做初始化工作,ActiveAndroid.dispose();做清理工作。

(二)創建model

@Table(name = "Items")
public class Item extends Model {
    // 這樣可以避免重複
    @Column(name = "remote_id", unique = true, onUniqueConflict = Column.ConflictAction.REPLACE)
    public int remoteId;
    @Column(name = "Name")
    public String name;
    @Column(name = "Category")
    public Category category;
    // 確保每個model類中都有一個默認的構造方法
    public Item(){
       super();
    }
    public Item(String remoteId, String name, Category category){
        super();
        this.remoteId = remoteId;
        this.name = name;
        this.category = category;
    }
}

@Table(name = “Items”)來表示表,使用@Column(name = “Name”)來表示列,ActiveAndroid會使用自增長的ID作爲主鍵,然後按照註解描述,將類對應映射爲數據庫表。

這個Item類中包含了一個Category類型的對象,這其中又包含了一個Entry對象。

@Table(name = "Categories")
public class Category extends Model {
    @Column(name = "remote_id", unique = true, onUniqueConflict = Column.ConflictAction.REPLACE)
    public int remoteId;
    @Column(name = "Name")
    public String name;
    @Column(name = "Entry")
    public Entry entry;
    public Category(){
       super();
    }
    public void saveEntry() {
        if (entry != null) {
            entry.save();
        }
    }
    public List<Item> data;
    // 使用外鍵,實現一對多存儲
    public List<Item> items() {
        data = getMany(Item.class, "Category");
    }
}
@Table(name = "Entrys")
public class Entry extends Model {
    @Column(name = "Name")
    public String name;
}

在這個框架中,一個對象中包含一個List對象,其實就是把List對象全部存到另一個表裏,通過外鍵來關聯。

(三)增刪改查

保存和更新數據到數據庫

1. 單條插入
保存一條記錄,只需要創建一個模型的實例,併爲每個字段指定值,然後調用save()方法。

Category restaurants = new Category();
restaurants.name = "Restaurants";
restaurants.save();

2. 批量插入
如果你要批量插入數據,最好使用事務(transaction)。

ActiveAndroid.beginTransaction();
try {
        for (int i = 0; i < 100; i++) {
            Item item = new Item();
            item.name = "Example " + i;
            item.save();
        }
        ActiveAndroid.setTransactionSuccessful();
}
finally {
        ActiveAndroid.endTransaction();
}

這裏需要注意的是Item類中包含Category對象,Category類中包含Entry對象。必須先保存Entry對象,Entry對象會得到一個Id,然後才能存儲Category對象,否則Category對象中的Entry對象就會爲null。

刪除記錄

我們有三種方式刪除一條記錄
調用delete()方法就可以刪除一條記錄,下面的例子中,通過id加載一個Item對象,並且刪除他。

Item item = Item.load(Item.class, 1);
item.delete();

也可以通過靜態方法刪除

Item.delete(Item.class, 1);

也可以創建調用Delete對象刪除

new Delete().from(Item.class).where("Id = ?", 1).execute();

更新記錄

new Update(Person.class).set("age=?," + "name=?", age, name).execute();

查詢數據庫

1.查詢一條

public static Item getRandom(Category category) {
    return new Select()
        .from(Item.class)
        .where("Category = ?", category.getId())
        .orderBy("RANDOM()")
        .executeSingle();
}

2.查詢所有

public static List<Item> getAll(Category category) {
    return new Select()
        .from(Item.class)
        .where("Category = ?", category.getId())
        .orderBy("Name ASC")
        .execute();
}

執行一個Select方法,指定表Item.class,限定條件where(“Category = ?”, category.getId()),排序爲orderBy(“Name ASC”),取出個數爲limit(num)
當然還支持其他非常多的指令。

  • limit
  • offset
  • as
  • desc/asc
  • inner/outer/cross join
  • group by

具體使用還是看自己的需求咯!

三、世紀大對比

1.ActiveAndroidOrmLite

作爲一個輕量級的ORM框架,在快速開發中,應用起來還是很方便的,比ORMLite要簡單一些,但某些細節不如ORMLite更強大,不如對象中包含對象時,ORMLite中可以有參數設定自動創建,而不是需要我們手動執行下sava,也許在ActiveAndroid中也可以這樣,但目前我沒搞明白註解中另幾個屬性的意思。整體性能經測試(100條Category數據,300條Item數據,100條Entry數據)存儲耗時1.1s-1.2s,與ORMLite是持平的,但也許是測試數據太小了,沒有說服性,有時間可以進行10w條數據的測試。

2.ActiveAndroidRealm

ActiveAndroid,這是一個很傳統的ORM框架,不過無論是與Gson的配合使用,還是連接查詢或者分頁查詢,傳統數據庫的理念它都能支持的很好。無奈的是這個項目在GitHub上的最近更新時間還是在兩年前,它對AndroidStudio的InstantRun特性支持的不是很好,強行使用的話可能會報錯誤。
第二點是它的版本升級策略做的不好,不能做到跨版本升級,目前的做法只能是升級APP的後如果檢測到先前的版本就卸載然後重裝,原先的數據只能丟失了。這樣簡單粗暴的做法自然不是長久之計。
第三點是不能查詢個別列,將所有字段都查出來既浪費時間,又浪費空間。

Realm,效率高,因爲是自己實現的C++數據庫,與SQLite底層使用java不同,它天生就比其高效快速。維護Realm數據庫還能帶來平臺無關性,iOS、Android等平臺都可以共享數據庫。
Auto-Refresh,Realm爲每個實體創建了代理類,並且實現了其Getter/Setter,因此,每次得到或者修改實體的值,都是直接對底層數據庫進行的操作。

3.GreenDaoORMLite

簡單的講,greenDAO 是一個將對象映射到 SQLite 數據庫中的輕量且快速的 ORM 解決方案。

優點:
1.greenDAO 性能遠遠高於同類的 ORMLite
2.greenDAO 支持 protocol buffer(protobuf) 協議數據的直接存儲,如果你通過 protobuf 協議與服務器交互,將不需要任何的映射。
3.與 ORMLite 等使用註解方式的 ORM 框架不同,greenDAO 使用「Code generation」的方式,這也是其性能能大幅提升的原因。

缺點:
學習成本較高。其中使用了一個Java工程根據一些屬性和規則去generate一些基礎代碼,類似於javaBean但會有一些規則,另外還有QueryBuilder、Dao等API,所以首先要明白整個過程,才能方便使用。沒有ORMLite那樣封裝的完整,不過greenDao的官網上也提到了這一點,正是基於generator而不是反射,才使得其效率高的多。

ormlite是基於註解和反射的的方式,導致ormlite性能有着一定的損失(註解其實也是利用了反射的原理)

優點:
文檔較全面,社區活躍,有好的維護,使用簡單,易上手。

缺點:
基於反射,效率較低

四、總結

相信以上的對比,有基本瞭解過這些框架的話,心裏就會有個大概,至於到底選擇哪個框架運用於項目中,具體問題具體分析,貪多嚼不爛,選擇最適合項目的是爲首要條件,關於android orm數據庫框架的介紹就在此告一段落了,後續會更新其他方面的博文。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章