构建 OData 服务 [6]:实现所有 URI

2021-11-07 23:55发布


          点击此处--->   EasySAP.com 群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)

在这篇文章中,您将学习如何实现实体的所有操作。

这是构建 OData 服务系列的一篇文章。可以通过以下链接访问较早的帖子。

  1. 构建 OData 服务 [1]:OData 概述

  2. 构建 OData 服务 [2]:了解 OData 服务

  3. 构建 OData 服务 [3]:创建 OData 服务

  4. 构建 OData 服务 [4]:注册和测试 OData 服务

  5. 构建 OData 服务 [5]:使用 OData URI

在上一篇文章中,我们了解了 URI 的工作原理。现在让我们在 SAP ABAP 中实现 URI/服务操作。

在 SEGW 事务中生成 OData 项目时,会创建数据提供者基类和数据提供者扩展类。我们将使用扩展类来实现所有操作。

这是扩展类——通常称为 DPC_EXT 类。

image.png


每个操作在数据提供者类中都有一个专用方法。方法名称表明应该使用它们来实现哪个操作。

例如,CARRIERSET_CREATE_ENTITY 用于创建载体。每个操作的代码示例如下。

阅读 - 获取实体 

IT_KEY_TAB 包含键名和键值。

DATA: lv_carrid TYPE scarr-carrid.

TRY.
    DATA(ls_key_tab) = it_key_tab[ name = 'CarrierID' ].
    lv_carrid        = ls_key_tab-value.
      
    SELECT SINGLE * FROM scarr INTO CORRESPONDING FIELDS OF er_entity
      WHERE carrid = lv_carrid.
   CATCH cx_sy_itab_line_not_found.     
   "Error handling
ENDTRY.

查询:数据的选择和排序——GET ENTITYSET

在查询操作中,可以根据业务逻辑默认应用一些过滤器。

数据按照导入对象 io_tech_request_context 中的信息进行排序。

*-- Select the dataSELECT * FROM scarr
  INTO TABLE et_entityset
  WHERE carrid IN lr_carrid.   "lr_carrid can be built as per business logic*-- Implement Sorting  DATA: lt_otab TYPE abap_sortorder_tab,
      ls_otab TYPE abap_sortorder,
      lt_tech_order TYPE /iwbep/t_mgw_tech_order.

lt_tech_order = io_tech_request_context->get_orderby( ).

IF lt_tech_order IS NOT INITIAL.
  LOOP AT lt_tech_order INTO DATA(ls_order).
    ls_otab-name = ls_order-property.
    TRANSLATE ls_otab-name TO UPPER CASE.
    IF ls_order-order = 'desc'.
      ls_otab-descending = abap_true.
    ELSE.
      ls_otab-descending = abap_false.
    ENDIF.
    APPEND ls_otab TO lt_otab.
  ENDLOOP.

  SORT et_entityset BY (lt_otab).
ENDIF.

查询:跳过和顶部 - GET ENTITYSET

Skip 和 Top 用于处理分页。

跳过x和顶部y意味着应该选择索引x+1中的y个记录由于这应该考虑排序标准,因此通常在应用排序后应用。

*-- This is additional code after the data selection and sorting

*-- Handle paging – provide number of records
IF io_tech_request_context->has_inlinecount( ) = abap_true.
  es_response_context-inlinecount = lines( et_entityset ).
ENDIF.
*-- Handle paging – keep only required records 
IF is_paging IS NOT INITIAL.
  lv_to   = is_paging-skip.
  lv_from = is_paging-skip + is_paging-top + 1.
  IF lv_from LT lines( et_entityset ).
    DELETE et_entityset FROM lv_from.
  ENDIF.
  IF lv_to GT 0.
    DELETE et_entityset TO lv_to.
  ENDIF.
ENDIF.

查询:关联 – GET ENTITYSET

任何实体集查询操作都可以有两个来源。可以直接调用,也可以通过关联调用。所以两个调用源都应该被处理。

当查询被关联调用时,关联引用约束字段信息会随之传递。否则可以通过过滤器。

导入参数 iv_source_name 告诉它从哪里被调用。

DATA ls_key TYPE /iwbep/s_mgw_name_value_pair.

CASE iv_source_name.
    "URI - /sap/opu/odata/sap/ZJP_DEMO_SRV/CarrierSet('DL')/ToFlightSchedule
  WHEN 'Carrier'.  "Association 
        READ TABLE it_key_tab INTO ls_key WITH KEY name = 'CarrierID'.
    IF sy-subrc EQ 0.
      SELECT * FROM spfli INTO CORRESPONDING FIELDS OF TABLE et_entityset
        WHERE carrid = ls_key-value.
    ENDIF.
    "URI - /sap/opu/odata/sap/ZJP_DEMO_SRV/FlightScheduleSet?$filter=Carrid eq 'DL'
  WHEN 'FlightSchedule'. "Called directly - check filters
       
    "Get the data using filters
    READ TABLE it_filter_select_options INTO ls_filter WITH KEY property = 'Carrid'.
    IF sy-subrc EQ 0.      "For demonstration, it is assumed that filter will be used only for one field 
      READ TABLE ls_filter-select_options INTO ls_selopt INDEX 1.
      IF sy-subrc EQ 0.
        SELECT carrid connid countryfr cityfrom countryto cityto
          FROM spfli INTO CORRESPONDING FIELDS OF TABLE et_entityset
          WHERE carrid = ls_selopt-low.
      ENDIF.
    ENDIF.
    
    WHEN OTHERS.
      RETURN.
  ENDCASE.

函数导入——实现方法:/IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION 

所有函数导入在数据提供者类中触发相同的方法。该方法具有导入参数 iv_action_name,该参数将函数导入名称作为值。

此示例描述了如果创建函数导入以获取承运人的航班数,如何实现代码。

在这里,重要的是要注意函数导入始终返回单个实体或实体集。由于它可以传回实体和实体集,因此使用特殊方法 copy_data_to_ref 将结果数据复制到 er_data ,即导出的数据引用。

CASE iv_action_name.
    WHEN 'GetCarrierFlights'.
      DATA: ls_parameter TYPE /iwbep/s_mgw_name_value_pair,
            lv_carrid    TYPE scarr-carrid,
            lv_count     TYPE i,
            ls_data      TYPE zcl_zjp_demo_mpc=>ts_scarr.

      READ TABLE it_parameter INTO ls_parameter WITH KEY name = 'CarrierID'.
      IF sy-subrc EQ 0.
        lv_carrid = ls_parameter-value.
        ls_data-carrid = lv_carrid.
        SELECT COUNT(*) FROM sflight
          INTO lv_count
          WHERE carrid = lv_carrid.
        IF sy-subrc EQ 0.
          ls_data-carrname = lv_count.
        ELSE.
          ls_data-carrname = '0'.
        ENDIF.
      ENDIF.* Call method copy_data_to_ref and export entity data      
      copy_data_to_ref( EXPORTING is_data = ls_data
                        CHANGING  cr_data = er_data ).

  ENDCASE.

其余的 CRUD 操作可以如下实现。为了演示,使用自定义表 ZJP_SFLIGHT。

创建 – 创建实体

要创建的数据从io_data_provider获取

DATA: ls_sflight TYPE sflight.CALL METHOD io_data_provider->read_entry_data
  IMPORTING es_data= er_entity.MOVE-CORRESPONDING er_entity TO ls_sflight.
ls_sflight-mandt = sy-mandt.

INSERT zjp_sflight FROM ls_sflight.
IF sy-subrc NE 0.
  RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception.
ENDIF.

更新 – 更新实体

要更新的数据从对象io_data_provider 中获取


DATA: ls_sflight TYPE sflight.CALL METHOD io_data_provider->read_entry_data
  IMPORTING es_data= er_entity.  
MOVE-CORRESPONDING er_entity TO ls_sflight.
ls_sflight-mandt = sy-mandt.

MODIFY zjp_sflight FROM ls_sflight.
IF sy-subrc NE 0.
  RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception.
ENDIF.

删除 – 删除实体

对于删除,密钥在 it_key_tab 中发送。一次删除一个条目。

DATA: ls_sflight TYPE sflight.
LOOP AT it_key_tab INTO DATA(ls_key_tab).    
  CASE ls_key_tab-name.
    WHEN 'Carrid'.
      ls_sflight-carrid = ls_key_tab-value.
    WHEN 'Connid'.
      ls_sflight-connid = ls_key_tab-value.
    WHEN 'Fldate'.
      ls_sflight-fldate = ls_key_tab-value.
  ENDCASE.
ENDLOOP.
  DELETE FROM zjp_sflight WHERE carrid = ls_sflight-carrid
                        AND   connid = ls_sflight-connid
                        AND   fldate = ls_sflight-fldate.

这些代码示例仅在实体名称和属性完全匹配时才起作用,因此在创建服务时,请使用这些代码示例作为参考并实现该服务。

赞赏支持