Android數(shù)據(jù)庫ORM框架:GreenDAO使用簡介

Android最常用的數(shù)據(jù)庫是SQLite喂分,通常使用SQLite進行CRUD操作需要記住一些常用的SQL語句,這不利于提高開發(fā)效率牙寞,而且很容易出錯袜啃。ORM(Object-Relational Mapping)框架的引入使得對數(shù)據(jù)庫的操作也能利用OOP(Object-oriented programming)思想實現(xiàn)。ORM通過將數(shù)據(jù)庫中的一張張表映射成Java的對象崔拥,并提供統(tǒng)一的API提供CRUD操作极舔,使得操作數(shù)據(jù)庫變得簡單,開發(fā)者可以將精力放在處理重要的邏輯链瓦,而不是記住SQL語句上拆魏。

對象關(guān)系映射(ORM)

有幾個常用的ORM開源框架,它們的特點比較如下:

Android ORM框架比較

其中由GreenRobot公司開源的GreenDAO尤為出色慈俯,該開源庫體積小渤刃,而且由于完全沒有使用反射,所以速度很快贴膘,本文將介紹GreenDAO的使用卖子。

特點

1. 魯棒性強, 2011年開始使用
2. 很小, <100k
3. 速度快
4. 安全易用的API
5. 強大的join語句
6. 靈活的屬性類型

使用步驟

1. 建立一個java工程,給每張表定義一個對應(yīng)的Entity刑峡,運行工程洋闽,生成一系列的輸出文件
2. 將這些輸出文件拷貝到Android工程里,并在gradle里做相應(yīng)的配置
3. 可以在Android里通過OOP的方式訪問數(shù)據(jù)庫了

首先打開Eclipse氛琢,建立一個java工程喊递,引入兩個庫文件freemarker.jar和greendao-generator-1.3.1.jar,可以開始定義Entity了阳似。

在greenDAO里,一個Entity對應(yīng)SQLite的一張表铐伴,可以給Entity設(shè)置Property撮奏,Relation和Index,分別代表數(shù)據(jù)表的屬性当宴,關(guān)系和索引(一對一畜吊,一對多)。

Entity

這里的Schema類包含了數(shù)據(jù)庫層面的信息户矢,如數(shù)據(jù)庫版本和名稱:

Schema schema = new Schema(1, "me.chunyu.support");

利用Schema玲献,可以給每張表建立一個對應(yīng)的Entity。Entity包含了Property,Relation和Index捌年。

Property

對Property的設(shè)置如下:

public static void addGroupChatRecord(Schema schema) {        
    Entity groupChatRecord = schema.addEntity("GroupChatRecord");     
    groupChatRecord.addStringProperty("messageMD5ID").primaryKey(); // conversation id + message id md5值        
    groupChatRecord.addBooleanProperty("hasRead"); // 是否已讀        
    groupChatRecord.addDateProperty("messageTime");        
}

這個Entity命名為GroupChatRecord瓢娜,記錄的是好友群的數(shù)據(jù),通過addStringProperty礼预,addBooleanProperty眠砾,addDateProperty分別添加類型為String,Boolean和Date的屬性托酸,對應(yīng)數(shù)據(jù)表里相應(yīng)的字段褒颈,并通過primaryKey()指定messageMD5ID為主鍵。

Relation

addToOne定義一對一的關(guān)系:

Property avatarIdProperty = user.addLongProperty("avatarId").getProperty();
user.addToOne(picture, avatarIdProperty);

上面的代碼中励堡,user和picture都是Entity谷丸,通過addToOne指定user的頭像屬性對應(yīng)picture表里的一條記錄。

addToMany定義一對多的關(guān)系:

Property customerId = order.addLongProperty("customerId").notNull().getProperty();
ToMany customerToOrders = customer.addToMany(order, customerId);

上面的代碼中应结,通過addToMany指定一個用戶(customer)可以對應(yīng)多個訂單(order)刨疼。這樣,通過customer.getOrders()就可以獲取一個用戶的所有訂單:

List orders = customer.getOrders();
Index

通過給數(shù)據(jù)表建立索引可以提高檢索效率摊趾,Index代表數(shù)據(jù)表的索引币狠,通過addProperty添加索引字段,可以建立獨立索引或聯(lián)合索引砾层。Entity通過addIndex方法添加索引:

Index index = new Index();
index.addProperty(property1);
index.addProperty(property2);
entity.addIndex(index);

定義完Entity后漩绵,調(diào)用DAOGenerator類的generateAll方法生成DAO文件,參數(shù)分布是代表數(shù)據(jù)庫的schema和文件輸出路徑:

// 生成DAO文件到指定路徑
new DaoGenerator().generateAll(schema, "../");

生成的公共文件肛炮,包括DaoMaster.java/DaoSession.java止吐,另外每個Entity對應(yīng)生成兩個文件EntityName.java/EntityNameDao.java,文件內(nèi)容如下:
1. EntityName.java: Entity的各個屬性侨糟,及get/set方法
2. EntityNameDao.java:Entity的CRUD方法
3. DaoSession.java:提供獲取各個EntityNameDao的方法
4. DaoMaster.java:生成DaoSession碍扔;進行數(shù)據(jù)庫生成,升級

使用:
首先初始化DaoMaster秕重,然后通過DaoMaster獲得DaoSession不同,樣例代碼:

public class GreenDaoUtils {    
    private static DaoSession daoSession;    
    private static byte[] _lock = {};    

    /**獲取Dao Session**/    
    public static DaoSession getDaoSession(Context context, String dbName) {        
        if (daoSession != null) {            
            return daoSession;        
        }        

        synchronized (_lock) {            
            if (daoSession != null) {                
                return daoSession;            
            }           
            SQLiteDatabase db;            
            DaoMaster daoMaster;            
            
            DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, dbName, null);
            db = helper.getWritableDatabase();        
            daoMaster = new DaoMaster(db);        
            daoSession = daoMaster.newSession();      
  
            return daoSession;    
        }
    }
}

代碼中g(shù)etWritableDatabase用于新建或返回數(shù)據(jù)庫,如果第一次執(zhí)行該代碼溶耘,新建數(shù)據(jù)庫二拐,以后執(zhí)行返回已建好的數(shù)據(jù)庫。同時凳兵,如果數(shù)據(jù)庫版本升級了百新,會執(zhí)行helper的onUpgrade函數(shù),執(zhí)行升級數(shù)據(jù)庫的操作庐扫。

樣例代碼中helper類型是DaoMaster.DevOpenHelper饭望,該類的onUpgrade函數(shù)會刪除所有表仗哨,再新建所有表,只適用于開發(fā)階段铅辞。開發(fā)者需要實現(xiàn)自己的OpenHelper厌漂,重寫onUpgrade函數(shù),指明如何進行數(shù)據(jù)庫的升級巷挥。下面是DaoMaster.DevOpenHelper的實現(xiàn):

public static class DevOpenHelper extends OpenHelper {    
    public DevOpenHelper(Context context, String name, CursorFactory factory) {        
        super(context, name, factory);    
    }    

    @Override    
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        
        Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");        
        dropAllTables(db, true);        
        onCreate(db);    
    }
}
使用DAO API進行CRUD操作:

Create:

entityNameDao.insert(newEntity)

Read:

List joes = userDao.queryBuilder()

                    .where(Properties.FirstName.eq("Joe"))

                    .orderAsc(Properties.LastName)

                    .list();

QueryBuilder qb = userDao.queryBuilder();

qb.where(Properties.FirstName.eq("Joe"),

    qb.or(Properties.YearOfBirth.gt(1970),

        qb.and(Properties.YearOfBirth.eq(1970), 
            Properties.MonthOfBirth.ge(10))));

List youngJoes = qb.list();

Update:

entityNameDao.update(newEntity);

Delete:

entityNameDao.deleteByKey(id)
// OR
entityNameDao.delete(note);
執(zhí)行raw sql語句

除了使用greenDao提供的接口進行增刪改查操作桩卵,greenDao還提供了執(zhí)行Sql語句的功能,示例如下:

Query query = userDao.queryBuilder()
    .where(new StringCondition(“_ID IN ” +“(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)”)
    .build();


Query query = userDao
    .queryRawCreate(  ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin");

同時倍宾,如果感覺沒有得到期望的結(jié)果雏节,可以通過下面代碼打開greenDao調(diào)試功能,輸出生成的sql語句進行debug:

QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;

參考:
https://github.com/greenrobot/greenDAO
http://greenrobot.org/greendao/documentation/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末高职,一起剝皮案震驚了整個濱河市钩乍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌怔锌,老刑警劉巖寥粹,帶你破解...
    沈念sama閱讀 211,042評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異埃元,居然都是意外死亡涝涤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評論 2 384
  • 文/潘曉璐 我一進店門岛杀,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阔拳,“玉大人,你說我怎么就攤上這事类嗤『Γ” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評論 0 345
  • 文/不壞的土叔 我叫張陵遗锣,是天一觀的道長货裹。 經(jīng)常有香客問我,道長精偿,這世上最難降的妖魔是什么弧圆? 我笑而不...
    開封第一講書人閱讀 56,340評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮笔咽,結(jié)果婚禮上墓阀,老公的妹妹穿的比我還像新娘。我一直安慰自己拓轻,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,404評論 5 384
  • 文/花漫 我一把揭開白布经伙。 她就那樣靜靜地躺著扶叉,像睡著了一般勿锅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枣氧,一...
    開封第一講書人閱讀 49,749評論 1 289
  • 那天溢十,我揣著相機與錄音,去河邊找鬼达吞。 笑死张弛,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酪劫。 我是一名探鬼主播吞鸭,決...
    沈念sama閱讀 38,902評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼覆糟!你這毒婦竟也來了刻剥?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,662評論 0 266
  • 序言:老撾萬榮一對情侶失蹤滩字,失蹤者是張志新(化名)和其女友劉穎造虏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體麦箍,經(jīng)...
    沈念sama閱讀 44,110評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡漓藕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挟裂。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片享钞。...
    茶點故事閱讀 38,577評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖话瞧,靈堂內(nèi)的尸體忽然破棺而出嫩与,到底是詐尸還是另有隱情,我是刑警寧澤交排,帶...
    沈念sama閱讀 34,258評論 4 328
  • 正文 年R本政府宣布划滋,位于F島的核電站,受9級特大地震影響埃篓,放射性物質(zhì)發(fā)生泄漏处坪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,848評論 3 312
  • 文/蒙蒙 一架专、第九天 我趴在偏房一處隱蔽的房頂上張望同窘。 院中可真熱鬧,春花似錦部脚、人聲如沸想邦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽丧没。三九已至鹰椒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間呕童,已是汗流浹背漆际。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留夺饲,地道東北人奸汇。 一個月前我還...
    沈念sama閱讀 46,271評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像往声,于是被迫代替她去往敵國和親擂找。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,452評論 2 348

推薦閱讀更多精彩內(nèi)容