2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【RAP】Early Numbering

Last updated at Posted at 2022-01-12

はじめに

この記事では、RAP(ABAP RESTful Application Programming Model)でキーの採番(Numbering)をする方法について紹介します。

シリーズの先頭はこちら☞ 【RAP】ADTのRAP Generatorを使ってみる

RAPでの採番方法

RAPでの採番方法には、以下のようなパターンがあります。
参考:Numbering

image.png
まず大きくEarly NumberingLate Numberingがあり、Early Numberingはさらに枝分かれしています。これらの方法はBOのタイプ(Managed, Unmanaged)、ドラフトの有無にかかわらず使うことができます(※)。
Numberingの種類を説明するManaged、Unmagaedは、BOの種類とは関係なく、番号を自分で(Unmanaged)採番するか、フレームワークが(Managed)採番するかの違いを表しています。

※Late NumberingについてはUnmanagd BOでしか使えないという情報もあるので次回確認します。ドキュメントを見ると、どちらでも使えそうですが…

2022/1/15 更新
BTPのABAP環境では、Managed BOでもLate Numberingを使うことができました。

Early Numbering, Late Numberingとは

Early、Lateはキーの採番タイミングを指します。Early Numberingでは、エンティティの登録リクエストがあると即座に採番を行います。このあとでチェックやDBへの保存が行われるため、登録がキャンセルされた場合はその番号は不使用となり、番号に抜けが発生する可能性があります。Late NumberingではDBへの保存の直前に採番が行われ、この後にエラーは基本起こりえないため、番号に抜けが発生しません。

Early Numberingの分類

Early Numberingはさらに枝分かれします。External Early Numberingとは、キーをユーザの入力など外部から受け取ることを指します。これに対してInternal Early Numberingとは、自動で採番を行うことを指します。Managed Internal Early Numberingはフレームワークに番号の採番を任せる方法で、この場合キーに使えるのはUUIDのみです。Unmanaged Internal Early Numberingは自分で番号を採番する方法です。

Unmanaged Internal Early Numberingを実装

この記事では、Unmanaged Internal Early Numberingを実装してみます。この方法は、テーブルがUUIDでないキーを持ち、キーの採番を自動で行いたい場合に使用します。
ステップは以下のようになります。

  1. UUIDでないキーを持つテーブルを登録
  2. RAP GeneratorでBOを生成
  3. Early Numberingの実装

1. UUIDでないキーを持つテーブルを登録

以下のテーブルを定義します。

@EndUserText.label : 'Managed Person with Numeric Key'
@AbapCatalog.enhancement.category : #NOT_EXTENSIBLE
@AbapCatalog.tableCategory : #TRANSPARENT
@AbapCatalog.deliveryClass : #A
@AbapCatalog.dataMaintenance : #RESTRICTED
define table zperson_num_m {
  key client            : abap.clnt not null;
  key person_id         : ze_person_id not null;
  first_name            : ze_firstname;
  last_name             : ze_lastname;
  email                 : ze_email120;
  birthday              : ze_birthday;
  status                : ze_status;
  created_by            : abp_creation_user;
  created_at            : abp_creation_tstmpl;
  last_changed_by       : abp_locinst_lastchange_user;
  local_last_changed_at : abp_locinst_lastchange_tstmpl;
  last_changed_at       : abp_lastchange_tstmpl;

}

キーのために以下のデータエレメントを定義しました。
image.png

2. RAP GeneratorでBOを生成

こちらの記事の要領でBOを生成します。
image.png

Behavior Definitionを見てみると、UUIDをキーにしていたときとは以下の違いがあります。

  • キー項目がreadonlyになっていない
  • numberingに関する指定がない

UUIDがキーのとき

{
  field ( readonly )
   PersonUUID,
   CreatedAt,
   CreatedBy,
   LastChangedAt,
   LocalLastChangedAt,
   LastChangedBy;

  field ( numbering : managed )
   PersonUUID;

UUIDがキーでないとき

{
  field ( readonly )
   CreatedAt,
   CreatedBy,
   LastChangedAt,
   LocalLastChangedAt,
   LastChangedBy;

すなわちデフォルトでは、キーを外部から受け取るExternal Early Numberingになっているということです。

3. Early Numberingの実装

3.1. Behavior Definitionの設定

Behavior Definitionの先頭にearly numberingの指定を追加します。また、キー項目であるPersonIDをreadonlyに設定します。

define behavior for ZI_PERSON_NUM_M alias Person
persistent table zperson_num_m
draft table zperson_num_m_d
etag master LocalLastChangedAt
lock master total etag LastChangedAt
authorization master( global )
early numbering //追加

{
  field ( readonly )
   CreatedAt,
   CreatedBy,
   LastChangedAt,
   LocalLastChangedAt,
   LastChangedBy,
   PersonID; //追加

createのところに警告が出るので、Quick Fix(Ctrl + 1)でメソッドを実装します。
image.png

Behavior InplementationクラスのLocal Typeにメソッドearlynumbering_createが追加されます。

CLASS LCL_HANDLER DEFINITION INHERITING FROM CL_ABAP_BEHAVIOR_HANDLER.
  PRIVATE SECTION.
    METHODS:
      GET_GLOBAL_AUTHORIZATIONS FOR GLOBAL AUTHORIZATION
        IMPORTING
           REQUEST requested_authorizations FOR Person
        RESULT result,
      earlynumbering_create FOR NUMBERING
            IMPORTING entities FOR CREATE Person.
ENDCLASS.

CLASS LCL_HANDLER IMPLEMENTATION.
  METHOD GET_GLOBAL_AUTHORIZATIONS.
  ENDMETHOD.
  METHOD earlynumbering_create.
  ENDMETHOD.

ENDCLASS.

3.2. Behavior Implementationの実装

メソッドearlynumbering_createを以下のように実装します。メソッドのリターンパラメータはfailedreportedmappedという3つのテーブルです。failed、reportedはエラーの場合に返すもので、今回重要なのがmappedです。mappedにはフレームワークで採番される仮のキー(%cid)と自分で採番したキーのマッピングを返します。
デバッグで見ると、mapped-personは以下の構造でした。つまり、ドラフトかどうかもキーに含まれるということです。
image.png

最初の考え
最初は以下のような実装を考えました。簡単にするためDBから最大のキーを取得してそれをインクリメントします。
参考:BTPで番号範囲を使うには、以下の方法があります。
https://blogs.sap.com/2020/09/03/number-ranges-sap-cloud-platform/

  METHOD earlynumbering_create.
    "Get max person id from db
    select max( person_id ) from zperson_num_m into @data(new_id).

    loop at entities ASSIGNING FIELD-SYMBOL(<person>).
      new_id += 1.
      append value #(
        %cid = <person>-%cid
        %is_draft = <person>-%is_draft
        personid = new_id
       ) to mapped-person.
    endloop.

  ENDMETHOD.

しかし、このメソッドはドラフトを登録したときと保存したときの2回動くことがわかりました。ドラフト状態のオブジェクトが複数作られるとキーがかぶってしまう可能性があります。そこで、以下のようにドラフトテーブルと本物のテーブルの両方を見に行くように変更しました。
また、保存時にドラフトと同じようにキーを採番すると、ドラフトのときのキーを上書きしてキーが変わってしまうこともわかったので、キーがすでに設定されている場合はその値をそのままmappedに渡すこととしました。

修正後

  METHOD earlynumbering_create.
    DATA new_id TYPE zperson_num_m-person_id.

    LOOP AT entities ASSIGNING FIELD-SYMBOL(<person>).
      if <person>-PersonID is not initial.
        new_id = <person>-PersonID.
      else.
        new_id = get_newid(  ).
      endif.

      APPEND VALUE #(
        %cid = <person>-%cid
        %is_draft = <person>-%is_draft
        personid = new_id
       ) TO mapped-person.

    ENDLOOP.

  ENDMETHOD.

  METHOD get_newid.
    "Get max person id from db and draft
    SELECT MAX( person_id ) FROM zperson_num_m INTO @DATA(max_id).
    SELECT MAX( personid ) FROM zperson_num_m_d INTO @DATA(max_id_draft).

    new_id = COND #( WHEN max_id > max_id_draft
                       THEN max_id
                       ELSE max_id_draft  ).
    new_id += 1.

  ENDMETHOD.

4. 動作確認

"Create"を押して新規データを登録します。
image.png
ドラフトの状態でキーが採番されます。
image.png
保存せずに戻り、もう一つデータを登録します。正しくキーがインクリメントされました。
image.png

参考

How to use Early Numbering with Semantic Keys – RAP Managed BO

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?