zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    程序员的双11:3723亿,你贡献了几分力?
    程序员国企1周上班5小时?国企VS私企,应该如何选择?
    C++没有"垃圾回收"功能?智能指针,实现C++的内存管理
    【C++学习笔记】什么是C++STL?掌握C++ STL的核心很重要!
    都要2021年了,现代C++有什么值得我们学习的?
    解析:C++如何实现简单的学生管理系统(源码分享)
    程序员过高工资导致加班?应该降低程序员工资?网友:放过其他苦逼的程序员吧
    结对-结对编程项目作业名称-需求分析
    使用对话框模板创建一个InputBox()在C + +
    选择图标
  • 原文地址:https://www.cnblogs.com/hhelibeb/p/5985110.html
Copyright © 2011-2022 走看看