網絡上可以找到一些使用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