SAP CRM BOL編程基礎,代碼+詳細注釋


網絡上可以找到一些使用BOL查詢、維護數據的DEMO,但幾乎都是單純的代碼,缺乏說明,難以理解。本文除了代碼外,還給出了詳細的注釋,有助於理解BOL編程中的一些基本概念。

這是一篇翻譯的文章,你可能會發現部分內容不是很明確,這時可以直接閱讀原文。

原文所在的sapcrmwebui.com是一個不錯的博客,里面有較為完整的Web UI入門教程,然而網站不是很穩定,偶爾會連接不上,建議使用Internet Archive訪問。

如果你訪問不了Internet Archive,說明你需要一點過牆的手段。

 

 本文鏈接:http://www.cnblogs.com/hhelibeb/p/5985110.html 

 原文鏈接:BASICS OF BOL PROGRAMMING

如果覺得本文有用,請記得在頁面底部點個贊~

 

2016.12.31 更多示例代碼請參考:BOL Programming(WebUI), AbapLog

搜索操作

**********************************************
*BOL 編程
*SAP CRM WEBCLIENT
*包含一些基本的操作,比如bol中的查找、創建、更新
*通過編程來介紹業務對象層的主要的類和方法
**********************************************

*需要的數據
DATA: lr_core TYPE REF TO cl_crm_bol_core.

*為了使用BOL中的服務,我們需要通過CORE類啟動模型(組件集)

lr_core = cl_crm_bol_core=>get_instance( ).


*一旦我們有了實例,之后便可以加載組件集
*這里我們將使用ONEORDER組件集

*在Web UI上面,這個將會由框架操作。這里我們正在report程序中編程,因此需要自己來操作


TRY.
    CALL METHOD lr_core->load_component_set
      EXPORTING
        iv_component_set_name = 'ONEORDER'.
  CATCH cx_crm_genil_general_error .
ENDTRY.


*組件加載了,因此我們可以使用BOL服務。讓我們搜索一個特定的合同。為了實現這個目的,我們需要獲取一個dquery服務對象的實例。
DATA: lr_query TYPE REF TO cl_crm_bol_dquery_service,
      lr_result TYPE REF TO cl_crm_bol_bo_col.

*****搜索操作***********************

"獲取動態搜索對象的實例,它會被用於搜索服務合同。
lr_query ?= cl_crm_bol_dquery_service=>get_instance( iv_query_name = 'BTQSrvCon' ).

"每一個動態搜索對象將會有他自己的結果類型對象,這里BTQSrvcon的結果對象是BTQRSrvcon
"因此在結果列表里面,所有的對象都是BTQRSrvcon的類型。

"我們得到了實例,之后我們需要設置選擇條件值,取得所有描述是‘testing’的合同。
"你可以多次使用這個方法,來添加不同的選擇參數。

 lr_query->add_selection_param( iv_attr_name = 'DESCRIPTION'
                                                iv_sign      = 'I'
                                                iv_option    = 'EQ'
                                                iv_low       = 'testing' ).
"獲取以集合(collection)形式存在的的、匹配選擇條件值的合同列表

"集合不過是一個保存記錄的容器,我們可以把它和內表相類比

"它保存了記錄.


lr_result ?= lr_query->get_query_result( ).


"讓我們輸出集合中所有的合同ID和描述

"cl_crm_bol_entity用於表現業務對象層中的記錄 

DATA: lr_entity TYPE REF TO cl_crm_bol_entity,
      lv_objectid TYPE string,
      lv_descr TYPE char40.



"讀取集合中的第一條記錄

lr_entity ?= lr_result->if_bol_bo_col~get_first( ).


"下面的while循環機制用於訪問集合中的每一條數據

WHILE lr_entity IS BOUND.


  "讀取合同ID.

  "get property as string方法將返回字符串格式的屬性,因此我們將lv_object聲明為字符串。 

  lr_entity->get_property_as_string( EXPORTING iv_attr_name = 'OBJECT_ID' RECEIVING rv_result    = lv_objectid  ).


  "get property as value將返回值本身的類型,因此我們使用數據元素來聲明DESCRIPTION

  lr_entity->get_property_as_value( EXPORTING iv_attr_name = 'DESCRIPTION' IMPORTING ev_result = lv_descr ).


  WRITE : lv_objectid, lv_descr.

  WRITE /:.


  "讀取集合中的下一條數據.

  lr_entity ?= lr_result->if_bol_bo_col~get_next( ).

ENDWHILE.

更新操作

**************更新操作***************************

  
"讓我們修改服務合同的描述

"從結果列表獲取現在的entity  

"每個集擁有一個總是指向我們當前訪問的記錄的指針,通常我們在BOL的語言中稱之為焦點
"因此get current返回擁有焦點的對象,所以就是我們在上面的循環中曾經最后訪問的對象 將會被下面的語句取得 


lr_entity ?= lr_result->if_bol_bo_col~get_current( ).


IF lr_entity IS BOUND.  "我們從不對initial狀態的對象引用進行操作,這個檢查在bol中是十分重要的



  "我們能直接在這個lr_entity中使用字符串設置屬性嗎?

  "答案是不能,這是一個動態查詢對象,通常這些類型的對象的所有的屬性都是只讀的

  "DESCRIPTION是BTAdminH對象的屬性,我們需要使用relations獲取它我們需要從MODEL中觀察我們抵達目標對象所需要的關系是什么.事務代碼GENIL_MODEL_BROWSER中可以瀏覽這些bol對象的關系

  "在我們的場景中,我們有lr_entity變量中的BTQRSrvcon作為源.這個對象有關系'聚合BTADVSSrvCon子級基數1'

  "將會給出對象BTOrder.


  "同樣BTOrder有關系'組成 BTOrderHeader子級基數1', 通過它將取得對象BTAdminH,這個對象有一個屬性‘DESCRIPTION’

  "當尋找關系時,觀察關系的子級基數。如果子級基數是0...1,這個關系將會總是能獲取到單一的entity。如果是0...n的話,這個關系將可以獲取多個entity.


  " 如果子級基數是0...1,使用 GET RELATED ENTITY.

  " 如果子級基數是0...n,使用 GET_RELATED_ENTITIES.


  DATA: lr_order TYPE REF TO cl_crm_bol_entity.


  "首先讀取BTORDER

  "參數iv_mode將攜帶一個值'b',代表繞過緩沖區.

  "這意味着,框架將會忽視bol緩沖區中存在的值,通過觸發相關的api從數據庫讀取目標entity的值。

  "這將降低性能,所以只應在需要的情況使用它,比如你在讀取一個特別的、第一次讀取的enetity。

  TRY.

      CALL METHOD lr_entity->get_related_entity
        EXPORTING
          iv_relation_name = 'BTADVSSrvCon'
          iv_mode          = cl_crm_bol_entity=>bypassing_buffer
        RECEIVING
          rv_result        = lr_order.

    CATCH cx_crm_genil_model_error .

  ENDTRY.



  "我們取得了訂單,接下來讀取BTAdminH.


  DATA: lr_header TYPE REF TO cl_crm_bol_entity.


  IF lr_order IS BOUND.

    TRY.

        CALL METHOD lr_order->get_related_entity
          EXPORTING
            iv_relation_name = 'BTOrderHeader'
            iv_mode          = cl_crm_bol_entity=>bypassing_buffer
          RECEIVING
            rv_result        = lr_header.

      CATCH cx_crm_genil_model_error .

    ENDTRY.


  ENDIF.


  "獲取到了BTadminH,之后修改它的DESCRIPTION屬性.

  IF lr_header IS BOUND.


    "在修改任何BOL的對象前,我們需要鎖定它

    "這由lock方法完成

    IF  lr_header->lock( ) = abap_true.  "如果我們獲取了鎖, 接下來繼續

      "我們使用set_* 方法來修改BOL對象的屬性.

      lr_header->set_property_as_string( EXPORTING iv_attr_name = 'DESCRIPTION'  

      iv_value = 'changed'  ).

    ENDIF.


    "一旦修改結束,我們需要通知框架這個改變已經發生

    "使用core類實現它

    lr_core->modify( ).


    "接着從entity獲取transaction,並且檢查它是否可以保存


    DATA: lr_transaction TYPE REF TO if_bol_transaction_context.


    lr_transaction ?= lr_header->get_transaction( ).


    IF lr_transaction IS BOUND.


      IF lr_transaction->check_save_possible( ) EQ abap_true.


        "如果可以保存,接下來保存transaction並且commit修改。

        IF lr_transaction->save( ) EQ abap_true.

          lr_transaction->commit( ).

        ENDIF.


        "我們修改了對象的描述,再次讀取它,以獲取新的值。

        lr_header->get_property_as_value( EXPORTING iv_attr_name = 'DESCRIPTION'  
                                          IMPORTING ev_resul   t = lv_descr ).

      ENDIF.


    ENDIF.


  ENDIF.



ENDIF.

創建操作

***************創建操作*****************************



*讓我們創建一個服務合同,並且填充一些它的屬性
*"第一步,我們需要創建根entity


DATA:  lr_factory       TYPE REF TO cl_crm_bol_entity_factory,

       lr_order_new     TYPE REF TO cl_crm_bol_entity,

       ls_params        TYPE crmt_name_value_pair,

       lt_params        TYPE crmt_name_value_pair_tab.



ls_params-name  = 'PROCESS_TYPE'.

ls_params-value = 'ZSZ'.

APPEND ls_params TO lt_params.


"使用工廠類以創建根entity。 我們發送根對象給core類的方法get entity factory去獲取需要的工廠類

"接下來我們通過發送需要的參數來使用工廠類的CREATE方法


"這里我們創建合同,將PROCESS_TYPE作為參數輸入  

lr_factory   = lr_core->get_entity_factory( 'BTOrder' ).    "#EC NOTEXT

lr_order_new = lr_factory->create( lt_params ).



IF lr_order_new IS BOUND.


  "BTOrder只含有GUID,我們需要獲取BTAdminH entity去填充某些它的屬性。

  TRY.

      CALL METHOD lr_order_new->get_related_entity
        EXPORTING
          iv_relation_name = 'BTOrderHeader'
          iv_mode          = cl_crm_bol_entity=>bypassing_buffer
        RECEIVING
          rv_result        = lr_header.

    CATCH cx_crm_genil_model_error .

  ENDTRY.



  "使用setter方法填充屬性

  IF lr_header IS BOUND.

    "使用set_*方法修改BOL對象的屬性.

    lr_header->set_property_as_string( EXPORTING iv_attr_name = 'DESCRIPTION'  

    iv_value = 'New Contract'  ).



    lr_core->modify( ).

    lr_transaction ?= lr_header->get_transaction( ).


    IF lr_transaction IS BOUND.


      IF lr_transaction->check_save_possible( ) EQ abap_true.


        "如果我們可以保存,保存事務並且commit修改

        IF lr_transaction->save( ) EQ abap_true.

          lr_transaction->commit( ).

        ENDIF.

        "修改對象描述,再次讀取以獲取新的值

        lr_header->get_property_as_value( EXPORTING iv_attr_name = 'DESCRIPTION'  
                                          IMPORTING ev_result    = lv_descr ).


      ENDIF.


    ENDIF.


  ENDIF.


ENDIF.
 

 

補充:創建條目可以使用cl_crm_bol_entity的create_related_entity方法

 

參考閱讀Business Object Layer (BOL) Application Programming Guide

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM