OData Service作为一个 Web API 服务,对外暴露实体数据,核心能力 CRUD 操作,本文只要讲解Query的功能。
一、什么是 OData Query?
在 OData 协议中,Query 泛指所有通过 HTTP GET 请求从服务端获取数据的操作。
| 操作 | HTTP 示例 | 返回结果 |
|---|---|---|
| GET_ENTITY | /ZSOHEADERSet('468') |
单个实体(一条数据) |
| GET_ENTITYSET | /ZSOHEADERSet |
实体集合(多条数据,可带过滤/排序/分页) |
ODATA Query案例及测试如下:

双击后配置

激活

激活成功后,可进行测试,测试方法如下:
进入到SAP Gateway Client

SAP Gateway Client测试

修改URL点击执行

上面是批量查询,下面是单条查询

二、Query 的核心参数(让数据可控)
OData 定义了一套 URL 查询参数,让客户端能在请求时就告诉后端"我需要什么样的数据"。这些参数在 GET_ENTITYSET 中尤其重要。
| 参数 | 示例 | 作用 |
|---|---|---|
$filter |
$filter=Price gt 100 |
筛选满足条件的记录 |
$orderby |
$orderby=Title asc |
排序 |
$top |
$top=10 |
最多返回前 N 条 |
$skip |
$skip=20 |
跳过前 N 条(用于分页) |
$select |
$select=Title,Author |
只返回指定字段 |
$expand |
$expand=Publisher |
同时返回关联实体 |
$inlinecount |
$inlinecount=allpages |
返回总记录数(分页常用) |
💡 一个真实请求长这样:/sap/opu/odata/SAP/ZXKJ_TEST_SRV/ZSOHEADERSet?filter=Vkorg eq '1710' and Erdat ge datetime'2018-01-01T00:00:00'\& orderby=Erdat desc, Erzet desc& top=50\& skip=0 ;含义:查询销售组织 1710 且 2018 年之后的订单,按创建日期时间倒序,取前 50 条。
$filter参数以日期为例:/sap/opu/odata/SAP/ZXKJ_TEST_SRV/ZSOHEADERSet?$filter=Erdat eq datetime'2024-05-15T00:00:00' 
练习参考
1. 基本等值过滤
| 需求 | $filter 表达式 |
|---|---|
销售订单等于 469 |
$filter=Vbeln eq '469' |
创建人员等于 BPINST |
$filter=Ernam eq 'BPINST' |
销售组织等于 1710 |
$filter=Vkorg eq '1710' |
分销渠道等于 10 |
$filter=Vtweg eq '10' |
注意:Vbeln、Ernam、Vkorg、Vtweg 通常视为字符串或数字。若字段是字符串,值需加单引号;若是数字,可直接写数字(如
Vkorg eq 1710),具体取决于元数据定义。
2. 日期字段 Erdat 过滤
Erdat 在响应中格式为 2018-04-05T00:00:00,属于 Edm.DateTime 类型。
| 需求 | $filter 表达式 |
|---|---|
| 创建日期等于 2018-04-05 | $filter=Erdat eq datetime'2018-04-05T00:00:00' |
| 创建日期在 2018-01-01 之后 | $filter=Erdat gt datetime'2018-01-01T00:00:00' |
| 创建日期在 2018-03-01 到 2018-04-30 之间 | $filter=Erdat ge datetime'2018-03-01T00:00:00' and Erdat le datetime'2018-04-30T00:00:00' |
| 只比较日期部分(忽略时间) | $filter=date(Erdat) eq 2018-04-05 |
| 年份为 2018 | $filter=year(Erdat) eq 2018 |
| 月份为 4 月 | $filter=month(Erdat) eq 4 |
| 日为 5 号 | $filter=day(Erdat) eq 5 |
3. 时间字段 Erzet 过滤
Erzet 响应值为 PT19H41M38S,这是 XML duration 格式,表示 19小时41分38秒。在 OData 中通常映射为 Edm.Time 或 Edm.Duration。
常用写法(取决于服务实现):
| 需求 | $filter 表达式 |
|---|---|
| 创建时间等于 19:41:38 | $filter=Erzet eq time'PT19H41M38S' 或 $filter=Erzet eq 19:41:38 |
| 创建时间早于 20:00:00 | $filter=Erzet lt time'PT20H00M00S' |
| 创建时间在 18:00 ~ 20:00 之间 | $filter=Erzet ge time'PT18H00M00S' and Erzet le time'PT20H00M00S' |
| 提取小时部分(需 OData 4.0+) | $filter=hour(Erzet) eq 19 |
注意:SAP Gateway (OData V2) 对 duration 的过滤支持可能有限,实际使用前建议用
/IWFND/GW_CLIENT验证。
4. 组合条件(与 / 或 / 括号)
| 需求 | $filter 表达式 |
|---|---|
| 销售组织=1710 并且 分销渠道=10 | $filter=Vkorg eq '1710' and Vtweg eq '10' |
| 销售订单=469 或 创建人员=BPINST | $filter=Vbeln eq '469' or Ernam eq 'BPINST' |
| (销售组织=1710 且 分销渠道=10) 或 (创建日期在2018-04-01之后) | $filter=(Vkorg eq '1710' and Vtweg eq '10') or (Erdat gt datetime'2018-04-01T00:00:00') |
| 销售订单不是 469 | $filter=not (Vbeln eq '469') 或 $filter=Vbeln ne '469' |
5. 注意事项
-
字段名大小写敏感 :必须与 WSDL/元数据中完全一致(如
Vbeln不是VBELN)。 -
日期时间字面量 :使用
datetime'YYYY-MM-DDThh:mm:ss'或date()函数。 -
时间字面量 :SAP OData V2 常见格式为
time'PT...'或直接用'HH:MM:SS',建议用 Gateway Client 测试。 -
空值判断 :
Ernam eq null或Ernam ne null。
三、为什么要用到 Query?
| 业务场景 | 需要 Query 的原因 |
|---|---|
| 前端 UI5 列表展示 | 需要 GET_ENTITYSET 返回多行数据 |
| 详情页显示一条记录 | 需要 GET_ENTITY 根据主键获取单条 |
| 下拉框数据源 | 需要 Query 提供候选值集合 |
| 报表导出 | 需要 Query 批量取数 |
| 搜索功能 | 需要 Query 支持 $filter 等参数 |
核心:没有 Query,OData 服务就是一个"只写不读"的黑洞,无法向客户端提供任何数据。读取是 API 最基础、最高频的操作。
四、为什么 Query 在 Service Implementation "下面"?
可以看到Query是OData Service树形图Service Implementation下的组件

在 SAP OData 服务的上下文中,Service Implementation 是将 OData 请求转化为实际数据处理的"大脑",Service Implementation 指的是 DPC_EXT 类(数据提供者扩展类)中为服务操作编写的具体 ABAP 代码。它的核心作用可以概括为 "连接 OData 协议请求与真实业务逻辑,实现服务的可定制化"。
具体体现在以下几个方面:
1. 实现复杂业务逻辑
当自动生成的读取(如 CDS 发布的服务)不满足需求时,Service Implementation 允许开发者重写 GET_ENTITY / GET_ENTITYSET 方法,加入:
-
动态权限过滤(根据用户显示不同数据)
-
数据转换(单位、货币换算)
-
调用外部数据源(BAPI、RFC、Web Service)
2. 支持非 CDS 数据源
如果数据来自传统数据库表、视图簇、甚至非 SAP 系统,Service Implementation 可以让开发者完全控制数据读取逻辑,而不依赖 CDS 的自动发布。
3. 实现写操作(CUD)
CDS View 本身是只读的,因此 CREATE、UPDATE、DELETE 操作必须通过 Service Implementation 手动实现。在 CREATE_ENTITY、UPDATE_ENTITY、DELETE_ENTITY 方法中写入数据库或调用业务模块。
4. 提供校验与错误处理
可以在 Service Implementation 中加入业务校验(如字段必填、数据有效性),并抛出标准的 OData 异常,而不是让底层错误直接暴露给客户端
5. 精细控制协议行为
-
手动解析
$filter、$orderby、$top、$skip等参数并转换为数据库查询 -
设置 ETag 以支持乐观锁并发控制
-
返回自定义的 HTTP 状态码(如 204 No Content)