在RN中使用realm数据库

Posted openglnewbee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在RN中使用realm数据库相关的知识,希望对你有一定的参考价值。

在移动开发领域,realm是最热门的跨平台数据库,没有之一。而现在,realm已经把他的触手伸到了服务端,在node.js服务器上也可以运行realm了(可以认为是mongodb的竞争对手了)。但我们这里所讨论的realm仍然局限于realm的本地数据库,也就是它一开始被设计用来做的事:在ios上的竞争对手是fmdb/coredata, 安卓上的greendao等。

realm的js文档非常完备和友好,推荐大家阅读,我这里会简单介绍一下它主要的功能和使用。

https://realm.io/docs/javascript/latest/

1. schema. schema是realm的模型,也就是说它定义了model的格式;在rn上我们可以通过json和es 6的class两种方式来对它进行定义; 这里的name唯一代表了一个model的类型,如果需要升级之则需要给realmdb指定版本号:schemaVersion; 值得一提的是realm的模型升级机制非常完备,并且考虑了多版本升级的数据迁移问题,可谓是非常贴心了。model的所有字段都支持默认值设置,例:

 miles: type: 'int',    default: 0

2. realm支持的数据类型有:bool, string, date, int ,float, double ,data(数组); 作为一个orm的数据库,当然它也可以将realm的对象嵌套在model中存储。此时我们在model里面给字段指定类型的时候就要输入嵌套对象的name。realm也支持将对象放在数组中作为属性,比如一个person可以拥有一个dogs的字段,这里存放的是dog类型的对象数组。这是一种单向的链接关系(dog存放在dog表中,person则拥有他的dogs),我们还可以在dog里面指定反向的链接关系,代码示例如下:

const PersonSchema = 
  name: 'Person',
  properties: 
    dogs: 'Dog[]'
  


const DogSchema = 
  name:'Dog',
  properties: 
    // No shorthand syntax for linkingObjects properties
    owners: type: 'linkingObjects', objectType: 'Person', property: 'dogs'
  
这里的狗可能是属于某个家庭,一个人也可能拥有多只狗,所以这里的狗和人存在正向和反向的链接关系。

3. 字段可以设置为索引值(付出的代价是插入变慢,收获是查询和搜索速度变快),且一个model可以设置一个主键值(类型可以是string或者int),可以通过主键直接访问对象。

4. 关于操作:增删改相关的操作一般来说需要放在write block中(transaction),代码编写起来也是比较方便的。realm支持对象的排序、过滤搜索等,还支持简单的语句(类似于iOS中的NSPredicate)。值得一提的是realm的值都是lazy load的,所以对于大数据集的访问可以直接获取,而不用担心内存溢出之类的问题,使用的时候先排序再通过slice获取即可。 也是基于性能的考虑,realm获取到的值的顺序并不能保证和插入的顺序一致,所以在开发时需要通过你自己的机制来保证顺序(比如key或者基于值的排序等等)。

5. 同步访问: realm db除了通过异步方式打开以外,也支持同步打开db进行操作(但不推荐,因为同步方式会带来可能的数据不一致等问题,还有可能有性能方面的问题),代码如下:

const realm = new Realm(schema: [PersonSchema]);

// You can now access the realm instance.
realm.write(/* ... */);
6. 数据库变更的通知

通知机制让我们可以以一种优雅的方式在多处操作数据库并刷新UI。对于本地数据库,realm提供了两个维度的通知:

a. 数据库变更通知

function updateUI() 
  // ...


// Observe Realm Notifications
realm.addListener('change', updateUI);
这是一种很粗的listener,当write transaction发生时,就会触发这个事件。所有的增、删、改操作都应该在write transaction内部发生,也就是说会引发数据库的变更。我们可以在这里做一个简单的reload.

b. 数据集变更通知

该通知是绑定在realm对象/对象集合上的。回调的参数也有两个:1.观察的数据集本身 2.变更

示例代码如下:

// Observe Collection Notifications
realm.objects('Dog').filtered('age < 2').addListener((puppies, changes) => 

  // Update UI in response to inserted objects
  changes.insertions.forEach((index) => 
    let insertedDog = puppies[index];
    ...
  );

  // Update UI in response to modified objects
  changes.modifications.forEach((index) => 
    let modifiedDog = puppies[index];
    ...
  );

  // Update UI in response to deleted objects
  changes.deletions.forEach((index) => 
    // Deleted objects cannot be accessed directly
    // Support for accessing deleted objects coming soon...
    ...
  );

);

// Unregister all listeners
realm.removeAllListeners();
此外,realm也支持同时存在多个db以及配置不同的本地存储路径、支持64位的aes加密、支持inmemory模式等等,作为一个移动db领域的巨头玩家,我认为realm可以作为react native开发中本地数据库的第一选择。

以上是关于在RN中使用realm数据库的主要内容,如果未能解决你的问题,请参考以下文章

使用VSCode调试RN项目

动态更改文本输出 - React Native

shiro之自定义Realm之继承AuthorizingRealm

Shrio02 Realm作用自定义简洁RealmRealm实现类使用

在循环中使用Realm或在Android中插入列表

使用 Combine 和 SwiftUI 在 Realm 中观察收集结果