GreenDao綜合主鍵和存儲自定義類型對象解決方案

最近公司項目選用GreenDao作為Android客戶端本地數(shù)據(jù)庫的對象關系映射框架。對于GreenDao雖然以往也有簡單用過谊惭,但這還是筆者第一次在實際業(yè)務中使用粟害。碰到了題目所述的兩個問題,雖然在Tutorial里和百度沒找到答案哈误,但在官方issue里搜了一圈果然有方案暖眼,遂記錄下來幫助更多人惕耕。

綜合主鍵

需求場景:某張表里需要兩個或多個column組合在一起成為一個綜合主鍵。比如你的表里需要存儲一個用戶的賬單诫肠,雖然賬單也有id司澎,但是你希望一張表存儲所有用戶欺缘,那么就需要把userId和賬單id放在一起作為一個綜合主鍵。雖然sqlite數(shù)據(jù)庫是可以直接指定綜合主鍵的挤安,但不幸的是GreenDao并不支持(筆者也很懵逼為啥不支持)谚殊。

查看官方方案來看一下:

@Entity(      
        // Define indexes spanning multiple columns here.
        indexes = {
                @Index(value = "prop1 DESC, prop2 DESC", unique = true)
        }
)
public class YourEntity {
    @Id(autoincrement = true)
    Long id;
    Integer prop1;
    Long prop2;
  ...
}

可以看到,它是通過一個加上unique約束的綜合索引來間接實現(xiàn)綜合主鍵的需求蛤铜。這樣的話還是要用@Id注解定義一個主鍵嫩絮,但是我們完全不用管理這個主鍵,后面插入數(shù)據(jù)的適合這個字段直接插入null即可围肥。真正的主鍵是prop1剿干,prop2這兩個組合的綜合主鍵,使用insertOrReplace方法插入數(shù)據(jù)時穆刻,如果這兩個值完全相等的話置尔,就會替換原有數(shù)據(jù)。不放心的話大家可以試一試氢伟,筆者已經試過了榜轿。

存儲自定義類型對象

需求場景:sqlite數(shù)據(jù)庫只能直接存儲數(shù)字、字符串腐芍、日期等簡單類型差导,如果要存儲一個復雜對象的話需要把對象拆解為一個個簡單數(shù)據(jù)類型,畢竟再復雜的數(shù)據(jù)類型也是由簡單數(shù)據(jù)類型組合而來猪勇。本以為大名鼎鼎的GreenDao可以幫我們智能拆解、組裝對象颠蕴,結果搜了一圈竟然找不到沒找到存儲自定義類型的辦法泣刹。

好在在官方文檔上找到解決方案:

@Entity
public class User {
    @Id
    private Long id;
 
    @Convert(converter = RoleConverter.class, dbType = Integer.class)
    private Role role;
 
    public enum Role {
        DEFAULT(0), AUTHOR(1), ADMIN(2);
        
        final int id;
        
        Role(int id) {
            this.id = id;
        }
    }
 
    public static class RoleConverter implements PropertyConverter<Role, Integer> {
        @Override
        public Role convertToEntityProperty(Integer databaseValue) {
            if (databaseValue == null) {
                return null;
            }
            for (Role role : Role.values()) {
                if (role.id == databaseValue) {
                    return role;
                }
            }
            return Role.DEFAULT;
        }
 
        @Override
        public Integer convertToDatabaseValue(Role entityProperty) {
            return entityProperty == null ? null : entityProperty.id;
        }
    }
}

可以看到這個實體類里包含了一個自定義的枚舉類型Role,在該類型上加了一個@Convert注解犀被,括號里面指定了用于轉換對象類型和數(shù)據(jù)庫類型的converter類椅您,以及該對象存儲在數(shù)據(jù)庫中的類型。

再來看看這個converter類做了什么事情寡键。很簡單掀泳,它實現(xiàn)了PropertyConverter接口,里面有兩個方法西轩,convertToEntityProperty是將數(shù)據(jù)庫中的類型轉換為java實體類员舵;convertToDatabaseValue方法相反,將java實體類轉換為數(shù)據(jù)庫中的類型藕畔。我們只要在這兩個方法里定義相應的轉換規(guī)則即可马僻。

看上去也不難,思路也很清晰注服。但是這個例子里的Enum類型要轉換為int類型還是比較簡單的韭邓,而筆者要存儲的對象要復雜的多措近。這還是解決不了我的需求啊(欲哭無淚)女淑。

如何快速簡單的把一個復雜的數(shù)據(jù)類型轉換為簡單數(shù)據(jù)類型瞭郑,而且還要能精準地轉換回來?好像是有這么一個東西鸭你,jsonG拧!苇本!json作為客戶端和服務端之間數(shù)據(jù)傳遞的載體袜茧,確實滿足我們現(xiàn)在的業(yè)務需求。更棒的是我們有gson這個解析框架來幫我們做轉換瓣窄!那么我們要做的事真就是無腦操作了笛厦。來看看我的Demo代碼:

@Entity(
)
public class Zoo {
    indexes = {
            @Index(value = "zooId DESC, zoneId DESC", unique = true)
    }
    @Id(autoincrement = true)
    private Long id;

    @Property
    private Long zooId;

    @Property
    private Long zoneId;

    @Property
    @Convert(converter = CatConverter.class, columnType = String.class)
    private Cat cat;

    public static class CatConverter implements PropertyConverter<Cat, String> {
        @Override
        public Cat convertToEntityProperty(String databaseValue) {
            if (databaseValue == null) {
                return null;
            }
            return new Gson().fromJson(databaseValue, Cat.class);
        }

        @Override
        public String convertToDatabaseValue(Cat entityProperty) {
            if (entityProperty == null) {
                return null;
            }
            return new Gson().toJson(entityProperty);
        }
    }
}

這里我新建了一個叫Zoo的實體,里面包含一個Cat類型的對象俺夕,且不管該對象復雜與簡單裳凸,我們甚至都不需要關心它的具體數(shù)據(jù)結構。加上@Convert注解后新建一個CatConverter類(注意converter類是內部類的話要聲明為static)劝贸,因為我們要轉換為json存儲起來所以數(shù)據(jù)庫中的類型肯定是String了姨谷,標注好泛型,做一個參數(shù)的非空判斷(良好習慣)映九。在轉換的方法內部我們只需要利用gson將數(shù)據(jù)在java bean類型和json之間轉換梦湘,就可以完成我們的需求了,是不是很簡單呢件甥?

Cat miaomiao = new Cat(13, "miaomiao");
Cat jingjing = new Cat(13, "jingjing");
ZooDao zooDao = daoSession.getZooDao();
zooDao.insertOrReplace(new Zoo(null, 222L, 333L, miaomiao));
zooDao.insertOrReplace(new Zoo(null, 222L, 331L, jingjing));

List<Zoo> zoos = zooDao.queryBuilder().list();
for (Zoo zoo : zoos) {
    Log.d("xxx", zoo.getZooId()+":"+zoo.getZoneId()+":"+zoo.getCat().toString());
}

寫完代碼后make project自動生成新的ZooDao類(有興趣的可以看看這個類捌议,其實也挺簡單的),不放心趕緊實驗一下能不能直接存取自定義對象了引有。

大家有什么問題的話可以留言瓣颅,歡迎交流~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市譬正,隨后出現(xiàn)的幾起案子宫补,更是在濱河造成了極大的恐慌,老刑警劉巖曾我,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粉怕,死亡現(xiàn)場離奇詭異,居然都是意外死亡您单,警方通過查閱死者的電腦和手機斋荞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來虐秦,“玉大人平酿,你說我怎么就攤上這事凤优。” “怎么了蜈彼?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵筑辨,是天一觀的道長。 經常有香客問我幸逆,道長棍辕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任还绘,我火速辦了婚禮楚昭,結果婚禮上,老公的妹妹穿的比我還像新娘拍顷。我一直安慰自己抚太,他們只是感情好,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布昔案。 她就那樣靜靜地躺著尿贫,像睡著了一般。 火紅的嫁衣襯著肌膚如雪踏揣。 梳的紋絲不亂的頭發(fā)上庆亡,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機與錄音捞稿,去河邊找鬼又谋。 笑死,一個胖子當著我的面吹牛娱局,可吹牛的內容都是我干的搂根。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼铃辖,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了猪叙?” 一聲冷哼從身側響起娇斩,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎穴翩,沒想到半個月后犬第,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡芒帕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年歉嗓,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片背蟆。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鉴分,死狀恐怖哮幢,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情志珍,我是刑警寧澤橙垢,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站伦糯,受9級特大地震影響柜某,放射性物質發(fā)生泄漏。R本人自食惡果不足惜敛纲,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一喂击、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淤翔,春花似錦翰绊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至寡具,卻和暖如春秤茅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背童叠。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工框喳, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厦坛。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓五垮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親杜秸。 傳聞我的和親對象是個殘疾皇子放仗,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內容