通过 OData 模型读取数据

学习目标

  • 通过 SAPUI5 OData 模型从 OData 服务读取数据

OData 模型

OData 模型支持将控件绑定到来自 OData 服务的数据。

观看视频以了解 SAPUI5 OData 模型。

视频:本节含 SAP 官方视频(视频 ID 1_ivvypca2),需在 learning.sap.com 在线观看。

本课程涉及的 OData V4 模型支持以下功能:

  • 读取访问

  • 删除和创建实体

  • 通过双向绑定更新 OData 实体(实体集和包含实体中的实体)的属性

  • 执行操作(函数和动作)

  • 将数据请求分组为批量请求

  • 服务器端排序和筛选

模型实例化

可以使用 sap.ui.model.odata.v4.ODataModel 类的构造函数在 JavaScript 中创建 OData V4 模型实例。必须向构造函数传递一个带参数的对象。该对象必须至少包含参数 serviceUrlsynchronizationMode

serviceUrl 的值是要从中请求数据的服务的根 URL。根据 OData V4 规范,URL 的路径部分必须以正斜杠结尾。

参数 synchronizationMode 控制在某个绑定中数据发生变化时,引用同一数据的不同绑定之间的同步。此参数必须设置为 'None',表示绑定完全不进行同步;所有其他值均不受支持,并会导致错误。

注意

更多信息,请参阅 Demo Kit 中 API reference 里 sap.ui.model.odata.v4.ODataModel 类构造函数的文档。

示例 JSON 代码,突出显示 mainService 属性。

此外,也可以通过 manifest.json 应用程序描述符以声明方式实例化 OData V4(以及 V2)模型。该示例展示了应用程序描述符中与此相关的部分。

sap.app 命名空间中,dataSources 属性用于指定组件中使用的 OData 服务。数据源的键使用 mainService,该键的名称可以任意指定。mainService 数据源包含重要信息——可以通过哪个 URL 调用该服务,以及它是一个 OData V4 服务。

然后,sap.ui5 命名空间中的 models 属性用于指定一个 OData 模型,该模型使用来自 mainService 数据源的 OData V4 服务。此 OData V4 模型会自动实例化并为组件设置。该模型没有使用名称,因为指定了空字符串("")作为键。

OData 模型定义中的 settings 对象被传递给 sap.ui.model.odata.v4.ODataModel 类的构造函数。它包含前面介绍的 synchronizationMode 参数。

此外,还使用了以下参数:

  • operationMode 此参数定义用于筛选和排序的操作模式。"Server" 表示这些操作通过附加相应的 URL 参数($filter$orderby)在服务器上执行。筛选或排序的每次更改都会触发对服务器的新请求。

  • earlyRequests 此布尔参数决定是否尽早请求服务元数据文档($metadata)、其他注释文件和安全令牌。

  • autoExpandSelect 此布尔参数决定 OData 模型的绑定是否自动生成 \(select 和 \)expand 系统查询选项。如果设置为 true,SAPUI5 只会选择 UI 所需的数据,从而获得最小的响应大小和更好的性能。

注意

更多信息,请参阅 Demo Kit 中 API reference 里 sap.ui.model.odata.v4.ODataModel 类构造函数的文档。

如果在 SAP Business Application Studio 中运行创建新 SAPUI5 项目的向导时为应用程序选择了 OData 服务,则会自动向应用程序描述符中添加相应的数据源以及引用它的 OData 模型。

绑定

绑定类型

绑定将 SAPUI5 视图元素连接到模型数据,使模型中的更改能够反映到视图元素中,反之亦然。

OData V4 模型支持的绑定:List(集合)、Context(单个实体/属性)和 Property(原始值或复杂类型)。

在 OData 模型中,每个资源路径(相对于服务根 URL,不带查询选项)在添加前导斜杠后都是有效的数据绑定路径。例如,可以使用 /UX_Customer(00505604-4e85-1edd-818f-21e64b9cd2cf) 访问键为 00505604-4e85-1edd-818f-21e64b9cd2cf 的实体实例。

绝对绑定和相对绑定

如果绑定的路径以正斜杠 "/" 开头,则称为绝对绑定;否则称为相对绑定。相对绑定是初始的,这意味着只要它们没有上下文就没有数据。它们从列表绑定或上下文绑定获取上下文:在列表绑定中,上下文表示实体集合中某个索引处的实体;在上下文绑定中,上下文表示该上下文绑定的那一个实体。

创建上下文的绑定称为相对绑定的父绑定;相对绑定是其父绑定的子绑定。

如果绑定的路径以正斜杠 "/" 开头,则称为绝对绑定——否则称为相对绑定。只要相对绑定没有上下文,它们就没有数据。

"绝对绑定和相对绑定"图展示了一个绝对列表绑定:表格的 items 聚合使用路径 /UX_Customer 绑定到 UX_Customer 实体集。各列定义了路径为 CustomerNameStreetPostCodeCityCountryEmail 的相对绑定,并以该绝对列表绑定作为父绑定。

OData 请求

生成的请求

一旦绑定的控件或具有相对绑定的子控件请求数据,绝对绑定就会创建数据服务请求以读取数据。读取 URL 路径是模型的服务 URL 与绑定的路径拼接而成。

示例 OData 请求,如下文所述。

在所示示例中,生成了以下 OData 请求以检索表格的数据:

在实例化模型时指定的服务 URL(/sap/ux_ui_customer_o4/srvd/sap/ux_ui_customer/0001/,见上文)后面,附加了用于 items 聚合的绑定路径(/UX_Customer)。这样就得到了通过该服务请求 UX_Customer 实体集的 URL。

查询选项也源自表格的绑定,并附加到生成的 URL 中:

由于该表格启用了 growing 功能,在初始请求期间只从 OData 服务请求前 5 个实体。这是通过 $skip=0&$top=5 实现的。如果用户请求更多数据,则会生成后续请求 $skip=5&$top=5 以检索接下来的 5 个实体,依此类推。

在表格绑定中定义的排序顺序也通过 $orderby=City,CustomerName 应用到 OData 请求。

注意

要使用服务器端排序和筛选,必须将 OData 模型的操作模式设置为 Server。这可以通过应用程序描述符中的 operationMode 模型参数来完成(见上文)。如果没有此操作模式,在表格绑定中定义的排序将导致错误。

最后,通过 $select 只请求那些也在表格中显示的属性。

注意

为了使 OData V4 模型能够根据为控件属性指定的绑定路径,自动为服务请求计算\(select 以及\)expand 查询选项,必须在构造模型时设置 autoExpandSelect 标志(见上文)。如果没有此标志,在示例中将会请求客户的所有属性。

即使 CustomerGuid 属性未绑定到 UI,它也会被选中。它之所以被自动选中,是因为它是客户的关键属性。

筛选

OData V4 模型还支持对列表进行服务器端筛选。

示例筛选请求,如下文所述。

在该示例中,用户可以通过搜索字段筛选包含客户数据的表格内容。数据的筛选在所示的事件处理程序中实现。在其中创建一个 sap.ui.model.Filter 对象,用于针对 CustomerName 属性的内容筛选表格内容。只有客户名称包含用户输入值(sQuery)的那些客户才会显示。在示例中,输入了 SAP 作为筛选值。

要设置筛选对象,需要检索表格 items 聚合的列表绑定对象。筛选对象通过 filter 方法传递给该对象。这反过来会生成一个 OData 请求,通过 $filter=contains(CustomerName,'SAP') 应用筛选。

注意

请记住,对于服务器端排序和筛选,必须将 OData 模型的操作模式设置为 Server。这可以通过应用程序描述符中的 operationMode 模型参数来完成(见上文)。如果没有此操作模式,在事件处理程序方法中实现的筛选将导致错误。

上下文绑定

示例上下文绑定代码,如下文所述。

该示例实现了一个包含两个表格的主从场景。客户显示在两个表格中上面的那个表格里。此表格通过其 items 聚合绑定到 UX_Customer 实体集。这里使用的绝对绑定路径确保生成相应的 OData 请求,以便用数据填充该表格(见上文)。

在下面的表格中,将显示所选客户的现有预订。为此,该表格绑定到客户的 _Bookings 导航属性。不过,这里使用的是相对绑定路径,因此只要此绑定没有上下文,就不会生成用于检索数据的 OData 请求。

一旦在客户表格中选择了某个客户,预订表格的绑定上下文就会通过关联的 onCustomerChange 事件处理程序设置为当前选定的客户。这使绑定中使用的相对路径得以补全为绝对路径,并生成相应的 OData 请求以填充预订表格。

向应用程序添加 OData 模型

业务场景

当前显示在客户表格和预订表格中的数据来自你在上一个练习中创建的 JSON 模型。在本练习中,你将删除此 JSON 模型,并改用为这两个表格提供数据的 OData 模型。

注意

为简单起见,你将不会调用后端系统中的 OData 服务来测试本练习。而是使用所谓的 mock 服务器来模拟对远程系统的访问。模拟访问期间显示的数据已包含在项目中。可以在 *UX_Customer.json**UX_Booking.json* 文件中找到这些数据,它们位于 *webapp/localService/data* 文件夹中。

要使用 mock 服务器,不再像之前那样通过 start-noflp 脚本启动应用程序预览,而是通过 start-mock 脚本启动。这适用于所有尚未完成的练习,并已相应地包含在练习说明中。

*Template:*Git Repository: https://github.com/SAP-samples/sapui5-development-learning-journey.git, Branch: **sol/19_resource_model***Model solution:*Git Repository: https://github.com/SAP-samples/sapui5-development-learning-journey.git, Branch: sol/20_OData_model_(read)

任务 1:向组件添加自动实例化的 OData 模型

步骤

  1. 在编辑器中打开 *webapp* 文件夹中的 *manifest.json* 应用程序描述符。

  2. 在应用程序描述符中,查找 sap.app 命名空间中包含的以下条目:

"dataSources": {
"mainService": {
"uri": "/sap/opu/odata4/sap/ux_ui_customer_o4/srvd/sap/ux_ui_customer/0001/",
"type": "OData",
"settings": {
"annotations": [],
"localUri": "localService/metadata.xml",
"odataVersion": "4.0"
}
}
}

注意

该条目指定组件使用带有声明 URL 的 OData v4 服务。此数据源的键名为 mainService,下面需要通过 OData 模型使用此 OData 服务时要用到它。

  1. 现在查找 sap.ui5 命名空间中 models 属性内包含的以下条目:

"ODataModel": {
"dataSource": "<...>",
"settings": {
"synchronizationMode": "None",
"operationMode": "Server",
"autoExpandSelect": true,
"earlyRequests": true
}
}

注意

此声明定义了一个模型,它会自动实例化并以名称 ODataModel 为组件设置。

  1. 将上述模型的名称从 ODataModel 改为空字符串(""),以将该模型设置为组件的未命名默认模型。

结果

模型的声明现在应如下所示: JSON 文件,突出显示空字符串。 5. 对于 dataSource 属性,将 "<...>" 替换为 "mainService",以引用上面为 mainService 键指定的 OData 服务作为该模型的数据源。

结果

OData 模型的声明现在应如下所示: JSON 文件,突出显示 mainService 属性。 6. 之前用作数据提供者的 JSON 模型现在不再需要。因此,请从 models 属性中删除以下条目:

"": {
"type": "sap.ui.model.json.JSONModel",
"uri": "model/data.json"
}

结果

models 属性现在应如下所示:

生成的 JSON 文件,突出显示 models 属性。

任务 2:将客户表格绑定到来自 OData 服务的数据

步骤

  1. 在编辑器中打开 *webapp/view* 文件夹中的 *Overview.view.xml* 文件。

  2. 按如下方式更改客户表格 items 聚合的数据绑定:将 path 属性的值 /Customers 替换为值 /UX_Customer

注意

来自 OData 服务的数据结构与之前使用的 JSON 模型的数据结构非常相似。唯一相关的区别是:JSON 模型中的客户存储在名为 Customers 的数组中,而所用 OData 服务中对应的实体集名为 UX_Customer。除此之外,这两个模型在使用的属性名称方面以及在 UI 层面客户与预订之间的关系方面都是一致的。因此,无需进一步调整即可通过 OData 服务为这两个表格填充数据。

OData 服务所基于的数据模型可以在服务元数据文档中进行探究。该文档包含在项目中,可在 *webapp/localService* 文件夹的 *metadata.xml* 文件中找到。

结果

客户表格的数据绑定现在应如下所示: 生成的客户表格,突出显示 UX/Customer 项。 3. 通过从 SAP Business Application Studio 启动应用程序来进行测试运行。

小心

如上所述,测试时不会调用后端系统中的 OData 服务。而是通过 mock 服务器模拟对远程系统的访问。为此,请使用名为 start-mock 的 npm 脚本启动应用程序,而不是之前使用的 start-noflp 脚本。

(如果你有权访问后端系统,可以使用 start-noflp 脚本。) 确保客户表格已填充数据,并且当选择某个客户时,关联的预订会显示在预订表格中。 注意

用于模拟 OData 调用的数据与之前使用的 JSON 模型的数据基本相同。后端系统提供的数据可能有所不同。

  1. 右键单击 sapui5-development-learning-journey 项目中的任意子文件夹,然后从出现的上下文菜单中选择 Preview Application

  2. 在出现的对话框中选择名为 start-mock 的 npm 脚本。

  3. 在打开的应用程序中,检查组件是否按预期工作。