8. DMDLによるデータモデルの定義

このチュートリアルでは DMDL を利用してAsakusa Frameworkで利用する データモデル を定義する方法を説明していきます。

8.1. DMDLとは

DMDL(Data Model Definition Language)はAsakusa Frameworkで利用可能なデータモデルを定義するためのDSLです。

DMDLスクリプト というファイルにデータモデルの名前や構造を定義し、DMDLコンパイラを実行することで、定義したデータモデルに対応するJavaのプログラムを自動的に生成します。

DMDLから生成されるJavaプログラムは、バッチアプリケーションを構成する各プログラムの入出力データを保持したり、外部ファイルやデータベースとの連携を行う際のフォーマットを管理したりと、様々な用途に利用します。

このチュートリアルでは、前項の サンプルアプリケーションの説明 で説明した データ構造 の定義に従って、以下のデータモデルを作成していきます。

  1. 売上明細 ( sales_detail )
  2. 店舗マスタ ( store_info )
  3. 商品マスタ ( item_info )
  4. カテゴリ別売上集計 ( category_summary )
  5. エラー情報 ( error_record )

下図は、これらのデータモデルがデータフローのどこで使用されているかを示しています。

_images/example-app-dataflow-dmdl-1.png

この図で示す通り、データモデルはバッチアプリケーションの入力データや出力データを保持したり、データフロー内の中間データを保持するために利用します。

なお、この図に対応がないデータモデルは後のチュートリアルで説明します。

8.2. DMDLスクリプトを作成する

まず、DMDLを記述するためのテキストファイルであるDMDLスクリプトファイルを作成します。

DMDLスクリプトファイルはプロジェクトの src/main/dmdl ディレクトリ以下に、拡張子 .dmdl を持つファイルとして作成します。

このチュートリアルでは、 models.dmdl というファイルを作成します。

_images/create-dmdl-file.png

作成したファイルをエディタで開きます。

See also

DMDLスクリプトはEclipseに組み込まれている通常のテキストエディタで編集することができますが、DMDLの構文ハイライト機能などを提供するEclipseプラグイン「DMDL EditorX」を利用することもできます。

DMDLエディタについては、 関連ドキュメント を参照してください。

8.3. DMDLスクリプトの構文

DMDLスクリプトの基本的な構文を簡単に説明します。

データモデルの定義は、DMDLスクリプト内に以下のような形式で記述します。

<データモデル名> = {
    <プロパティ名> : <プロパティ型>;
    <プロパティ名> : <プロパティ型>;
    ...
};

<データモデル名> = {
    <プロパティ名> : <プロパティ型>;
    <プロパティ名> : <プロパティ型>;
    ...
};
...
  • 「データモデル名」や「プロパティ名」は 小文字のアルファベット、数字、アンダースコア のみを使用できます。
  • データモデル定義のブロックやプロパティ定義行の末尾には セミコロン を指定します。
  • 「プロパティ型」には次の型を指定できます。
利用可能なプロパティの型
型の名前 説明
INT 32bit符号付き整数
LONG 64bit符号付き整数
FLOAT 単精度浮動小数点
DOUBLE 倍精度浮動小数点
TEXT 文字列
DECIMAL 10進数
DATE 日付
DATETIME 日時
BOOLEAN 論理値
BYTE 8bit符号付き整数
SHORT 16bit符号付き整数

データモデルやプロパティの定義の直前の行に ダブルクォートで囲んだ文字列 を指定することで「データモデルの説明」を記述することができます。

"データモデルの説明"
<データモデル名> = {

    "プロパティの説明"
    <プロパティ名> : <プロパティ型>;

    "プロパティの説明"
    <プロパティ名> : <プロパティ型>;
    ...
};

なおプロパティ定義行の前後には任意の空行を挿入することもできます。

8.4. データモデルを定義する

DMDLスクリプトファイルにデータモデルを定義していきます。

ここでは サンプルアプリケーションの説明 で紹介した データ構造 のうち、 売上明細 ( sales_detail ) のデータモデルを定義する過程を説明していきます。

まず models.dmdlsales_detail というデータモデル名を持つデータモデル定義ブロックを記述します。

models.dmdl
1
2
3
sales_detail = {

};

データモデル定義ブロック内にデータモデルのプロパティを追加していきます。

models.dmdl
1
2
3
4
5
6
7
8
sales_detail = {
    sales_date_time : DATETIME;
    store_code : TEXT;
    item_code : TEXT;
    amount : INT;
    unit_selling_price : INT;
    selling_price : INT;
};

データモデル定義とプロパティ定義に説明を追加します。

models.dmdl
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
"売上明細"
sales_detail = {

    "売上日時"
    sales_date_time : DATETIME;

    "店舗コード"
    store_code : TEXT;

    "商品コード"
    item_code : TEXT;

    "数量"
    amount : INT;

    "販売単価"
    unit_selling_price : INT;

    "販売金額"
    selling_price : INT;
};

8.5. データモデルクラスを生成する

売上明細データモデルを定義したところで、このDMDLスクリプトからJavaのデータモデルクラスを作成してみましょう。

8.5.1. Eclipse上でデータモデルクラスを生成

Shafuを導入したEclipse環境では、コンテキストメニューからデータモデルクラスの生成を実行することができます。

  1. プロジェクトを選択してコンテキストメニュー(右クリックなどで表示されるメニュー)を表示します。
  2. コンテキストメニューの Jinrikisha (人力車) を選択し、サブメニューとして表示される DMDLからデータモデルクラスを生成 を選択します。
_images/shafu-compile-dmdl.png
  1. 正常に終了すると、コンソールに以下のように BUILD SUCCESSFUL と出力されます。
_images/shafu-compile-dmdl-log.png

生成されるデータモデルクラスについては、この後のチュートリアル DMDLのコンパイル で説明します。

8.5.2. コマンドライン上でデータモデルクラスを生成

コマンドライン上からデータモデルクラスを生成する場合は、Gradleの compileDMDL タスクを実行します。

./gradlew compileDMDL

8.5.3. DMDLのコンパイルエラー

データモデルクラスの生成に失敗した場合には、コンソールにエラーメッセージが表示され、生成処理が中断されます。

ERROR file:/C:/Users/asakusa/workspace/asakusa-tutorial/src/main/dmdl/models.dmdlの解析に失敗しました
com.asakusafw.dmdl.parser.DmdlSyntaxException: DMDLスクリプトが正しくありません: 「";"」がおそらく必要です
(場所: file:/C:/Users/asakusa/workspace/asakusa-tutorial/src/main/dmdl/models.dmdl:3:5)
...
BUILD FAILED

生成に失敗する場合の多くは、記述したDMDLスクリプトに構文エラーがあることが原因です。 上記のエラーメッセージは、プロパティ定義の最後に ; を指定し忘れた場合のエラーメッセージ例です。

models.dmdl - 不正なデータモデルの例
1
2
3
4
sales_detail = {
    sales_date_time : DATETIME
    store_code : TEXT;
};

エラーメッセージにはDMDLスクリプトが不正な原因とおおよその場所(原因のファイル名:行:列)が表示されます。 上記の例では3行目の5文字目、というように表示されていますが実際にはこの直前の行の末尾に ; がないことが原因です。

エラー箇所を特定する場合はエラーメッセージの内容を手かがりに、その周辺に不正な記述がないかを確認するようにしてください。

8.6. レコードモデル

DMDLでは、このチュートリアルで説明したようなデータモデル内にプロパティの一覧のみを持つデータモデルを レコードモデル と呼びます。 つまり先の手順では売上明細をレコードモデルとして定義したことになります。

次のチュートリアルでは、レコードモデル以外のデータモデル 結合モデル , 集計モデル について説明しますが、 その前に サンプルアプリケーションの説明データ構造 で説明した全てのデータモデルを定義しておきましょう。

サンプルアプリケーションの説明データ構造 に含まれる、 以下のデータ構造の定義をレコードモデルとして models.dmdl に追加しましょう。

8.7. 終わりに

全てのデータモデルを定義した後にデータモデルクラスの生成を行い、5つのデータモデルの生成が成功していることをコンソールで確認してください。

このチュートリアル終了時点のDMDLスクリプト models.dmdl は、次のようになります。

models.dmdl
 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
"売上明細"
sales_detail = {

    "売上日時"
    sales_date_time : DATETIME;

    "店舗コード"
    store_code : TEXT;

    "商品コード"
    item_code : TEXT;

    "数量"
    amount : INT;

    "販売単価"
    unit_selling_price : INT;

    "販売金額"
    selling_price : INT;
};

"店舗マスタ"
store_info = {

    "店舗コード"
    store_code : TEXT;

    "店舗名称"
    store_name : TEXT;
};

"商品マスタ"
item_info = {

    "商品コード"
    item_code : TEXT;

    "商品名"
    item_name : TEXT;

    "商品部門コード"
    department_code : TEXT;

    "商品部門名"
    department_name : TEXT;

    "商品カテゴリコード"
    category_code : TEXT;

    "商品カテゴリ名"
    category_name : TEXT;

    "商品単価"
    unit_selling_price : INT;

    "マスタ登録日"
    registered_date : DATE;

    "マスタ適用開始日"
    begin_date : DATE;

    "マスタ適用終了日"
    end_date : DATE;
};

"カテゴリ別売上集計"
category_summary = {

    "カテゴリコード"
    category_code : TEXT;

    "販売数量"
    amount_total : LONG;

    "売上合計"
    selling_price_total : LONG;
};

"エラー情報"
error_record = {

    "ファイル名"
    file_name : TEXT;

    "売上日時"
    sales_date_time : DATETIME;

    "店舗コード"
    store_code : TEXT;

    "商品コード"
    item_code : TEXT;

    "エラーメッセージ"
    message : TEXT;
};