本文介绍创建一个有主从表关系的CDS,并同时生成BOPF,其中使用到两个自定义表:ZTUSER(用户表),ZTUSER_MENU(用户可用菜单 表),每个用户可用的菜单可能有多个,表结构如图,其中表ZTUSER,包含结构:/BOBF/S_LIB_ADMIN_DATA,用于记录数据的创建、修改信息,后面介绍BOPF的Determinations增强时使用。


1.创建使用到的主、从表结构
结构如上图,
2.在HANA Studio中创建两个CDS
1.在创建BOPF的CDS时创建建议VIEW的名字定义格式为:Z***_I_**,其中的I表示的是Interface(接口)的意思,以使用于与其它的ODATA的CDS(Z***_C_**)、查询的CDS等区别Z***_Q_**),
2.sqlViewName名字在VIEW名字后面加V;
3.在从表CDS中由于使用了@ObjectModel.association.type: [#TO_COMPOSITION_ROOT,#TO_COMPOSITION_PARENT],所以不能使用:transactionalProcessingEnabled: true参考,否则提示报错,也就是说从表CDS不会生成BOPF.
4.仔细查看两个CDS发现他们是互相包含,所以在激活时需要选择两个一起激活;
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
@AbapCatalog.sqlViewName: 'ZUSER_I_USER2V' @AbapCatalog.compiler.compareFilter: true @AbapCatalog.preserveKey: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'user mange' @ObjectModel:{ semanticKey: ['bname'], modelCategory: #BUSINESS_OBJECT, compositionRoot: true, transactionalProcessingEnabled: true, writeActivePersistence: 'ztuser', createEnabled: true, deleteEnabled: true, updateEnabled: true } define view ZUSER_I_USER2 as select from ztuser as user association [0..*] to ZUSER_I_USER_MENU2 as _menu on $projection.bname = _menu.bname { key user.bname, user.name_text, user.zpwod, user.ztel, user.zutyp, user.zstcod, user.menue, user.spld, user.hdest, user.hname, user.langu, user.zlaip, user.crea_date_time, user.crea_uname, user.lchg_date_time, user.lchg_uname, @ObjectModel.association.type: #TO_COMPOSITION_CHILD _menu } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
@AbapCatalog.sqlViewName: 'ZUSER_I_UMENU2V' @AbapCatalog.compiler.compareFilter: true @AbapCatalog.preserveKey: true @AccessControl.authorizationCheck: #NOT_REQUIRED @EndUserText.label: 'user menu' @ObjectModel:{ semanticKey: ['bname'], modelCategory: #BUSINESS_OBJECT, // compositionRoot: true, // transactionalProcessingEnabled: true, writeActivePersistence: 'ztuser_menu', createEnabled: true, deleteEnabled: true, updateEnabled: true } define view ZUSER_I_USER_MENU2 as select from ztuser_menu as menu association [1..1] to ZUSER_I_USER2 as _user on $projection.bname = _user.bname { key menu.bname, key menu.zstcod, menu.zkcde, menu.zauth, @ObjectModel.association.type: [#TO_COMPOSITION_ROOT,#TO_COMPOSITION_PARENT] _user } |
3.BOPF增强,
上面的两个CDS激活后,主表的CDS就会激活一个BOPF Business Objects的对像ZUSER_I_USER2。双击打开此对像。
并在Determinations中增加一个增强类LIB_ADMIN(自己取名),

第四步创建成功LIB_ADMIN后,点击第五步。

点击Implementation class,就可以写入代码来实现在主表创建、修改时的触类了,类的代码主要写在/BOBF/IF_FRW_DETERMINATION~EXECUTE方法中,如下,此可做为通用的记录表的创建、修改信息增强类使用。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
CLASS ZCL_USER_D_LIB_ADMIN DEFINITION PUBLIC INHERITING FROM /BOBF/CL_LIB_D_SUPERCL_SIMPLE FINAL CREATE PUBLIC . PUBLIC SECTION. METHODS /BOBF/IF_FRW_DETERMINATION~EXECUTE REDEFINITION . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS ZCL_USER_D_LIB_ADMIN IMPLEMENTATION. METHOD /BOBF/IF_FRW_DETERMINATION~EXECUTE. FIELD-SYMBOLS <LT_DATA> TYPE INDEX TABLE. DATA: LS_NODE_CONF TYPE /BOBF/S_CONFRO_NODE. DATA LO_CHANGE TYPE REF TO /BOBF/IF_FRW_CHANGE. DATA LS_CHANGE TYPE /BOBF/S_FRW_CHANGE. DATA LT_CHANGE TYPE /BOBF/T_FRW_CHANGE. DATA LS_KEY TYPE /BOBF/S_FRW_KEY. IO_READ->COMPARE( EXPORTING IV_NODE_KEY = IS_CTX-NODE_KEY IT_KEY = IT_KEY IV_FILL_ATTRIBUTES = ABAP_TRUE IMPORTING EO_CHANGE = LO_CHANGE ). * get relevant changes LO_CHANGE->GET( EXPORTING IV_SORTED = /BOBF/IF_FRW_C=>SC_CHANGE_SORT_KEY IV_NO_LOAD = ABAP_TRUE IMPORTING ET_CHANGE = LT_CHANGE ). /BOBF/CL_FRW_FACTORY=>GET_CONFIGURATION( IS_CTX-BO_KEY )->GET_NODE( EXPORTING IV_NODE_KEY = IS_CTX-NODE_KEY IMPORTING ES_NODE = LS_NODE_CONF ). DATA: TP_DATA TYPE REF TO DATA. CREATE DATA TP_DATA TYPE (LS_NODE_CONF-DATA_TABLE_TYPE). ASSIGN TP_DATA->* TO <LT_DATA>. IO_READ->RETRIEVE( EXPORTING IV_NODE = IS_CTX-NODE_KEY IT_KEY = IT_KEY IMPORTING ET_DATA = <LT_DATA> ). FIELD-SYMBOLS: <LINE> TYPE ANY, <FIELD> TYPE ANY. GET TIME STAMP FIELD DATA(LV_TIMSTMP). LOOP AT <LT_DATA> ASSIGNING <LINE>. ASSIGN COMPONENT |KEY| OF STRUCTURE <LINE> TO FIELD-SYMBOL(<KEY>). ASSIGN COMPONENT |ROOT_KEY| OF STRUCTURE <LINE> TO FIELD-SYMBOL(<ROOT_KEY>). ASSIGN COMPONENT |STATUS| OF STRUCTURE <LINE> TO <FIELD>. IF SY-SUBRC = 0 AND <FIELD> IS INITIAL. <FIELD> = 'A'. ENDIF. CLEAR: LS_CHANGE. READ TABLE LT_CHANGE INTO LS_CHANGE WITH KEY KEY = <KEY>. IF LS_CHANGE-CHANGE_MODE = 'C'."CREATE ASSIGN COMPONENT |CREA_DATE_TIME| OF STRUCTURE <LINE> TO <FIELD>. IF SY-SUBRC = 0 AND <FIELD> IS INITIAL. <FIELD> = LV_TIMSTMP. ENDIF. ASSIGN COMPONENT |CREA_UNAME| OF STRUCTURE <LINE> TO <FIELD>. IF SY-SUBRC = 0 AND <FIELD> IS INITIAL. <FIELD> = SY-UNAME. ENDIF. ELSEIF LS_CHANGE-CHANGE_MODE = 'U'."UPDATE ASSIGN COMPONENT |LCHG_DATE_TIME| OF STRUCTURE <LINE> TO <FIELD>. IF SY-SUBRC = 0. <FIELD> = LV_TIMSTMP. ENDIF. ASSIGN COMPONENT |LCHG_UNAME| OF STRUCTURE <LINE> TO <FIELD>. IF SY-SUBRC = 0. <FIELD> = SY-UNAME. ENDIF. ENDIF.. ASSIGN COMPONENT |NODE_DATA| OF STRUCTURE <LINE> TO FIELD-SYMBOL(<NODE_DATA>). IO_MODIFY->UPDATE( EXPORTING IV_NODE = IS_CTX-NODE_KEY IV_KEY = <KEY> IV_ROOT_KEY = <ROOT_KEY> IS_DATA = REF #( <NODE_DATA> ) ). ENDLOOP. ENDMETHOD. ENDCLASS. |
4.BOPF测试
在SAP GUI中使用事务码BOBT打开ZUSER_I_USER2,就可创建数据了

创建并保存的后,SE16N打开主表可发现同时记录了创建及修改信息,但在ODATA操作时只会记录一个,可进行测试.

在此测试时,发现是输入数据回车后,就会触发前面的Determinations中增加一个增强类LIB_ADMIN,结果就是点击增加时状态为”C”,修改数据回车时就触发的就是“U”,这可能与我们需求有差异,当然事实上,如我们是最后生成的ODATA或者其它的功能使用时,这也不会有问题的,
这时我们可以使用BOBX打开此BOPF对像,把此LIB_ADMIN类的触发条件从原来的”After Modify”修改为“Before Save”,如图,结果就完美了。

下一步是使用此CDS创建并生成新ODATA。
