Realm 是一个移动数据库,可运行于手机、平板和可穿戴设备之上。可以让你的应用更快速,带来难以想象的体验。其目标是为了代替 CoreData 和 SQLite 数据库。

Realm 的优点

  • 易用

Ream 不是在SQLite基础上的ORM,它有自己的数据查询引擎。并且十分容易使用。

  • 快速

由于它是完全重新开始开发的数据库实现,所以它比任何的ORM速度都快很多,甚至比SLite速度都要快。

  • 跨平台

Realm 支持 iOS & OS X (Objective‑C & Swift) & Android。我们可以在这些平台上共享Realm数据库文件,并且上层逻辑可以不用任何改动的情况下实现移植。

  • 高级

Ream支持加密,格式化查询,易于移植,支持JSON,流式api,数据变更通知等高级特性

  • 可视化

Realm 还提供了一个轻量级的数据库查看工具,在Mac Appstore 可以下载“Realm Browser”这个工具,开发者可以查看数据库当中的内容,执行简单的插入和删除数据的操作。

Realm的使用条件

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

1.加入依赖关系

(1)在project的build中加入依赖

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

(2)在module中加入

   apply plugin: 'realm-android

2.创建和初始化

(1)、使用RealmConfiguration配置Realm

创建数据库时首先需要调用Realm.init()方法,否则系统报错:java.lang.IllegalStateException: Call `Realm.init(Context)` before creating a RealmConfiguration

数据库初始化主要工作是什么数据库的name(设置数据库的文件名称)、schemaVersion(设置当前数据库版本号,当前版本号不能小于历史版本号)、migration(数据库版本迁移)、 deleteRealmIfMigrationNeeded(版本冲突时删除原始数据库)、inMemory(在内存中持久化,关闭后自动删除)、build(创建数据库)。

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) //版本号.migration(migration)//数据库版本迁移(数据库升级,当数据库中某个表添加字段或者删除字段).deleteRealmIfMigrationNeeded()//声明版本冲突时自动删除原数据库(当调用了该方法时,上面的方法将失效)。.build();//创建return Realm.getInstance(config);
}

执行该方法后将生成一个文件名为:realmdb.realm的数据库文件。

(2)使用默认配置

     Realm.init(this);Realm mRealm = Realm.getDefaultInstance();

使用默认配置将生成一个名为default.realm数据库文件

note:记得使用完后,在onDestroy中关闭Realm
          @Override
           protected void onDestroy() {
                  super.onDestroy();
                  // Close the Realm instance.
                  realm.close();
           }

3、创建model

创建一个类名为User的model,首先该类必须继承自RealmObject,只有这才用使用Realm来操作model生成相应的表。

在Realm支持的类型有:boolean, byte, short,int,long,float, double,String, Date,byte[], RealmObject, RealmList<? extends RealmObject>还支持Boolean, Byte, Short, Integer, Long, Float 和 Double。但是:整数类型 short、int 和 long 都被映射到 Realm内的相同类型(实际上为 long )。

@PrimaryKey——表示该字段是主键
       PrimaryKey就是主键。使用@PrimaryKey来标注,字段类型必须是字符串(String)或整数(byte,short,int或long)以及它们的包装类型(Byte,Short, Integer, 或 Long)。一个model中不可以存在多个主键,使用字符串字段作为主键意味着字段被索引(注释@PrimaryKey隐式地设置注释@Index)。

@Required——表示该字段非空
      在某些情况下,某些属性是不能为null的。使用@Required可用于用于强行要求其属性不能为空,只能用于Boolean, Byte, Short, Integer, Long, Float, Double, String, byte[] 和 Date。在其它类型属性上使用 @Required修饰会导致编译失败。
      note:基本数据类型不需要使用注解 @Required,因为他们本身就不可为空。

  @Ignore——表示忽略该字段
      如果想忽略某个字段,则可以使用@Ignore修饰该字段,被秀@ignore修饰的字段在存储数据时会忽略该字段。

@Index——添加搜索索引
     使用@index可以为字段添加搜索索引,使用索引以后使得插入的速度变慢,数据量也变得更大。但是在查询速度将变得更快,所以建议只在优化读取性能的特定情况时添加索引。

支持索引:String,byte,short,int,long,boolean和Date字段。

public class User extends RealmObject
{@PrimaryKeyprivate int id;private int age;@Requiredprivate 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;}
}

接下来开始数据库的CRUD操作了。

4、增

写入操作需要在事务中进行,

*使用executeTransaction方法来开启事务。

当model没有primaryKey时,可以使用下面的方法

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

当model有primaryKey时,则可以使用下面的方法,将对@primaryKey修饰的字段直接在创建对象是赋值(createObject(User.class,1))

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

*使用copyToRealmOrUpdate或copyToRealm方法插入数据

当model中含有primaryKey时使用copyToRealmOrUpdate插入数据,在当前插入主键的值存在时则修改对应主键值相关的数据信息,否则插入数据。

当model中不含有主键时,则使用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(){@Overridepublic void execute(Realm realm){                realm.copyToRealmOrUpdate(user);}});

当在model(User)中包办另外一个model例如在User中包含一个Dog模型,也可以包含一个Dog的集合

还记得在之前的User数据模型中含有这么一块代码吗?这个申明表示一个User中可以包含(养)多条狗(Dog)

在Realm中List类型表示为RealmList。

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

向数据模型(User)插入另外一个数据模型(Dog)时,可以才用如下方式(当User含有主键时采用):

private void insertOrUpdateDataWithPrimaryKey()
{final User user = new User();user.setName("李德华");user.setUserId("admin");user.setAge(25);user.setId(1);realm.executeTransaction(new Realm.Transaction(){@Overridepublic 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);}});
}

当user没有主键时使用如下方式:

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);        }});

*使用异步方式进行数据插入,具体的方式如下:

使用异步插入,可以检测数据是否插入成功,成功后可以使用new Realm.Transaction.OnSuccess()进行监测,失败可以使用new Realm.Transaction.OnError()监测。

/*** 异步执行* 向有主键的数据表中insert或update数据* 数据表中有当前主键时则执行update* 否者执行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(){@Overridepublic 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(){@Overridepublic void onSuccess(){Logger.d("Success");}}, new Realm.Transaction.OnError(){@Overridepublic void onError(Throwable error){Logger.d("Error");}});
}

注意:如果当Acitivity或Fragment被销毁时,在OnSuccess或OnError中执行UI操作,将导致程序奔溃 。用RealmAsyncTask .cancel();可以取消事务,在onStop中调用,避免crash

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

*将Json数据直接插入数据库

Realm有一个强大的功能就是将Json数据直接插入到相应的数据库,具体的代码入下:

/*** 将Json数据添加到数据表中*/
private void insertDataFromJson()
{realm.executeTransaction(new Realm.Transaction(){@Overridepublic 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 时遵循如下规则:
    1.使用包含空值(null)的 JSON 创建对象:
    2.对于非必须(可为空值的属性),设置其值为 null;
    3.对于必须(不可为空值的属性),抛出异常;
    4.使用包含空值(null)的 JSON 更新对象:
    5.对于非必须(可为空值的属性),设置其值为 null;
    6.对于必须(不可为空值的属性),抛出异常;
    7.使用不包含对应属性的 JSON: * 该属性保持不变

5.删

Realm的删除,包含两个步骤,首先查找到相应的数据集合,在在集合中删除相应的数据,代码如下:

private void deleteData()
{    //先查找到数据    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表的第一条数据            userList.deleteLastFromRealm();//删除user表的最后一条数据            userList.deleteAllFromRealm();//删除user表的全部数据        }    });
}

6.改

改是通过先查找到相应的数据,然后再设置需要修改的相应的信息。

例如修改User表中name=sealong 并且Id=2的所有对象,并将其UserId设置为user的代码如下。

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

7.查

查找常用的函数有:

findAll ---- 查询满足条件的所有记录

findAllAsync----异步查询(当数据量较大,可能会引起ANR的时候,就可以使用findAllAsync)

findFirst ---- 查询第一条数据

equalTo ---- 根据条件查询(多次使用该函数可以实现多条件查询)

sum ---- 对指定字段求和。

average ---- 对指定字段求平均值。

min ---- 对指定字段求最小值。

max ---- 对指定字段求最大值。count : 求结果集的记录数量。

findAll ---- 返回结果集所有字段,返回值为RealmResults队列

findAllSorted ---- 排序返回结果集所有字段,返回值为RealmResults队列

between ---- 指定字段的值在某区间内

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

greaterThanOrEqualTo() & lessThanOrEqualTo()----指定字段的值大于等于(小于等于)给定的值
equalTo() & notEqualTo() ---- 指定字段的值(不)等于
contains() ----指定字段的值包含某些字符(指定字段为String)

beginsWith() & endsWith() ----指定字段的值以给定的值开始(结束)
isNull()  & isNotNull() ----指定字段的值(不)为null
isEmpty() & isNotEmpty() ----指定字段的值(不)为空

private void dataSelectUser(){RealmResults<User> users = realm.where(User.class).findAllSorted("id", Sort.DESCENDING);//按照id倒序排序long size = users.size();//返回数据的条数double average = users.average("age");//返回查询结果的中age的平均值long sum = users.sum("age").longValue();//返回查询结果中age的总数long min = users.min("age").longValue();//返回查询结果中age的最小值long max = users.max("age").longValue();//返回查询结果中age的最大值
}

8.数据库升级

当某个数据表需要加某些字段或者添加某些属性时,而且不删除之前的原始数据的情况下,需要对原始数据进行升级

例如需要对表删除字段age,并且需要添加一个String类型的userId 并且设置将之前表中的userId的值设置为1,同时版本号需要更新

public class Migration implements RealmMigration
{/*** 升级数据库*/@Overridepublic void migrate(DynamicRealm realm, long oldVersion, long newVersion){RealmSchema schema = realm.getSchema();if (oldVersion != newVersion){RealmObjectSchema personSchema = schema.get("User");//新增@Required的idpersonSchema.addField("userId", String.class, FieldAttribute.REQUIRED).transform(new RealmObjectSchema.Function(){@Overridepublic void apply(DynamicRealmObject obj){obj.set("userId", "1");//为id设置值}}).removeField("age");oldVersion++;}}
}

最后贴出本人测试的源代码:http://download.csdn.net/detail/sealong_/9741919

Realm在android的应用相关推荐

  1. realm android,Realm for Android快速入门教程

    介绍 如果你关注安卓开发的最新趋势,你可能已经听说过 Realm .Realm是一个可以替代SQLite以及ORMlibraries的轻量级数据库. 相比SQLite,Realm更快并且具有很多现代数 ...

  2. Realm for Android 使用入门

    Realm 是一个手机数据库,是用来替代 SQlite 的解决方案,比 SQlite 更轻量级,速度更快,因为它有一套自己的数据库搜索引擎,并且还具有很多现代数据库的优点,支持 JSON,流式 API ...

  3. realm教程 android,Realm for Android基本教程

    8种机械键盘轴体对比 本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选? Realm是一款开源的数据库工具,它具有快速,易于使用和支持多平台的特点.它完全可以取代我们Android中的SQLit ...

  4. 【Android开发】【数据库】Realm For Android

    目录 1.Realm简介 2.环境配置 3.初始化Realm 4.创建实体 5.增 6.删 7.改 8.查 9.异步操作 10.数据库数据更新监听 11.json转对象,插入数据库 12.Demo地址 ...

  5. 《Android开源库》 Realm For Android~ Queries(译文)

    查询 Realm 中的所有读取(包括查询)操作都是延迟执行的,且数据绝不会被拷贝. Realm 的查询引擎使用 Fluent interface 来构造多条件查询. 使用 User 类 - publi ...

  6. Android数据库新王者-Realm入门教程

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u010046908/article/details/51629262 好长时间没有写关于Androi ...

  7. Android Realm数据库

    In this tutorial, we'll be discussing the basics of Realm Database and implement it in our Android A ...

  8. 【Android】Realm详解(Android 数据库Sqlite的完美替代者)

    介绍 Realm 是一个 MVCC (多版本并发控制)数据库,由Y Combinator公司在2014年7月发布一款支持运行在手机.平板和可穿戴设备上的嵌入式数据库,目标是取代SQLite. Real ...

  9. android Realm 优化

    Realm数据库优化 Realm数据的一个特点是支持跨平台操作,且效率上面比较高,是非关系数据库.但是在使用的过程中还是存在很多可以优化的控件,本文章重点解决Realm数据库无表信息和列信息,和Rea ...

  10. Android 开源框架选择

    目录 一.前言 二.APP的整体架构 三.技术选型的考量点 四.日志记录能力 五.JSON解析能力 1.gson 2.jackson 3.Fastjson 4.LoganSquare 六.数据库操作能 ...

最新文章

  1. 基于RDKit的溶解度预测的机器学习模型
  2. linux 内核编译错误 undefined reference to '__mutex_lock_slowpath'
  3. 全局变量/static静态变量在section段中的分布
  4. python从数据库取数据保存为excel_python读取数据库表数据并写入excel
  5. 自由自在意式手工冰淇淋的清凉之风已“冰”临城下
  6. linux 安装软件_Linux:其它软件安装方式
  7. [JS-DOM]事件监听机制
  8. Windows内核函数
  9. Git Permission to fazhiyun86/Test.git denied to MarRoar
  10. 了解Base64编码的原理(js核对)
  11. MIT自适应律MRAC的理解和MATLAB实现
  12. c语言文件归档,Go语言tar归档文件的读写操作
  13. 使用mingw编译log4cpp--问题整理
  14. Excel如何统计多种分隔符号的单元格姓名个数
  15. java 考勤_java,添加一个类,显示考勤信息的。
  16. c语言中front是什么,front用法,关于front的用法
  17. 打破思维断层之KMP分析
  18. 申宝投资-三大股指开盘逐渐下跌
  19. Servlet - Filtering (过滤器))
  20. 现代 Web 开发的现状与未来

热门文章

  1. powerha_使用IBM PowerHA SystemMirror的Hitachi TrueCopy镜像
  2. python 标签云_Python中文标签云之pytagcloud
  3. Java 给PDF文件添加水印
  4. matlab求解微分方程ode23
  5. Fiddler抓包工具报:The system ptoxy changed. Click to reenable capturing
  6. 大数据技术学习带来的思考
  7. 图像曲率 与 黎曼几何
  8. pip install:Requirement already satisfied
  9. 产品线管理:学习笔记
  10. 云桌面-ThinVirt3-EXP操作手册(一)云桌面系统安装