GreenDao官網
GitHub
GitHub -> https://github.com/greenrobot/greenDAO
性能對比
介紹
- GreenDao採用的是用java代碼直接生成Bean(實體)和Dao(Data Access Object數據訪問對象)的方式,都不用自己寫實體了,也是一大好處,不過這也造成了理解上的難度,我剛開始用的時候就有點蒙。
- 首先創建一個Java的Library,一定是Java的,命名爲daogenerator(可以起別的名字,爲了後面敘述方便)。在app下面和’java’目錄同級創建’java-gen’目錄,將會用來放置生成的Bean和Dao。Dao也就是數據訪問對象,實體類只能描述一個對象的屬性和行爲,想與數據庫交流就需要Dao對象,它包含對應的數據庫字段和增刪改查方法。
生成文件
- 在daogenerator庫裏創建’ExampleDaoGenerator.java’文件,包含main方法,構建schema,生成目錄和文件
public static void main(String[] args) throws Exception{
operate();
}
private static void operate() throws Exception {
// Schema對象,可以用來生成實體和dao
// 兩個參數分別代表:數據庫版本號與自動生成bean代碼的包路徑。
Schema schema = new Schema(2, "com.march.bean");
// 默認的dao目錄
schema.setDefaultJavaPackageDao("com.march.dao");
// 模式(Schema)同時也擁有兩個默認的 flags,分別用來標示 entity 是否是 activie 以及是否使用 keep sections。
// 可以激活預熱實體,使讀寫更迅速
schema.enableActiveEntitiesByDefault();
// 這個是爲了你可以在自動生成的實體類中添加自己的custom代碼
schema.enableKeepSectionsByDefault();
// 一旦你擁有了一個 Schema 對象後,你便可以使用它添加實體(Entities)了。這裏只是一個假的方法表示一下,生成實體在下一節
generateBean(schema);
// 最後我們將使用 DAOGenerator 類的 generateAll() 方法自動生成代碼,此處你需要根據自己的情況更改輸出目錄(既之前創建的 java-gen)。
// 其實,輸出目錄的路徑可以在 build.gradle 中設置,有興趣的朋友可以自行搜索,這裏就不再詳解。
new DaoGenerator().generateAll(schema, "/Users/march/AndroidPro/Reaper/app/src/main/java-gen");
}
如何生成實體
private static void addNote(Schema schema) {
// 一個實體(類)就關聯到數據庫中的一張表,此處表名爲「Note」(既類名)
Entity note = schema.addEntity("Note");
// greenDAO 會自動根據實體類的屬性值來創建表字段,並賦予默認值
// 接下來你便可以設置表中的字段,又很多鏈式編程的方法,結合數據庫的create table操作可以設置相關的字段及約束
note.addIdProperty().autoincrement();
note.addBooleanProperty("isYes").primaryKey().unique();
note.addStringProperty("text").notNull();
// 與在 Java 中使用駝峯命名法不同,默認數據庫中的命名是使用大寫和下劃線來分割單詞的。
// For example, a property called “creationDate” will become a database column “CREATION_DATE”.
note.addStringProperty("comment");
note.addDateProperty("date");
}
自定義生成的代碼
- 當重新執行java代碼時會覆蓋生成新的文件,如果你修改了生成的類,就會被重新覆蓋,解決這個問題,設置
note.setHasKeepSections(true);
會在文件中生成一些註釋,在註釋中間的代碼將不會被覆蓋,也可以設置繼承,實現等。。。這樣就不需要每次都修改代碼了
// KEEP INCLUDES - put your custom includes here
import com.march.quickrvlibs.inter.RvQuickInterface;
// KEEP INCLUDES END
// KEEP FIELDS - put your custom fields here
public static final int TYPE_SHU = 0;
public static final int TYPE_HENG = 1;
// KEEP FIELDS END
// KEEP METHODS - put your custom methods here
@Override
public int getRvType() {
if (height > width)
return 0;
else
return 1;
}
// KEEP METHODS END
//設置支持自定義代碼(或schema.enableKeepSectionsByDefault();)
note.setHasKeepSections(true);
//設置實現的接口
note.implementsInterface("RvQuickInterface", "java.io.Serializable");
//設置繼承的父類
note.setSuperclass("Album");
//你也可以重新給表命名
note.setTableName("NODE");
初始化數據庫
private DaoSession mDaoSession;
public void setupDatabase(Context context) {
// 通過 DaoMaster 的內部類 DevOpenHelper,你可以得到一個便利的 SQLiteOpenHelper 對象。
// 可能你已經注意到了,你並不需要去編寫「CREATE TABLE」這樣的 SQL 語句,因爲 greenDAO 已經幫你做了。
// 注意:默認的 DaoMaster.DevOpenHelper 會在數據庫升級時,刪除所有的表,意味着這將導致數據的丟失。
// 所以,在正式的項目中,你還應該做一層封裝,來實現數據庫的安全升級。
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, "notes-db", null);
SQLiteDatabase db = helper.getWritableDatabase();
// 注意:該數據庫連接屬於 DaoMaster,所以多個 Session 指的是相同的數據庫連接。
DaoMaster daoMaster = new DaoMaster(db);
mDaoSession = daoMaster.newSession();
// 在 QueryBuilder 類中內置兩個 Flag 用於方便輸出執行的 SQL 語句與傳遞參數的值
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
獲取Dao
public WholeAlbumItemDao getWholeAlbumItemDao() {
return mDaoSession.getWholeAlbumItemDao();
}
增
//這兩個方法提供簡單的插入和不存在則插入存在則更新的操作
DaoHelper.get().getAlbumDetailDao().insert();
DaoHelper.get().getAlbumDetailDao().insertOrReplace();
//這兩個方法是上面兩個方法的加強版,支持iterable類型多個對象的插入和更新,同時是基於事務的。
DaoHelper.get().getAlbumDetailDao().insertInTx();
DaoHelper.get().getAlbumDetailDao().insertOrReplaceInTx();
//官方解釋:Insert an entity into the table associated with a concrete DAO <b>without</b> setting key property.
//Warning: This may be faster, but the entity should not be used anymore. The entity also won't be attached to identity scope.
//大概意思就是小心點用,雖然速度快,但是插進去可能就拿不出來了
DaoHelper.get().getAlbumDetailDao().insertWithoutSettingPk()
刪
//與insert方法大同小異
DaoHelper.get().getAlbumDetailDao().delete();
DaoHelper.get().getAlbumDetailDao().deleteInTx();
//根據主鍵刪除元素
DaoHelper.get().getAlbumDetailDao().deleteByKey();
DaoHelper.get().getAlbumDetailDao().deleteByKeyInTx();
//刪除全部
DaoHelper.get().getAlbumDetailDao().deleteAll();
//也是刪除,具體的區別還沒弄明白
DaoHelper.get().getAlbumDetailDao().detach()
DaoHelper.get().getAlbumDetailDao().detachAll();
改
DaoHelper.get().getAlbumDetailDao().update();
DaoHelper.get().getAlbumDetailDao().updateInTx();
查
- 關於Query的操作相對複雜, 下面只是比較基本的,更多的使用方法可以參照Query文檔
// 獲取querybuilder
QueryBuilder<RecommendAlbumItem> queryBuilder = DaoHelper.get().getRecommendAlbumItemDao().queryBuilder();
// 查詢條件,大於小於,and,or
queryBuilder.where(
RecommendAlbumItemDao.Properties.Album_type.eq(""),
queryBuilder.or(RecommendAlbumItemDao.Properties.Album_cover.gt(""),
queryBuilder.and(RecommendAlbumItemDao.Properties.Album_cover.ge("")
,RecommendAlbumItemDao.Properties.Album_cover.eq(""))));
// offset limmit
queryBuilder.offset(10).limit(10);
//排序
queryBuilder.orderAsc();
queryBuilder.orderCustom(null,null);
queryBuilder.orderDesc();
queryBuilder.build();
//查詢數量
queryBuilder.count();
//返回list
queryBuilder.list();