realm数据库

React Native 存储方案——AsyncStorage

React Native 官方存储方案是 AsyncStorage。AsyncStorage 是一个简单的、异步的、持久化的 Key-Value 存储系统,它对于 App 来说是全局性的。可用来代替 LocalStorage。官方推荐使用者在 AsyncStorage 的基础上做一层抽象封装,而不是直接使用 AsyncStorage。

AsyncStorage 封装库——realm

realm 是一款专为移动 端开发的高性能数据库,其宣称自己是最快的 React Native 数据库。
realm 整体的优点有这么四点:
1.简单易用,2.跨平台,3.快速性能优越,4.提供高级功能。
realm 核心数据引擎用 C++ 打造,并不是建立在 SQLite 之上的 ORM。因此性能就是比普通的 ORM 要快很多,甚至比单独无封装的 SQLite 还要快。同时因为是 ORM,本身在设计时也针对移动设备(iOS、Android),所以简单易用,学习成本很低。

realm 常用操作

1、定义 model

作为数据库,使用它无法就是「增删改查」等基本操作,使用之前,需要定义 model:
name:表格名称。
primaryKey:主键,这个属性的类型可以是 ‘int’ 和 ‘string’,并且如果设置主键之后,在更新和设置值的时候这个值必须保持唯一性,并且无法修改。声明主键可以有效地查找和更新对象,并为每个值强制实现唯一性。
properties:这个属性内放置需要的字段。

  1. // models/hello.ts
  2. export const HelloSchema = {
  3. name: "Hello",
  4. primaryKey: "uid", // 定义主键后,无法创建同一主键的数据
  5. properties: {
  6. uid: "string",
  7. name: "string", // {type: 'string'} 的简写
  8. phone: { type: "string", default: "136xxxxxxxx" }
  9. }
  10. };

2、初始化

// 根据提供的表初始化 Realm,可同时往数组中放入多个表

  1. let realm = new Realm({ schema: [HelloSchema] });

3、增加数据

对域中对象的更改、创建、更新和删除,必须在 write()事务块中进行。
需要注意:写入事务具有不可忽略的开销,应该尽量减少代码中写入块的数量。

  1. try {
  2. realm.write(() => {
  3. realm.create("Hello", {
  4. uid: "a371d56d7b6f77ba31f71d22",
  5. name: "名字1",
  6. phone: "137xxxxxxxx"
  7. });
  8. realm.create("Hello", {
  9. uid: "a371d56d7b6f77ba31f71d22",
  10. name: "名字1",
  11. phone: "137xxxxxxxx"
  12. });
  13. // ...
  14. });
  15. catch(e) {
  16. console.log("Error on creation");
  17. }
  18. }

定义 model 时使用了 primaryKey,如果写入 primaryKey 之前的数据中已存在时,写入会出错,并且如果此时写入的是多个数据时,会导致后面的写入失败,所以可以在单个 realm.create('Hello', item) 的外面使用一个 try...catch...

  1. const result = await new Promise((resolve, reject) => {
  2. try {
  3. realm.write(() => {
  4. for (let item of data) {
  5. try {
  6. realm.create("Hello", item);
  7. } catch (e) {
  8. console.log("write error: ", e);
  9. }
  10. }
  11. resolve("ok");
  12. });
  13. } catch (e) {
  14. console.log("write error: ", e);
  15. resolve("error");
  16. }
  17. });
  18. console.log("write result: ", result);

4、查找和删除数据

查询数据允许从 realm 获取单个类型的对象,并可选择过滤和排序这些结果。最基本方法是使用 objects 方法获取给定类型的所有对象。

  1. let dogs = realm.objects('Dog'); // retrieves all Dogs from the Realm

Filtering 参数可过滤查找结果:

  1. let dogs = realm.objects('Dog').filtered('color = "tan" AND name BEGINSWITH "B"');

Sorting 参数允许根据单个或多个属性指定排序条件和顺序:

  1. let hondas = realm.objects('Car').filtered('make = "Honda"');
  2. // Sort Hondas by mileage
  3. let sortedHondas = hondas.sorted('miles');
  4. // Sort in descending order instead
  5. sortedHondas = hondas.sorted('miles', true);
  6. // Sort by price in descending order and then miles in ascending
  7. sortedHondas = hondas.sorted([['price', true], ['miles', false]]);

Limiting 参数提供了对查询结果进行“分页”的能力。这通常是为了避免从磁盘中读取太多内容,或者一次将太多结果拖入内存中。由于 realm 中的查询是惰性的,因此根本不需要执行这种分页行为,因为 realm 只会在显式访问后从查询结果中加载对象。

  1. let cars = realm.objects('Car'); let firstCars = cars.slice(0, 5);

// 删除单个数据

  1. let result = await new Promise((resolve, reject) => {
  2. try {
  3. realm.write(() => {
  4. for (let uid of data) {
  5. try {
  6. let dataRource = realm.objects("Hello").filtered(`uid = "${uid}"`);
  7. realm.delete(dataRource);
  8. console.log("delete: ", uid);
  9. } catch (e) {
  10. console.log("delete error: ", uid);
  11. }
  12. }
  13. resolve("delete ok!");
  14. });
  15. } catch (e) {
  16. console.log("delete error: ", e);
  17. resolve("delete error!");
  18. }
  19. });
  20. console.log("delete done!: ", result);
  21. // delete all Hello
  22. let result = await new Promise((resolve, reject) => {
  23. try {
  24. let dataRource = realm.objects("Hello");
  25. realm.write(() => {
  26. realm.delete(dataRource);
  27. resolve("delete done!");
  28. });
  29. } catch (e) {
  30. resolve("delete error!");
  31. }
  32. });
  33. console.log("delete done!:", result);

5、 修改数据

如果定义 model 时包含主键,则可以让 realm 根据其主键值智能地更新或添加对象。更新时将 true 作为第三个参数传递给 create 方法。

  1. realm.write(() => {
  2. realm.create("Hello", {
  3. uid: "a371d56d7b6f77ba31f71d22",
  4. name: "Recipes",
  5. phone: "135xxxxxxxx"
  6. });
  7. // Update book with new price keyed off the id
  8. realm.create(
  9. "Hello",
  10. { uid: "a371d56d7b6f77ba31f71d22", phone: "138xxxxxxxx" },
  11. true
  12. );
  13. });

使用报错记录

1、安卓打包安装进入闪退

  1. java.lang.ClassNotFoundException: Didn't find class on path: DexPathList - io.realm.react.utils.SSLHelper

试着在 android/app/proguard-rules.pro 加上 -keep class io.realm.react.**可以解决,因为这打包的时候包混淆引起的。

2、删除操作记录时报错

  1. Accessing object of type X which has been invalidated or deleted

删除部分数据后,必须更新 store ,如果需要显示删除后的数据也必须先把 store 中显示的 realm 数据置为空,然后再去重新查询。