GreenDao增刪改查使用中的一些坑

入坑前的鋪墊

昨天在上一篇[GreenDao項(xiàng)目接入]http://www.reibang.com/p/dac3bd9bad72 中說明了在項(xiàng)目中使用GreenDao的一個(gè)流程,因?yàn)闀r(shí)間問題沒有詳細(xì)的講解有關(guān)增刪改查的一些問題,今天給大家補(bǔ)充一下巩踏。

public class User extends BaseBean
{
    private int memberSex;//性別
    private String memberLastX;//X幣
    private String memberNickname;//昵稱
    private String memberIcon;//頭像地址鏈接
    private String memberMobile;//手機(jī)號(hào)
    private int memberId;//用戶ID
    private String memberDetailAddr;//用戶的詳細(xì)地址
    private String memberLastExperience;//用戶經(jīng)驗(yàn)值
    private String memberLevelName;//用戶等級(jí)昵稱
    private long memberBirthday;//用戶生日
    private String memberProvince;//用戶所在地
}

上面為我實(shí)際開發(fā)中用來獲取接口用戶信息的實(shí)體類,然后我按照步驟對(duì)實(shí)體類進(jìn)行了注釋肥矢,如下:

@Entity
public class User extends BaseBean
{
    @Id
    private Long id;
    private int memberSex;//性別
    private String memberLastX;//X幣
    private String memberNickname;//昵稱
    private String memberIcon;//頭像地址鏈接
    private String memberMobile;//手機(jī)號(hào)
    private int memberId;//用戶ID
    private String memberDetailAddr;//用戶的詳細(xì)地址
    private String memberLastExperience;//用戶經(jīng)驗(yàn)值
    private String memberLevelName;//用戶等級(jí)昵稱
    private long memberBirthday;//用戶生日
    private String memberProvince;//用戶所在地
}

不知道大家有沒有仔細(xì)觀察,我在實(shí)體類里面又定義了一個(gè)Long類型的字段作為ID(是按照官方Demo中開發(fā)的)叠洗,正是這個(gè)ID甘改,讓我掉了一次坑,給大家詳細(xì)的描述下當(dāng)時(shí)我遇到的問題以及解決辦法:

我按照上面的實(shí)體類去Make project生成對(duì)應(yīng)的UserDao和DaoMaster灭抑、DaoSession十艾。然后我在代碼里面緩存用戶信息的時(shí)候是這么做的,首先從服務(wù)器獲取用戶數(shù)據(jù)腾节,然后轉(zhuǎn)換成一個(gè)User對(duì)象使用GreenDao進(jìn)行本地緩存忘嫉,代碼如下:

/**
     * 緩存用戶信息
     *
     * @param user
     */
    public void cacheUserInfo(User user)
    {
        UserDao userDao = GreenDaoManager.getInstance().getmDaoSession().getUserDao();
        userDao.save(user);
    }

GreenDao里面提供存儲(chǔ)數(shù)據(jù)的方法有三個(gè):

  • save(T entity)
    "Saves" an entity to the database: depending on the existence of the key property, it will be inserted (key is null) or updated (key is not null).通過key屬性判斷是否存在,如果存在就更新數(shù)據(jù)案腺,如果key為null就插入庆冕。這里的key是什么東東?這就是我今天被坑的地方劈榨,這個(gè)key就是我新增的Long id這個(gè)字段访递,也就是表中的主鍵
  • insert(T entity)
    Insert an entity into the table associated with a concrete DAO.
    插入實(shí)體類,這個(gè)是直接插入同辣。
  • insertOrReplace(T entity)
    Insert an entity into the table associated with a concrete DAO.將實(shí)體插入到與具體DAO關(guān)聯(lián)的表中拷姿,這是官方api的給的解釋,不過他的實(shí)際效果和svae很類似邑闺,就是如果存在就修改跌前,不存在插入棕兼。

這里先說一下查詢的方法吧陡舅,官方提供查詢的方法有:

  • loadByRowId(long rowId)
  • load(K key)
    Loads the entity for the given PK.
    根據(jù)主鍵獲取對(duì)象,也就是通過id獲取

但是我只有實(shí)體類的memberId伴挚,也就是在服務(wù)器上生成的Id靶衍,所以肯定沒法用這兩個(gè)方法獲取到數(shù)據(jù)灾炭,然后又查文檔,發(fā)現(xiàn)[QueryBuilder<T>]http://greenrobot.org/files/greendao/javadoc/current/ ,在QueryBuilder中提供了幾個(gè)方法:

  • unique()
    Shorthand for build()
    .
    Shorthand for build()
    .unique()
    ; see Query.unique()
    for details. To execute a query more than once, you should build the query and keep the Query
    object for efficiency reasons.
    大概的意思就是說通過build對(duì)象構(gòu)建一個(gè)Query<T>的對(duì)象颅眶,可以重復(fù)反復(fù)的利用這個(gè)去進(jìn)行獲取數(shù)據(jù)

入坑ing

我是怎么入坑的蜈出? 當(dāng)時(shí)我看了文檔之后發(fā)現(xiàn)save挺智能的嘛,就尋思著用save吧涛酗,自身就是在插入前做個(gè)判斷铡原,省時(shí)省力,然后就有了上面的那段代碼商叹,然后我在就在個(gè)人中心去獲取緩存的數(shù)據(jù)燕刻,方法如下:

 /**
     * 從本地緩存中獲取user對(duì)象
     *
     * @param memberId 用戶ID
     * @return 返回用戶信息
     */
    public User getUserInfoFromCache(String memberId)
    {
        UserDao userDao = GreenDaoManager.getInstance().getmDaoSession().getUserDao();
        Query<User> query = userDao.queryBuilder().where(UserDao.Properties.MemberId.eq(memberId))
                                   .orderDesc(UserDao.Properties.MemberId).build();
        return query.unique();
    }

看起來沒有什么問題,然后我就去跑程序測(cè)試剖笙,第一次發(fā)現(xiàn)吆喝卵洗,果然好使,執(zhí)行完后數(shù)據(jù)庫果然有了一行數(shù)據(jù)弥咪,屁顛的退出再來一遍过蹂,竟然崩了,一看日志提示:Expected unique result, but count was 2聚至,意思就是說unique只能查詢數(shù)據(jù)庫中有一條符合條件的數(shù)據(jù)酷勺,上面的方法中我的查詢條件是.where(UserDao.Properties.MemberId.eq(memberId)),也就是memberId等于當(dāng)前用戶的晚岭,打印輸出果然數(shù)據(jù)庫有兩條數(shù)據(jù)鸥印,然后找原因,肯定是在緩存的方法中去找坦报,發(fā)現(xiàn)save也沒什么問題啊库说,想不通的時(shí)候必殺絕招就是看源碼

出坑

save的源碼如下:

  public void save(T entity) {
        if (hasKey(entity)) {
            update(entity);
        } else {
            insert(entity);
        }
    }

大家可以看到其實(shí)他就是update和insert的一個(gè)判斷使用,有個(gè)hasKey的方法片择,然后查看hasKey的源碼:

abstract protected boolean hasKey(T entity);

發(fā)現(xiàn)是一個(gè)抽象方法潜的,那我只能去他的繼承類UserDao里面去找了

@Override
public boolean hasKey(User entity)
 {   
     return entity.getId() != null;
 }

終于找到了真兇,沒錯(cuò) 字管,就是我們定義的Long id這個(gè)字段啰挪,原來他在插入之前是判斷了這個(gè)是否存在,如果不存在就執(zhí)行插入嘲叔,如果存在就更新亡呵,然后就明白了,我在插入數(shù)據(jù)的時(shí)候是從服務(wù)器獲取到的數(shù)據(jù)硫戈,只有memberId锰什,而沒有本地?cái)?shù)據(jù)庫的id,所以第二次緩存的時(shí)候仍然是執(zhí)行了insert的操作,然后在查詢的時(shí)候肯定出現(xiàn)了問題汁胆,真相大白就可以想辦法解決了梭姓。下面是我的解決代碼:

  /**
     * 緩存用戶信息
     *
     * @param user
     */
    public void cacheUserInfo(User user)
    {
        User oldUser = getUserInfoFromCache(user.getMemberId() + "");
        if (oldUser != null)
        {
            user.setId(oldUser.getId());
        }
        UserDao userDao = GreenDaoManager.getInstance().getmDaoSession().getUserDao();
        userDao.save(user);
    }

在插入之前坐了個(gè)判斷,判斷是否有memberId相同的存在嫩码,如果存在取出GreenDao對(duì)應(yīng)的id誉尖,放入user,這樣在hasKey判斷的時(shí)候肯定是執(zhí)行update了铸题。ok铡恕,問題解決。不過丢间,還有一種可能没咙,說可不可能不添加Long id這個(gè)字段,直接給我們的memberId添加@Id呢千劈,實(shí)際上試試不行的祭刚。大家看下面修改之后的代碼就知道了:

@Entity
public class User extends BaseBean
{
    private int memberSex;//性別
    private String memberLastX;//X幣
    private String memberNickname;//昵稱
    private String memberIcon;//頭像地址鏈接
    private String memberMobile;//手機(jī)號(hào)
    @Id
    private int memberId;//用戶ID
    private String memberDetailAddr;//用戶的詳細(xì)地址
    private String memberLastExperience;//用戶經(jīng)驗(yàn)值
    private String memberLevelName;//用戶等級(jí)昵稱
    private long memberBirthday;//用戶生日
    private String memberProvince;//用戶所在地
}

然后Make project,執(zhí)行了下出現(xiàn)問題了墙牌,然后去查看hasKey的代碼:

 @Override
    public boolean hasKey(User entity) {
        throw new UnsupportedOperationException("Unsupported for entities with a non-null key");
    }

變成了直接拋出異常了涡驮,所以,這個(gè)想法大家就別想了喜滨,如果有更好的辦法歡迎大家下方留言告知捉捅。謝謝。
我每天都會(huì)更新一個(gè)小知識(shí)給大家虽风,如果有興趣可以關(guān)注棒口,指不定什么時(shí)候就可以幫到你了,謝謝大家辜膝。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末无牵,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子厂抖,更是在濱河造成了極大的恐慌茎毁,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忱辅,死亡現(xiàn)場(chǎng)離奇詭異七蜘,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)墙懂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門橡卤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人损搬,你說我怎么就攤上這事碧库∪雍ィ” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵谈为,是天一觀的道長。 經(jīng)常有香客問我踢关,道長伞鲫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任签舞,我火速辦了婚禮秕脓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘儒搭。我一直安慰自己吠架,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開白布搂鲫。 她就那樣靜靜地躺著傍药,像睡著了一般。 火紅的嫁衣襯著肌膚如雪魂仍。 梳的紋絲不亂的頭發(fā)上拐辽,一...
    開封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音擦酌,去河邊找鬼俱诸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛赊舶,可吹牛的內(nèi)容都是我干的睁搭。 我是一名探鬼主播,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼笼平,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼园骆!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寓调,我...
    開封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤遇伞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后捶牢,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鸠珠,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年秋麸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了渐排。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灸蟆,死狀恐怖驯耻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤可缚,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布霎迫,位于F島的核電站,受9級(jí)特大地震影響帘靡,放射性物質(zhì)發(fā)生泄漏知给。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一描姚、第九天 我趴在偏房一處隱蔽的房頂上張望涩赢。 院中可真熱鬧,春花似錦轩勘、人聲如沸筒扒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽花墩。三九已至,卻和暖如春澄步,著一層夾襖步出監(jiān)牢的瞬間观游,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來泰國打工驮俗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留懂缕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓王凑,卻偏偏與公主長得像搪柑,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子索烹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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

  • 最近接觸greenDao3.x百姓,總結(jié)一些業(yè)務(wù)中用到的東西和坑渊额。greenDao 到3.x之后用法比2.x和1.x時(shí)...
    Uprising閱讀 3,277評(píng)論 0 7
  • 1. 什么是greenDao 弄明白greenDao之前我們應(yīng)該先了解什么是ORM(Object Relation...
    看一季殘花落幕閱讀 2,505評(píng)論 0 4
  • GreenDao 介紹:greenDAO是一個(gè)對(duì)象關(guān)系映射(ORM)的框架,能夠提供一個(gè)接口通過操作對(duì)象的方式去操...
    小董666閱讀 733評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法垒拢,類相關(guān)的語法旬迹,內(nèi)部類的語法,繼承相關(guān)的語法求类,異常的語法奔垦,線程的語...
    子非魚_t_閱讀 31,631評(píng)論 18 399
  • GreenDao 介紹:greenDAO是一個(gè)對(duì)象關(guān)系映射(ORM)的框架,能夠提供一個(gè)接口通過操作對(duì)象的方式去操...
    johnnycmj閱讀 4,328評(píng)論 1 7