天天看點

demo:同步接口處理接收資料

場景:

第三方調用SAP接口,建立單據,如果對方因為某種原因在極短的時間内,使用重複資料連續調用了sap接口,怎樣防止重複建立單據。

之前群裡聊過這個問題,我把問題抛出來,大家随便聊聊而已。

場景其實挺簡單,也很常見,至于怎麼實作,無非是什麼加鎖,加日志之類的。

我也是做了一個簡單測試。

場景是推送資料到sap,建立PO。

先建立了個log表:

​​

demo:同步接口處理接收資料

​​​

​​

demo:同步接口處理接收資料

​​ 然後建了個鎖

​​

demo:同步接口處理接收資料

​​

然後寫了倆函數,分别是用鎖和用log表。

第一個函數

FUNCTION*"----------------------------------------------------------------------*"*"本地接口:*"  IMPORTING*"     VALUE(IS_DATA) TYPE  ZLMT_PO_LOG OPTIONAL*"  EXPORTING*"     VALUE(ES_DATA) TYPE  ZLMT_PO_LOG*"----------------------------------------------------------------------
DATA:LT_LOG TYPE TABLE OF ZLMT_PO_LOG.DATA:LS_LOG TYPE ZLMT_PO_LOG.
DATA:    LT_RETURN  LIKE TABLE OF BAPIRET2,    LT_POITEM  LIKE TABLE OF BAPIMEPOITEM,    LT_POITEMX LIKE TABLE OF BAPIMEPOITEMX,    LT_POCOND  LIKE TABLE OF BAPIMEPOCOND,    LT_POCONDX LIKE TABLE OF BAPIMEPOCONDX,    LS_POCOND  LIKE    BAPIMEPOCOND,    LS_POCONDX LIKE   BAPIMEPOCONDX.DATA:    LS_POHEADER  LIKE BAPIMEPOHEADER,    LS_POHEADERX LIKE BAPIMEPOHEADERX,    LS_RETURN    LIKE BAPIRET2,    LS_POITEM    LIKE BAPIMEPOITEM,    LS_POITEMX   LIKE BAPIMEPOITEMX.DATA:LV_PO_NUMBER LIKE  BAPIMEPOHEADER-PO_NUMBER.
*--------------------------------------------------------------------** 參數指派*--------------------------------------------------------------------*
IF    MOVE-CORRESPONDING IS_DATA TO LS_LOG.  ELSE.
FUNCTION '/SAPSLL/GUID_CREATE'      IMPORTING        EV_GUID_32 = LS_LOG-GUID.
'LM00001'  ."外部單據号    LS_LOG-BUKRS         = '1710'  ."公司代碼'NB'  ."訂單類型(采購)    LS_LOG-LIFNR         = 'USSU-VSF04'  ."供應商或債權人的帳号'1710'  ."采購組織    LS_LOG-EKGRP         = '002'  ."采購組'MZ-RM-R300-01'  ."物料編号    LS_LOG-WERKS         = '1710'  ."工廠'171C'  ."庫存地點    LS_LOG-KSCHA         = 'PMP0'  ."條件類型'1'  ."條件金額    LS_LOG-WAERS         = 'USD'  ."貨币碼
    LS_LOG-UNAME = SY-UNAME.    LS_LOG-DATUM = SY-DATUM.    LS_LOG-UZEIT = SY-UZEIT.
  ENDIF.
*--------------------------------------------------------------------** 枷鎖*--------------------------------------------------------------------*
FUNCTION 'ENQUEUE_EZLMT_PO_LOG'    EXPORTING'X'      MANDT            = SY-MANDT      WEB_ORDER        = LS_LOG-WEB_ORDER'3'    EXCEPTIONS123.IF SY-SUBRC <> 0.'E'.'被鎖'.
    INSERT ZLMT_PO_LOG FROM LS_LOG.    COMMIT WORK AND WAIT.
    ES_DATA = LS_LOG.    RETURN.  ENDIF.
*--------------------------------------------------------------------** 檢查庫表内該 web order是否已經成功建立 po*--------------------------------------------------------------------*DATA(LS_TMP)    WHERE  WEB_ORDER = @LS_LOG-WEB_ORDER.
IF SY-SUBRC = 0.'E'.'重複建立'.    INSERT ZLMT_PO_LOG FROM LS_LOG.    COMMIT WORK AND WAIT.
    ES_DATA = LS_LOG.    RETURN.  ENDIF.*--------------------------------------------------------------------** 指派 call bapi*--------------------------------------------------------------------*  CLEAR LS_POHEADER.  CLEAR LS_POHEADERX.  LS_POHEADER-COMP_CODE      = LS_LOG-BUKRS.  LS_POHEADER-CURRENCY       = LS_LOG-WAERS.  LS_POHEADER-DOC_DATE       = SY-DATUM.  LS_POHEADER-DOC_TYPE       = LS_LOG-BSART.  LS_POHEADER-VENDOR         = LS_LOG-LIFNR.  LS_POHEADER-PURCH_ORG      = LS_LOG-EKORG.  LS_POHEADER-PUR_GROUP      = LS_LOG-EKGRP.'X'.'X'.'X'.'X'.'X'.'X'.'X'.    CLEAR: LS_POITEM,LS_POITEMX.  CLEAR: LT_POITEM[],LT_POITEMX[].
'10'.                   "采購憑證的項目編号  LS_POITEM-MATERIAL        = LS_LOG-MATNR.          "商品代碼1."           "采購訂單數量'EA' .                   "采購訂單的計量機關  LS_POITEM-PLANT           = LS_LOG-WERKS.          "工廠"庫存地點
  APPEND LS_POITEM TO LT_POITEM.

  LS_POITEMX-PO_ITEM         =  '10'.          "采購憑證的項目編号'X'.            "商品代碼  LS_POITEMX-QUANTITY        = 'X'.            "采購訂單數量'X' .           "采購訂單的計量機關  LS_POITEMX-PLANT           = 'X'.            "工廠'X'.            "庫存地點

  APPEND LS_POITEMX TO LT_POITEMX.
  CLEAR LT_POCOND[].  CLEAR LT_POCONDX[].  CLEAR LS_POCOND.
  LS_POCOND-ITM_NUMBER = '10'.  LS_POCOND-COND_TYPE  = LS_LOG-KSCHA.  "定價條件  LS_POCOND-COND_VALUE = LS_LOG-AMOUNT."币别  LS_POCOND-CHANGE_ID   = 'I'.  "修改類型 I U  D
  APPEND LS_POCOND TO LT_POCOND.
  CLEAR LS_POCONDX.
'10'."定價條件  LS_POCONDX-COND_VALUE = 'X'.  "價格'X'.  "修改類型

  IF LS_POCOND-CURRENCY IS NOT INITIAL.    LS_POCONDX-CURRENCY   = 'X'.  "币别  ENDIF.
  APPEND LS_POCONDX TO LT_POCONDX.
*& call bapi
FUNCTION 'BAPI_PO_CREATE1'    EXPORTING      POHEADER         = LS_POHEADER      POHEADERX        = LS_POHEADERX    IMPORTING      EXPPURCHASEORDER = LV_PO_NUMBER    TABLESRETURN      POITEM           = LT_POITEM      POITEMX          = LT_POITEMX      POCOND           = LT_POCOND      POCONDX          = LT_POCONDX.

*--------------------------------------------------------------------**  save log*--------------------------------------------------------------------*  LS_LOG-EBELN = LV_PO_NUMBER.'S'.'建立成功'.
  LS_LOG-UNAME = SY-UNAME.  LS_LOG-DATUM = SY-DATUM.  LS_LOG-UZEIT = SY-UZEIT.
  ES_DATA = LS_LOG.
  INSERT ZLMT_PO_LOG FROM LS_LOG.
FUNCTION 'BAPI_TRANSACTION_COMMIT'    EXPORTING'X'.
*--------------------------------------------------------------------** 解鎖*--------------------------------------------------------------------*FUNCTION 'DEQUEUE_EZLMT_PO_LOG'    EXPORTING      MANDT     = SY-MANDT      WEB_ORDER = LS_LOG-WEB_ORDER    .ENDFUNCTION.      

僅僅是測試代碼而已。

第二個函數,隻是沒用鎖,自己把 加鎖 解鎖 注釋掉就行了,

(LS_LOG-WEB_ORDER         = 'LM00002')。

​​

demo:同步接口處理接收資料

​​​

​​

demo:同步接口處理接收資料

​​

第一個函數沒有重複資料。

第二個函數出現了問題:

​​

demo:同步接口處理接收資料

​​

大概就是這個意思了。

僅僅是簡單測試了下,如果有什麼不對的地方歡迎批評指正。謝謝!~

這個其實還有一個極端情況的問題,就是第一條鎖釋放後,到第一條資料落表的這個時間差裡,進來的資料。

這個場景我沒模拟出來。