Flutter中的Parse 1对多关系实现指南
Flutter中的一对多关系
介绍
使用Parse,您可以存储数据对象并在它们之间建立关系。要建模这种行为,任何 ParseObject 都可以作为其他 ParseObject 的值。内部,Parse框架将只在一个地方存储被引用的对象,以保持一致性。这可以在构建和运行复杂查询时为您提供额外的能力。主要有三种关系类型:
- 一对一, 在两个对象之间建立直接关系,仅限于这两个对象;
- 一对多, 一个对象可以与多个其他对象相关;
- 多对多, 可以在多个对象之间创建许多复杂的关系。
在本指南中,我们将详细说明如何使用一个实际应用示例来实现 一对多 关系。 在 Parse 中有两种方法可以创建 一对多 关系:
- 第一种是使用 指针 在 子类中,这是创建和查询时间最快的方法。
- 第二种是使用 数组 的 指针 在父类中,这可能会导致查询时间变慢,具体取决于它们的大小。由于这个性能问题,我们将仅使用指针示例。
您将实现一个 Flutter 图书注册应用,并将使用 Parse 指针 创建和查询相关对象。
关系如 一对一 并不常见,我们不会在我们的指南中涵盖。 作为示例,用户类与另一个类之间的关系将包含敏感用户数据,出于 安全原因 (1.4. 不要让用户访问其他用户的敏感数据)。
前提条件
- 一个连接到 Back4app 的 Flutter 应用。
- 一台运行 Android 或 iOS 的设备(或虚拟设备)。
理解书籍应用
您将使用的主要对象类是 书籍 类,存储每本书的注册条目。此外,还有其他三个对象类:
- 出版商: 书籍出版商名称,与 书籍 的一对多关系;
- 类型: 书籍类型,与 书籍 的一对多关系。请注意,在本示例中,我们将考虑一本书只能有一个类型;
- 作者: 书籍作者,与 书籍 的多对多关系,因为一本书可以有多个作者,而一个作者也可以有多本书;
这些数据模型的可视化表示:

我们将假设每个对象类 (发布者, 类型) 只有一个字符串类型的 名称 属性,而 书籍 具有 标题 和 年份, 除了任何额外的关系属性。在之前的指南中,我们已经看到如何保存和读取 ParseObject,因此在本指南中,我们将不再介绍如何保存和读取 类型 和 发布者 对象。
您将在书籍应用程序中找到以下屏幕:
- 类型的注册和列表
- 发布者的注册和列表
- 书籍注册
- 发布者和书籍列表
- 书籍详情
我们不会解释Flutter应用程序代码,因为本指南的主要重点是使用Flutter与Parse进行关系。
1 - 创建图书应用模板
让我们首先运行图书应用项目模板。从之前的指南中打开您的Flutter项目 Flutter插件用于Parse服务器。 图书Flutter应用 仓库也可以供您克隆并运行该项目。复制 main.dart 文件并替换您之前指南中的当前代码。
注意: 当 debug 参数在函数 Parse().initialize 为 true, 允许在控制台上显示Parse API调用。此配置可以帮助调试代码。建议在发布版本中禁用调试。
步骤 2 - 将模板连接到 Back4app 项目
通过导航到您的应用程序仪表板找到您的应用程序 ID 和客户端密钥凭据,地址为 Back4App 仪表板->应用设置->安全性与密钥。在 main.dart 中更新您的代码,使用您项目的 ApplicationId 和 ClientKey 的值在 Back4app 中.
- keyApplicationId = 应用程序 ID
- keyClientKey = 客户端密钥
运行项目,应用程序将如图所示加载.

点击 添加类型 来注册并查看将用于书籍注册的 类型 列表.

点击 添加出版商 注册并查看将用于书籍注册的 出版商 列表。

点击 添加书籍 注册新的 书籍,使用与 类型 和 出版商 的关系。

点击 列表出版商/书籍 查看 出版商 和 书籍 的列表。

3 - 保存书籍对象及其关系
此功能将在 Back4app 数据库中创建一个新的书籍及其关系。搜索文件中的函数 doSaveBook main.dart, 并在 Future<void> doSaveBook() 函数中插入以下代码:
1 final book = ParseObject('Book')
2 ..set('title', controllerTitle.text.trim())
3 ..set('year', int.parse(controllerYear.text.trim()))
4 //the objectId will be converted to a Pointer on the save() method
5 ..set('genre', ParseObject('Genre')..objectId = genre.objectId)
6 //you can also convert to a Pointer object before the saving using the .toPointer() method
7 ..set(
8 'publisher',
9 (ParseObject('Publisher')..objectId = publisher.objectId)
10 .toPointer());
11
12 await book.save();要构建此功能,请按照以下步骤操作:
- 1. 创建一个新的 Parse Book 类的实例,使用命令 ParseObject('Book').
- 2. 使用 set 函数来设置此对象的字段。
- 2.1.title 是一个文本属性,从文本控制器接收值。
- 2.2.genre 通过定义一个 ParseObject 来接收值,使用所选的 objectId 的 Genre. (Parse 将在保存时转换为指针)
- 2.3.publisher 通过定义一个 ParseObject 来接收值,使用所选的 objectId 的 Publisher. (请注意,我们可以为 Parse 指定我们希望保存为一个 pointer,使用 toPointer() 方法)
- 3. 在 save 函数中调用 ParseObject, 这将有效地将对象注册到您的 Back4app Dashboard 数据库中。
运行应用程序并测试新功能。
- 点击 添加书籍 按钮。
- 填写书籍信息。
该应用程序需要选择作者,但相关代码将在下一个指南中介绍。
- 点击 保存书籍 按钮

要确认新对象是否与关系一起保存在数据库中,您可以访问 Back4app Dashboard 并访问 Book 类。

如果您使用仪表板访问您的 Book 类,您可以单击对象指针值,您将被重定向到引用的对象。这看起来可能是一个无害的功能,但这使得调试和错误追踪比手动搜索快得多。
4 - 查询书籍列表及其相关对象
此功能将使用与出版商的关系在 Back4app 数据库中查询书籍。通过出版商,我们将获得书籍列表。
搜索文件中的函数 getBookList ,在 main.dart 文件中,然后在 Future<List<ParseObject>> getBookList(String publisherId) 函数中替换以下代码:
1 QueryBuilder<ParseObject> queryBook =
2 QueryBuilder<ParseObject>(ParseObject('Book'))
3 ..whereEqualTo('publisher',
4 (ParseObject('Publisher')..objectId = publisherId).toPointer())
5 ..orderByAscending('title');
6 final ParseResponse apiResponse = await queryBook.query();
7
8 if (apiResponse.success && apiResponse.results != null) {
9 return apiResponse.results;
10 } else {
11 return [];
12 }要构建此功能,请按照以下步骤操作:
- 为 ParseQuery 对象创建一个实例,针对 Book 类。插入查询条件,以搜索 Books,其中 publisher 字段等于 pointer 的 Publisher ParseObject.
- 我们按升序 name 排序结果
- 使用 query() 方法进行查询的搜索。
- 如果操作成功,将返回 Book 中的对象。
运行应用程序并测试新的查询。首先,单击 List Publisher/Book 按钮。

完成了!
在这一点上,您已经学习了如何在 Parse 中创建和查询一对多关系,Flutter。在下一个指南中,我们将向您展示如何建立多对多关系以及如何执行返回相关对象数据的查询。