Realm的使用

Tag:對(duì)于自己認(rèn)定的事情,要堅(jiān)持乔煞。

Realm 是一個(gè)移動(dòng)數(shù)據(jù)庫(kù),可運(yùn)行于手機(jī)柒室、平板和可穿戴設(shè)備之上渡贾。可以讓你的應(yīng)用更快速雄右,帶來難以想象的體驗(yàn)空骚。其目標(biāo)是為了代替 CoreData 和 SQLite 數(shù)據(jù)庫(kù)。

易用

Ream 不是在SQLite基礎(chǔ)上的ORM擂仍,它有自己的數(shù)據(jù)查詢引擎囤屹。并且十分容易使用。

跨平臺(tái)

Realm 支持 iOS & OS X (Objective?C & Swift) & Android逢渔。我們可以在這些平臺(tái)上共享Realm數(shù)據(jù)庫(kù)文件肋坚,并且上層邏輯可以不用任何改動(dòng)的情況下實(shí)現(xiàn)移植。

高級(jí)

Ream支持加密肃廓,格式化查詢智厌,易于移植,支持JSON盲赊,流式api铣鹏,數(shù)據(jù)變更通知等高級(jí)特性

Realm的使用條件

  • 目前不支持Android以外的Java
  • Android Studio >= 1.5.1
  • 較新的Android SDK版本
  • JDK version >=7.
  • 支持API 9(Android 2.3)以及之后的版本

一.加入依賴關(guān)系

1、在project的build中加入依賴

    buildscript {
        repositories {
             jcenter()
        }
       dependencies {
       classpath "io.realm:realm-gradle-plugin:2.2.1"
       }
 }

2哀蘑、 在module中加入

    apply plugin: 'realm-android

二.創(chuàng)建和初始化

1诚卸、使用RealmConfiguration配置Realm

創(chuàng)建數(shù)據(jù)庫(kù)時(shí)首先需要調(diào)用Realm.init()方法,否則系統(tǒng)報(bào)錯(cuò):Java.lang.IllegalStateException: Call Realm.init(Context) before creating a RealmConfiguration
數(shù)據(jù)庫(kù)初始化主要工作是什么數(shù)據(jù)庫(kù)的name(設(shè)置數(shù)據(jù)庫(kù)的文件名稱)绘迁、schemaVersion(設(shè)置當(dāng)前數(shù)據(jù)庫(kù)版本號(hào)合溺,當(dāng)前版本號(hào)不能小于歷史版本號(hào))、migration(數(shù)據(jù)庫(kù)版本遷移)缀台、 deleteRealmIfMigrationNeeded(版本沖突時(shí)刪除原始數(shù)據(jù)庫(kù))棠赛、inMemory(在內(nèi)存中持久化,關(guān)閉后自動(dòng)刪除)、build(創(chuàng)建數(shù)據(jù)庫(kù))恭朗。

public static Realm getRealm(Context context)
{
byte[] key = new byte[64];
new SecureRandom().nextBytes(key);
Realm.init(context);
Migration migration = new Migration();
RealmConfiguration config = new RealmConfiguration.Builder()
        .name("realmdb.realm") //文件名
        .schemaVersion(0) //版本號(hào)
        .migration(migration)//數(shù)據(jù)庫(kù)版本遷移(數(shù)據(jù)庫(kù)升級(jí)屏镊,當(dāng)數(shù)據(jù)庫(kù)中某個(gè)表添加字段或者刪除字段)
        .deleteRealmIfMigrationNeeded()//聲明版本沖突時(shí)自動(dòng)刪除原數(shù)據(jù)庫(kù)(當(dāng)調(diào)用了該方法時(shí),上面的方法將失效)痰腮。
        .build();//創(chuàng)建
return Realm.getInstance(config);
}

2而芥、 創(chuàng)建model

創(chuàng)建一個(gè)類名為User的model,首先該類必須繼承自RealmObject膀值,只有這才用使用Realm來操作model生成相應(yīng)的表棍丐。
在Realm支持的類型有:boolean, byte, short,int,long,float, double,String, Date,byte[], RealmObject, RealmList<? extends RealmObject>還支持Boolean, Byte, Short, Integer, Long, Float 和 Double沧踏。但是:整數(shù)類型 short歌逢、int 和 long 都被映射到 Realm內(nèi)的相同類型(實(shí)際上為 long )。

@PrimaryKey——表示該字段是主鍵

PrimaryKey就是主鍵翘狱。使用@PrimaryKey來標(biāo)注秘案,字段類型必須是字符串(String)或整數(shù)(byte,short潦匈,int或long)以及它們的包裝類型(Byte,Short, Integer, 或 Long)阱高。一個(gè)model中不可以存在多個(gè)主鍵,使用字符串字段作為主鍵意味著字段被索引(注釋@PrimaryKey隱式地設(shè)置注釋@Index)茬缩。

@Required——表示該字段非空

在某些情況下赤惊,某些屬性是不能為null的。使用@Required可用于用于強(qiáng)行要求其屬性不能為空凰锡,只能用于Boolean, Byte, Short, Integer, Long, Float, Double, String, byte[] 和 Date未舟。在其它類型屬性上使用

@Required修飾會(huì)導(dǎo)致編譯失敗。

note:基本數(shù)據(jù)類型不需要使用注解 @Required掂为,因?yàn)樗麄儽旧砭筒豢蔀榭铡?/p>

@Ignore——表示忽略該字段

如果想忽略某個(gè)字段裕膀,則可以使用@Ignore修飾該字段,被秀@ignore修飾的字段在存儲(chǔ)數(shù)據(jù)時(shí)會(huì)忽略該字段菩掏。

@Index——添加搜索索引

使用@index可以為字段添加搜索索引魂角,使用索引以后使得插入的速度變慢,數(shù)據(jù)量也變得更大智绸。但是在查詢速度將變得更快,所以建議只在優(yōu)化讀取性能的特定情況時(shí)添加索引访忿。

支持索引:String瞧栗,byte,short海铆,int迹恐,long,boolean和Date字段卧斟。

public class User extends RealmObject
{
@PrimaryKey
private int id;
private int age;
@Required
private String name;
public int getId()
{
    return id;
}
public void setId(int id)
{
    this.id = id;
}
public String getName()
{
    return name;
}
public void setName(String name)
{
    this.name = name;
}
private RealmList<Dog> dogs;
public RealmList<Dog> getDogs()
{
    return dogs;
}
public void setDogs(RealmList<Dog> dogs)
{
    this.dogs = dogs;
}
public int getAge()
{
    return age;
}
public void setAge(int age)
{
    this.age = age;
}
}

4殴边、增

寫入操作需要在事務(wù)中進(jìn)行憎茂,
*使用executeTransaction方法來開啟事務(wù)。
當(dāng)model沒有primaryKey時(shí)锤岸,可以使用下面的方法

mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
    User user = realm.createObject(User.class);
    user.setName("Gavin");
    user.setAge(23);
    user.setId(1);
}});      

當(dāng)model有primaryKey時(shí)竖幔,則可以使用下面的方法,將對(duì)@primaryKey修飾的字段直接在創(chuàng)建對(duì)象是賦值(createObject(User.class,1))

mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
    User user = realm.createObject(User.class是偷,1);
    user.setName("Gavin");
    user.setAge(23);       
   }});

使用copyToRealmOrUpdate或copyToRealm方法插入數(shù)據(jù)

當(dāng)model中含有primaryKey時(shí)使用copyToRealmOrUpdate插入數(shù)據(jù)拳氢,在當(dāng)前插入主鍵的值存在時(shí)則修改對(duì)應(yīng)主鍵值相關(guān)的數(shù)據(jù)信息,否則插入數(shù)據(jù)蛋铆。
當(dāng)model中不含有主鍵時(shí)馋评,則使用copyToRealm。若在不含有主鍵的model中使用copyToRealmOrUpdate將拋異常:

java.lang.IllegalArgumentException: A RealmObject with no @PrimaryKey cannot be updated:XXXXX
   final User user = new User();
user.setName("李德華");
user.setUserId("admin");
user.setAge(25);
user.setId(1);

realm.executeTransaction(new Realm.Transaction()
{
    @Override
    public void execute(Realm realm)
    {                
        realm.copyToRealmOrUpdate(user);
    }
});

當(dāng)在model(User)中包辦另外一個(gè)model例如在User中包含一個(gè)Dog模型刺啦,也可以包含一個(gè)Dog的集合
還記得在之前的User數(shù)據(jù)模型中含有這么一塊代碼嗎留特?這個(gè)申明表示一個(gè)User中可以包含(養(yǎng))多條狗(Dog)
在Realm中List類型表示為RealmList。

private RealmList<Dog> dogs;
public RealmList<Dog> getDogs()
{
    return dogs;
}
public void setDogs(RealmList<Dog> dogs)
{
    this.dogs = dogs;
}      

向數(shù)據(jù)模型(User)插入另外一個(gè)數(shù)據(jù)模型(Dog)時(shí)玛瘸,可以才用如下方式(當(dāng)User含有主鍵時(shí)采用):

private void insertOrUpdateDataWithPrimaryKey()
{
final User user = new User();
user.setName("李德華");
user.setUserId("admin");
user.setAge(25);
user.setId(1);
realm.executeTransaction(new Realm.Transaction()
{
    @Override
    public void execute(Realm realm)
    {
        Dog dog1 = new Dog();
        dog1.setId(1);
        dog1.setAge(5);
        dog1.setName("藏獒");
        dogs = new RealmList<Dog>();
        dogs.add(dog1);
        user.setDogs(dogs);
        realm.copyToRealmOrUpdate(user);
    }
});
}    

當(dāng)user沒有主鍵時(shí)使用如下方式:

realm.executeTransaction(new Realm.Transaction()
{
@Override    
public void execute(Realm realm) {
    User user = realm.createObject(User.class);        
    user.setName("Gain");        
    user.setAge(23);       
    Dog dog1 = realm.createObject(Dog.class);        
    dog1.setAge(1);        
    dog1.setName("二哈");        
    user.getDogs().add(dog1);        
    Dog dog2 = realm.createObject(Dog.class);        
    dog2.setAge(2);        
    dog2.setName("阿拉撕家");        
    user.getDogs().add(dog2);    
}
});

使用異步方式進(jìn)行數(shù)據(jù)插入蜕青,具體的方式如下:

使用異步插入,可以檢測(cè)數(shù)據(jù)是否插入成功捧韵,成功后可以使用new Realm.Transaction.OnSuccess()進(jìn)行監(jiān)測(cè)市咆,失敗可以使用new Realm.Transaction.OnError()監(jiān)測(cè)。

/**
 * 異步執(zhí)行
 * 向有主鍵的數(shù)據(jù)表中insert或update數(shù)據(jù)
 * 數(shù)據(jù)表中有當(dāng)前主鍵時(shí)則執(zhí)行update
 * 否者執(zhí)行insert
 */
private void insertOrUpdateDataWithPrimaryKeyAsync()
{
final User user = new User();
user.setName("李德華");
user.setUserId("admin");
user.setAge(25);
user.setId(1);

task = realm.executeTransactionAsync(new Realm.Transaction()
{
    @Override
    public void execute(Realm realm)
    {
        Dog dog1 = new Dog();
        dog1.setId(1);
        dog1.setAge(5);
        dog1.setName("藏獒");
        dogs = new RealmList<Dog>();
        dogs.add(dog1);
        user.setDogs(dogs);
        realm.copyToRealmOrUpdate(user);
    }
}, new Realm.Transaction.OnSuccess()
{
    @Override
    public void onSuccess()
    {
        Logger.d("Success");
    }
}, new Realm.Transaction.OnError()
{
    @Override
    public void onError(Throwable error)
    {
        Logger.d("Error");
    }
});
}

注意:如果當(dāng)Acitivity或Fragment被銷毀時(shí)再来,在OnSuccess或OnError中執(zhí)行UI操作蒙兰,將導(dǎo)致程序奔潰 。用RealmAsyncTask .cancel();可以取消事務(wù)芒篷,在onStop中調(diào)用搜变,避免crash

@Override
protected void onStop()
{
super.onStop();
if (task != null && task.isCancelled())
{
    task.cancel();
}
}   

將Json數(shù)據(jù)直接插入數(shù)據(jù)庫(kù)

Realm有一個(gè)強(qiáng)大的功能就是將Json數(shù)據(jù)直接插入到相應(yīng)的數(shù)據(jù)庫(kù),具體的代碼入下:

/**
* 將Json數(shù)據(jù)添加到數(shù)據(jù)表中
*/
private void insertDataFromJson()
{
realm.executeTransaction(new Realm.Transaction()
{
    @Override
    public void execute(Realm realm)
    {
        realm.createOrUpdateObjectFromJson(User.class, "{ id: 2, age: 50, name:\"sealong\",userId:\"admin\",
                      dogs:[{id:5,name:\"龍騎士\",age:3},{id:6,name:\"豬騎士\",age:4},{id:7,name:\"馬騎士\",age:5}]}");
    }
});
}

Realm 解析 JSON 時(shí)遵循如下規(guī)則:
1.使用包含空值(null)的 JSON 創(chuàng)建對(duì)象:

2.對(duì)于非必須(可為空值的屬性)针炉,設(shè)置其值為 null挠他;

3.對(duì)于必須(不可為空值的屬性),拋出異常篡帕;

4.使用包含空值(null)的 JSON 更新對(duì)象:

5.對(duì)于非必須(可為空值的屬性)殖侵,設(shè)置其值為 null;

6.對(duì)于必須(不可為空值的屬性)镰烧,拋出異常钱雷;

7.使用不包含對(duì)應(yīng)屬性的 JSON: * 該屬性保持不變

5.刪

Realm的刪除凉唐,包含兩個(gè)步驟,首先查找到相應(yīng)的數(shù)據(jù)集合,在在集合中刪除相應(yīng)的數(shù)據(jù)烁挟,代碼如下:

private void deleteData()
{    //先查找到數(shù)據(jù)    
 final RealmResults<User> userList = realm.where(User.class).findAll();    
 realm.executeTransaction(new Realm.Transaction()    
 {        
     @Override        
     public void execute(Realm realm)        
     {            
         userList.get(4).deleteFromRealm();//刪除指定位置(第4條記錄)的記錄
         userList.deleteFromRealm(4);//刪除指定位置(第4條記錄)的記錄            
         userList.deleteFirstFromRealm(); //刪除user表的第一條數(shù)據(jù)            
         userList.deleteLastFromRealm();//刪除user表的最后一條數(shù)據(jù)            
         userList.deleteAllFromRealm();//刪除user表的全部數(shù)據(jù)        
     }    
  });
}

6.改

改是通過先查找到相應(yīng)的數(shù)據(jù),然后再設(shè)置需要修改的相應(yīng)的信息。
例如修改User表中name=sealong 并且Id=2的所有對(duì)象,并將其UserId設(shè)置為user的代碼如下艾凯。

private void dataUpdate()
{
realm.executeTransaction(new Realm.Transaction()
{
    @Override
    public void execute(Realm realms)
    {
        //先查找后得到User對(duì)象
        RealmResults<User> users = realm.where(User.class).equalTo("name", "sealong").equalTo("id", 2).findAll();
        for (User user : users)
        {
            user.setUserId("user");
        }
    }
});
}

7.查

查找常用的函數(shù)有:
findAll ---- 查詢滿足條件的所有記錄

findAllAsync----異步查詢(當(dāng)數(shù)據(jù)量較大,可能會(huì)引起ANR的時(shí)候懂傀,就可以使用findAllAsync)

findFirst ---- 查詢第一條數(shù)據(jù)

equalTo ---- 根據(jù)條件查詢(多次使用該函數(shù)可以實(shí)現(xiàn)多條件查詢)

sum ---- 對(duì)指定字段求和趾诗。

average ---- 對(duì)指定字段求平均值。

min ---- 對(duì)指定字段求最小值鸿竖。

max ---- 對(duì)指定字段求最大值沧竟。count : 求結(jié)果集的記錄數(shù)量。

findAll ---- 返回結(jié)果集所有字段缚忧,返回值為
RealmResults隊(duì)列

findAllSorted ---- 排序返回結(jié)果集所有字段悟泵,返回值為RealmResults隊(duì)列

between ---- 指定字段的值在某區(qū)間內(nèi)

greaterThan()|lessThan()----指定字段的值大于(小于)給定的值

greaterThanOrEqualTo() & lessThanOrEqualTo()----指定字段的值大于等于(小于等于)給定的值

equalTo() & notEqualTo() ---- 指定字段的值(不)等于

contains() ----指定字段的值包含某些字符(指定字段為String)

beginsWith() & endsWith() ----指定字段的值以給定的值開始(結(jié)束)

isNull() & isNotNull() ----指定字段的值(不)為null

isEmpty() & isNotEmpty() ----指定字段的值(不)為空

private void dataSelectUser()
{
    RealmResults<User> users = realm.where(User.class).findAllSorted("id", Sort.DESCENDING);//按照id倒序排序
long size = users.size();//返回?cái)?shù)據(jù)的條數(shù)
double average = users.average("age");//返回查詢結(jié)果的中age的平均值
long sum = users.sum("age").longValue();//返回查詢結(jié)果中age的總數(shù)
long min = users.min("age").longValue();//返回查詢結(jié)果中age的最小值
long max = users.max("age").longValue();//返回查詢結(jié)果中age的最大值
}

8.數(shù)據(jù)庫(kù)升級(jí)

當(dāng)某個(gè)數(shù)據(jù)表需要加某些字段或者添加某些屬性時(shí),而且不刪除之前的原始數(shù)據(jù)的情況下闪水,需要對(duì)原始數(shù)據(jù)進(jìn)行升級(jí)
例如需要對(duì)表刪除字段age糕非,并且需要添加一個(gè)String類型的userId 并且設(shè)置將之前表中的userId的值設(shè)置為1,同時(shí)版本號(hào)需要更新

public class Migration implements RealmMigration
{
/**
 * 升級(jí)數(shù)據(jù)庫(kù)
 */
@Override
public void migrate(DynamicRealm realm, long oldVersion, long newVersion)
{
    RealmSchema schema = realm.getSchema();
    if (oldVersion != newVersion)
    {
        RealmObjectSchema personSchema = schema.get("User");
        //新增@Required的id
        personSchema.addField("userId", String.class, FieldAttribute.REQUIRED)
                .transform(new RealmObjectSchema.Function()
                {
                    @Override
                    public void apply(DynamicRealmObject obj)
                    {
                        obj.set("userId", "1");//為id設(shè)置值
                    }
                }).removeField("age");
        oldVersion++;
    }
}
}

轉(zhuǎn)載自: Realm在android的應(yīng)用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末球榆,一起剝皮案震驚了整個(gè)濱河市朽肥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌持钉,老刑警劉巖衡招,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異每强,居然都是意外死亡始腾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門空执,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浪箭,“玉大人,你說我怎么就攤上這事辨绊∧唐埽” “怎么了?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵门坷,是天一觀的道長(zhǎng)宣鄙。 經(jīng)常有香客問我,道長(zhǎng)默蚌,這世上最難降的妖魔是什么框冀? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮敏簿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己惯裕,他們只是感情好温数,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蜻势,像睡著了一般撑刺。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上握玛,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天够傍,我揣著相機(jī)與錄音,去河邊找鬼挠铲。 笑死冕屯,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拂苹。 我是一名探鬼主播安聘,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼瓢棒!你這毒婦竟也來了浴韭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤脯宿,失蹤者是張志新(化名)和其女友劉穎念颈,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體连霉,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡榴芳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窘面。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翠语。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖财边,靈堂內(nèi)的尸體忽然破棺而出肌括,到底是詐尸還是另有隱情,我是刑警寧澤酣难,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布谍夭,位于F島的核電站,受9級(jí)特大地震影響憨募,放射性物質(zhì)發(fā)生泄漏紧索。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一菜谣、第九天 我趴在偏房一處隱蔽的房頂上張望珠漂。 院中可真熱鬧晚缩,春花似錦、人聲如沸媳危。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)待笑。三九已至鸣皂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間暮蹂,已是汗流浹背寞缝。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仰泻,地道東北人荆陆。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像我纪,于是被迫代替她去往敵國(guó)和親慎宾。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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