S-JIS[2013-11-10/2016-02-11] 変更履歴

Asakusa Framework マスターつき更新演算子

Asakusa FrameworkOperator DSLのマスターつき更新演算子(@MasterJoinUpdate)のメモ。


概要

マスターつき更新演算子は、レコードに合致するマスターレコードの値を使ってトランザクション(明細)レコードの内容を更新する演算子。
性能特性はJoin(旧ドキュメントではReduce、最適化によってはMap)。[/2016-02-11]

入力
ポート数
入力データモデル
の制約
イメージ 出力
ポート数
出力データモデル
の制約
入力1レコード
に対する
出力レコード数
2 master (マスター) 2 updated txと同じ
データモデル
txの1レコードに対し
updatedかmissedの
どちらかに1レコード。
tx   missed txと同じ
データモデル

トランザクション(明細データ)レコード(の指定したキー)に合致するマスターレコードが存在したら、そのトランザクションレコードの内容を更新してupdatedに出力する。
存在しなければmissedに出力する。


マスターつき更新演算子は、マスターデータの値によってトランザクションレコードの値を変更する為に使う。

マスターと結合した新しいデータモデルを出力したい場合はマスター結合演算子(@MasterJoin)を使う。
合致するマスターが存在するかどうかを確認するだけの場合はマスター確認演算子(@MasterCheck)を使う。
(マスターデータは出力しないが)結合したマスターデータの内容に応じて処理を分岐したい場合はマスター分岐演算子(@MasterBranch)を使う。


hoge_transactionに合致するhoge_masterから「master_name」項目を更新する例。

入力データ例   出力データ例
master
hoge_master
id name group
a apple 1
b orange 2
c toy 100
d game 101
e other 900
f other2 999
updated
hoge_transaction
date master_id master_name value
2013-11-29 a apple 123
2013-11-29 b orange 456
2013-11-29 d game 789
2013-11-29 e other 111
tx
hoge_transaction
date master_id master_name value
2013-11-29 a   123
2013-11-29 b   456
2013-11-29 d   789
2013-11-29 e   111
2013-11-29 z   222
missed
hoge_transaction
date master_id master_name value
2013-11-29 z   222

example.dmdl(DMDL):

hoge_master = {

    id : TEXT;

    name : TEXT;
};

hoge_transaction = {

    date : DATE;

    master_id : TEXT;

    master_name : TEXT;

    value : LONG;
};

ExampleOperator.java(Operator DSL):

import com.asakusafw.vocabulary.model.Key;
import com.asakusafw.vocabulary.operator.MasterJoinUpdate;

import com.example.modelgen.dmdl.model.HogeMaster;
import com.example.modelgen.dmdl.model.HogeTransaction;
public abstract class ExampleOperator {

	/**
	 * HogeMasterのnameをHogeTransactionにセットする
	 * 
	 * @param master
	 *         マスタデータ
	 * @param tx
	 *         トランザクションデータ
	 */
	@MasterJoinUpdate
	public void updateWithMaster(
		@Key(group = "id")        HogeMaster      master,
		@Key(group = "master_id") HogeTransaction tx
	) {
		tx.setMasterName(master.getName());
	}
}

第1引数でマスターとなるデータモデル、第2引数でトランザクション(明細)となるデータモデルを指定する。
各引数には@Keyアノテーションを付けて、結合キーを指定する。
複数の項目を結合キーとする場合は「@Key(group = { "key1", "key2" })」のように波括弧でくくってカンマ区切りで指定する。

MasterBranchとは異なり、)第1引数も第2引数も常にnull以外となる。[2015-03-22]
マスターが存在しない場合はmissedに出力されるので、自分がコーディングしたメソッドが呼ばれることは無い。

ExampleJob.java(Flow DSL):

import com.example.modelgen.dmdl.model.HogeMaster;
import com.example.modelgen.dmdl.model.HogeTransaction;

import com.example.operator.ExampleOperatorFactory;
import com.example.operator.ExampleOperatorFactory.UpdateWithMaster;
	private final In<HogeMaster>      master;
	private final In<HogeTransaction> detail;

	private final Out<HogeTransaction> out1;
	private final Out<HogeTransaction> out2;
	@Override
	public void describe() {
		ExampleOperatorFactory operators = new ExampleOperatorFactory();

		// マスターつき更新
		UpdateWithMaster updateWithMaster = operators.updateWithMaster(this.master, this.detail);

		this.out1.add(exists.updated);
		this.out2.add(exists.missed);
	}

Flow DSLでは、自分が作ったOperatorのFactoryクラス(AsakusaFWのコンパイラーによって生成される)を使用する。
メソッド名はOperatorクラスに書いたメソッド名と同じ。
戻り値の型はAsakusaFWのコンパイラーによって生成されたクラス。(メソッド名を先頭が大文字のキャメルケースに変換したもの)
メソッドの引数は第1引数がマスターデータ、第2引数がトランザクション(明細)データ。
出力ポートの名前のデフォルトはupdatedとmissed。

出力ポート名を変えたい場合は@MasterJoinUpdateアノテーションで指定できる。

	@MasterJoinUpdate(updatedPort = "updated", missedPort = "missed")

単体テスト

マスター更新演算子の単体テストの実装例。

ExampleOperatorTest.java:

package com.example.operator;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Test;

import com.example.modelgen.dmdl.model.HogeMaster;
import com.example.modelgen.dmdl.model.HogeTransaction;
/**
 * {@link ExampleOperator}のテスト.
 */
public class ExampleOperatorTest {

	@Test
	public void updateWithMaster() {
		ExampleOperator operator = new ExampleOperatorImpl();

		HogeMaster master = new HogeMaster();
		master.setNameAsString("hishidama");
		HogeTransaction tx = new HogeTransaction();

		operator.updateWithMaster(master, tx);

		assertThat(tx.getMasterNameAsString(), is("hishidama"));
	}
}

Operatorのテストクラスは、通常のJavaのJUnitのテストケースクラスとして作成する。

テスト対象のOperatorクラス自身は抽象クラスだが、Operatorクラス名の末尾に「Impl」の付いた具象クラスがAsakusaFWによって生成されるので、それを使う。


他の演算子による代替

マスター分岐演算子は、マスター結合更新分割で同様の処理を行うことが出来る。
分割演算子(@Split)は、結合モデルを結合元のデータモデルに戻す演算子)

つまり、後の処理で結合したデータを使うなら(分割の必要は無いので)、マスター結合更新を使う。


類似

マスターつき更新演算子は、SQLのJOINに似ている。

INSERT INTO updated (date, master_id, master_name, value)
SELECT tx.date, tx.master_id, master.name, tx.value FROM tx INNER JOIN master ON master.id = tx.master_id;

Operator DSLへ戻る / AsakusaFW目次へ戻る / 技術メモへ戻る
メールの送信先:ひしだま