Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Reladomoを使った
トランザクション履歴管理を
プロダクトに適用した際の
メリット/デメリット/課題など
JJUG CCC 2019 Spring
#jjug_ccc #ccc_m7
2019-05-18
株式会社オープントーン 渡邉 一夫
#ccc_m7
自己紹介
• 名前:渡邉 一夫 ( Twitter → @nave_kazu )
• エンジニア歴:20年
• 所属:株式会社オープントーン
• 秋葉原
• 勤怠管理システム
• 観光ビッグデータ
• ヘルス・メディテック
• ...
#ccc_m7
自己紹介
• 名前:渡邉 一夫 ( Twitter → @nave_kazu )
• Java歴:20年弱
• MS Visual J++ 6.0でアプレットを作ったのが初めてのJava
• 独習Javaで言語仕様やJava S...
#ccc_m7
自己紹介
• 名前:渡邉 一夫 ( Twitter → @nave_kazu )
• Java歴:20年弱
• 今はDB設計してSpring BootでWeb APIを書いたり、
AngularやVue.jsでクライアントを書い...
#ccc_m7
自己紹介
• 名前:渡邉 一夫 ( Twitter → @nave_kazu )
• その他
• 共著 システム開発のための見積りのすべてがわかる本
• AWS 認定ソリューションアーキテクト–アソシエイト取得
#ccc_m7
自己紹介
• HEAVY ROTATION → BAND-MAID
#ccc_m7
自己紹介
• HEAVY ROTATION → BAND-MAID
メイド喫茶のノリをバンドでやってみた
5ピースガールズバンド
コスチューム → メイド服
ライブ → お給仕
ライブ参加 → ご帰宅
ファン → ご主人様・お嬢...
#ccc_m7
自己紹介
• HEAVY ROTATION → BAND-MAID
メイド喫茶のノリをバンドでやってみた
5ピースガールズバンド
コスチューム → メイド服
ライブ → お給仕
ライブ参加 → ご帰宅
ファン → ご主人様・お嬢...
#ccc_m7
アジェンダ
• Reladomoとは?
• 履歴管理のいろいろ
• Reladomoのプロダクト適用例
• Reladomoの実装例
#ccc_m7
Reladomoとは?
• ゴールドマン・サックスが開発するORM
• XMLでテーブル定義をしDDL・エンティティ自動生成
• 履歴管理(バイテンポラル)に特化している
• 型付けされたクエリー言語(SQLは書かない)
• e...
#ccc_m7
履歴管理いろいろ(Chaining)
• 履歴管理なし (Snapshot)
• 「今」しか扱わない
• 営業時間のみ (Business-Only)
• 業務上の意味のある時間(Business date)を管理する
• 処理...
#ccc_m7
履歴管理いろいろ(Chaining)
• シナリオ (ユーザー管理)
• 「小鳩ミク」さんを登録する
• 利用開始は4月1日から (Business date)
• 登録は3月25日に行う(Processing date)
• ...
#ccc_m7
履歴管理いろいろ(Chaining)
• 履歴管理なし (Snapshot)
• 「小鳩ミク」さんを登録する
• 利用開始は4月1日から (Business date)
• 登録は3月25日に行う(Processing date...
#ccc_m7
履歴管理いろいろ(Chaining)
• 履歴管理なし (Snapshot)
• 「小鳩ミク」さんを登録する
• 利用開始は4月1日から (Business date)← 表現できない!
• 登録は3月25日に行う(Proces...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間のみ (Business-Only)
• 「小鳩ミク」さんを登録する
• 利用開始は4月1日から (Business date)
• 登録は3月25日に行う(Processing...
#ccc_m7
履歴管理いろいろ(Chaining)
• 処理時間のみ (Audit-Only)
• 「小鳩ミク」さんを登録する
• 利用開始は4月1日から (Business date)← 表現できない!
• 登録は3月25日に行う(Proc...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間・処理時間両方 (Bi-temporal)
• 「小鳩ミク」さんを登録する
• 利用開始は4月1日から (Business date)
• 登録は3月25日に行う(Process...
#ccc_m7
履歴管理いろいろ(Chaining)
• 履歴管理なし(Snapshot)
• 住所変更する
• 5月1日に住所変更したい(Business date) ← 表現できない!
• 申請は5月3日にあった(Processing da...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間のみ (Business-Only)
• 住所変更する
• 5月1日に住所変更したい(Business date)
• 申請は5月3日にあった(Processing date) ...
#ccc_m7
履歴管理いろいろ(Chaining)
• 処理時間のみ (Audit-Only)
• 住所変更する
• 5月1日に住所変更したい(Business date) ← 表現できない!
• 申請は5月3日にあった(Processing...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間・処理時間両方 (Bi-temporal)
• 住所変更する
• 5月1日に住所変更したい(Business date)
• 申請は5月3日にあった(Processing dat...
#ccc_m7
履歴管理いろいろ(Chaining)
• 履歴管理なし(Snapshot)
• 住所変更の訂正をする
• 誤りを5月4日に訂正したい (Processing date) ← 表現できない!
ユーザーID 名前 住所
1 小鳩ミク...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間のみ (Business-Only)
• 住所変更の訂正をする
• 誤りを5月4日に訂正したい (Processing date) ← 表現できない!
ユーザーID 名前 住所 ...
#ccc_m7
履歴管理いろいろ(Chaining)
• 処理時間のみ (Audit-Only)
• 住所変更の訂正をする
• 誤りを5月4日に訂正したい (Processing date)
監査(Audit)が目的なので、
変更前の「埼玉県」...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間・処理時間両方 (Bi-temporal)
• 住所変更の訂正をする
• 誤りを5月4日に訂正したい (Processing date)
ユーザーID 名前 住所 from_z ...
#ccc_m7
履歴管理いろいろ(Chaining)
• 履歴管理なし(Snapshot)
• 利用停止する
• 申請が5月31日にあった(Business / Processing date)← 表現できない!
• 即日停止としたい
ユーザー...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間のみ (Business-Only)
• 利用停止する
• 申請が5月31日にあった(Business / Processing date)
• 即日停止としたい
ユーザーID ...
#ccc_m7
履歴管理いろいろ(Chaining)
• 処理時間のみ (Audit-Only)
• 利用停止する
• 申請が5月31日にあった(Business / Processing date)
• 即日停止としたい
神奈川県のシステム有...
#ccc_m7
履歴管理いろいろ(Chaining)
• 営業時間・処理時間両方 (Bi-temporal)
• 利用停止する
• 申請が5月31日にあった(Business / Processing date)
• 即日停止としたい
ユーザー...
#ccc_m7
Bi-temporalを深掘り
住所 from_z thru_z in_z out_z
Inf
6/1
5/3
5/1
4/1
3/25
BusinessTime(from_z/thru_z) 3/25 4/1 5/1 3 4 ...
#ccc_m7
Bi-temporalを深掘り
• 「小鳩ミク」さんを登録する
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 9999/12/1 A
Inf
6/1
5...
#ccc_m7
Bi-temporalを深掘り
• 住所変更する
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
Inf
6/1
5/3
5/1
4...
#ccc_m7
Bi-temporalを深掘り
• 住所変更する
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 2019...
#ccc_m7
Bi-temporalを深掘り
• 住所変更の訂正をする
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 ...
#ccc_m7
Bi-temporalを深掘り
• 住所変更の訂正をする
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 ...
#ccc_m7
Bi-temporalを深掘り
• 利用停止する
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 2019...
#ccc_m7
Bi-temporalを深掘り
• 利用停止する
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 2019...
#ccc_m7
Bi-temporalを深掘り
• 4月中旬の状態
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 201...
#ccc_m7
Bi-temporalを深掘り
• 5月中旬の状態
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 201...
#ccc_m7
Bi-temporalを深掘り
• 最新の状態
住所 from_z thru_z in_z out_z
東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A
東京都 2019/4/1 2019/...
#ccc_m7
Bi-temporalを深掘り
こんな複雑な仕組みを
SQLで実装するのは面倒・・・
→ Reladomoで解決!
#ccc_m7
Reladomoのプロダクト適用例
• Duolingo
• Duolingo社の語学学習サービス
• 英語以外も充実
• ハイ・ヴァリリア語も学べる
• リスニング、リーディング、ライティング
• ソーシャル機能
• ノルマ&...
#ccc_m7
Reladomoのプロダクト適用例
• Study up!
• 個人プロダクト
• AWS ソリューションアーキテクト
アソシエイトの次、
プロフェッショナルを勉強するには?
• 書籍がない・・・
• じゃぁ、自分で学習用のサイ...
#ccc_m7
Reladomoのプロダクト適用例
• Demo
#ccc_m7
Reladomoのプロダクト適用例
• Reladomoの適用箇所
• 回答結果の履歴を保持 →
• 最新の正解率 →
• 過去5回の平均正解率 →
• 過去10回の平均正解率 →
※ 正解率 ・・・ 10問の初回回答結果から算...
#ccc_m7
Reladomoのプロダクション適用例
• Study up! on AWS
#ccc_m7
Reladomoのプロダクション適用例
• Study up! on AWS
ちと高い(お値段)
#ccc_m7
Reladomoのプロダクション適用例
• Study up! on AWS
#ccc_m7
Reladomoの実装例
• XMLでテーブル定義
• ビルドプロセスでDDL生成
• ビルドプロセスでコード生成
• 開発のフロー
• ConnectionManagerの作成
• CRUD操作の例
• リレーションの定義
•...
#ccc_m7
Reladomoの実装例
• XMLでテーブル定義 – テーブル名・クラス名定義
user.xml
<MithraObject objectType=“transactional” xmlns:xsi="http://www.w...
#ccc_m7
Reladomoの実装例
• XMLでテーブル定義 – カラム定義
user.xml
<MithraObject objectType=“transactional” xmlns:xsi="http://www.w3.org/2...
#ccc_m7
Reladomoの実装例
• XMLでテーブル定義 – カラム定義
user.xml
<MithraObject objectType=“transactional” xmlns:xsi="http://www.w3.org/2...
#ccc_m7
Reladomoの実装例
• XMLでテーブル定義 – Bi-temporal
user.xml
<MithraObject objectType="transactional" xmlns:xsi="http://www.w3...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
pom.xmlの抜粋
<configuration>
<tasks>
<property name="plugin_classpath" refid="maven.plu...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
MithraClassList.xml
<Mithra xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
pom.xmlの抜粋
<configuration>
<tasks>
<property name="plugin_classpath" refid="maven.plu...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
pom.xmlの抜粋
<configuration>
<tasks>
<property name="plugin_classpath" refid="maven.plu...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
• AWS RDSの t2.micro(1CPU 1GiBmem) の料金比較
• AWS RDSの t2.2xlarge(8CPU 32GiBmem) の料金比較
RD...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
• AWS RDSの t2.micro(1CPU 1GiBmem) の料金比較
• AWS RDSの t2.2xlarge(8CPU 32GiBmem) の料金比較
My...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでDDL生成
• create table、PK、外部キーが生成される
create table user (
user_id bigint not null, ← PK
name v...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
pom.xmlの抜粋
<configuration>
<tasks>
<property name="plugin_classpath" refid="maven.plu...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• ビルドプロセスでコード生成
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
User Use...
#ccc_m7
Reladomoの実装例
• 開発のフロー
user.xml
user.ddl
…etc
User.java
…etc
DB
View
Procedure
…etc
可視化
#ccc_m7
Reladomoの実装例
• 開発のフロー
user.xml
user.ddl
…etc
User.java
…etc
DB
View
Procedure
…etc
設計者がXMLを
編集するの?
DBからリバースして
生成して...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – クラス作成
public class ConnectionManager implements SourcelessConnectionManager ...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – クラス作成
public class ConnectionManager implements SourcelessConnectionManager ...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – クラス作成
public class ConnectionManager implements SourcelessConnectionManager ...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – クラス作成
public class ConnectionManager implements SourcelessConnectionManager ...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – XML作成
MithraRuntimeConfig.xml
<MithraRuntime>
<ConnectionManager className="...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – XML作成
MithraRuntimeConfig.xml
<MithraRuntime>
<ConnectionManager className="...
#ccc_m7
Reladomoの実装例
• ConnectionManagerの作成 – アプリ起動時にXML読込
try (InputStream is = ReladomoInitializer.class.getClassLoader(...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
}...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – C(insert)
User user =
MithraManagerProvider.getMithraManager().executeTransactionalComma...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – R(select)
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – R(select)
Operation id = UserFinder.userId().eq(1);
Operation bz = UserFinder.businessDa...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – R(select)
Operation id = UserFinder.userId().eq(1);
Operation bz = UserFinder.businessDa...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – R(select)
Operation id = UserFinder.userId().eq(1);
Operation bz = UserFinder.businessDa...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – R(select)
Operation id = UserFinder.userId().eq(1);
Operation bz = UserFinder.businessDa...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – R(select)
Operation id = UserFinder.userId().eq(1);
Operation bz = UserFinder.businessDa...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – U(update)
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – U(update)
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
O...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – U(update)
ユーザーID 名前 住所 from_z thru_z in_z out_z
1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 ...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – D(delete)
user.xml
UserAbstract UserDatabaseObjectAbstract
UserFinder
UserListAbstract
U...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – D(delete)
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
O...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – D(delete)
ユーザーID 名前 住所 from_z thru_z in_z out_z
1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 ...
#ccc_m7
Reladomoの実装例
• CRUD操作の例 – D(delete)
↓
update user_Bi-temporal set out_z = '2019-06-01'
where user_id = 1 AND thru_...
#ccc_m7
Reladomoの実装例
• リレーションの定義
• Study up!の例
問題マスター
(QuestionMaster)
問題
(Question)
1 多
・EC2の基本 ・EC2は何の略?
・AMIで選択できるOSイメー...
#ccc_m7
Reladomoの実装例
• リレーションの定義
QuestionMaster.xml
<Attribute name=“questionMasterId” javaType="int“
columnName="question...
#ccc_m7
Reladomoの実装例
• リレーションの定義
QuestionMaster Question
+ getQuestions() : QuestionList
Operation operation = QuestionMas...
#ccc_m7
Reladomoの実装例
• リレーションの定義
問題マスターを全件読み、問題文を出力
Operation operation = QuestionMasterFinder.all();
QuestionMasterList l...
#ccc_m7
Reladomoの実装例
• リレーションの定義
問題マスターを全件読み、問題文を出力
Operation operation = QuestionMasterFinder.all();
QuestionMasterList l...
#ccc_m7
Reladomoの実装例
• リレーションの定義
問題マスターを全件読み、問題文を出力
Operation operation = QuestionMasterFinder.all();
QuestionMasterList l...
#ccc_m7
Reladomoの実装例
• リレーションの定義
問題マスターを全件読み、問題文を出力
Operation operation = QuestionMasterFinder.all();
QuestionMasterList l...
#ccc_m7
Reladomoの実装例
• リレーションの定義
問題マスターを全件読み、問題文を出力
Operation operation = QuestionMasterFinder.all();
QuestionMasterList l...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• H2データベース(on memory)でテスト
• テスト用ConnectionManagerを作成
• テストデータファイルでデータ投入
#ccc_m7
Reladomoの実装例
• ユニットテスト
• H2データベース(on memory)でテスト
• テスト用ConnectionManagerを作成
• テストデータファイルでデータ投入
プロダクションと
同じデータベースを使...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テスト用ConnectionManagerを作成
private MithraTestResource testResource;
@Before
public void set...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テスト用ConnectionManagerを作成
MithraRuntimeConfig_test.xml
<MithraRuntime>
<ConnectionManager ...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テスト用ConnectionManagerを作成
MithraRuntimeConfig_test.xml
<MithraRuntime>
<ConnectionManager ...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テストデータファイルでデータ投入
private MithraTestResource testResource;
@Before
public void setup() thr...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テストデータファイルでデータ投入
test_data.txt
class some.package.User
userId, name, address, businessDat...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テストデータファイルでデータ投入
test_data.txt
class some.package.User
userId, name, address, businessDat...
#ccc_m7
Reladomoの実装例
• ユニットテスト
• テストデータファイルでデータ投入
private MithraTestResource testResource;
@After
public void tearDown() t...
#ccc_m7
Reladomoの実装例
• プライマリキー生成戦略
• Max
• Sequence
#ccc_m7
Reladomoの実装例
• プライマリキー生成戦略
user.xml
<MithraObject objectType="transactional" xmlns:xsi="http://www.w3.org/2001/XML...
#ccc_m7
Reladomoの実装例
• プライマリキー生成戦略
user.xml
<MithraObject objectType="transactional" xmlns:xsi="http://www.w3.org/2001/XML...
#ccc_m7
Reladomoの実装例
• キャッシュ戦略
• データをキャッシュしてデータベースアクセスを最小に
• エンティティ単位にキャッシュ方法を指定可能
MithraRuntimeConfig.xml
<MithraRuntime>...
#ccc_m7
Reladomoの実装例
• キャッシュ戦略
• partial
• 一度検索したものはメモリにキャッシュする
• full
• 起動時にメモリにキャッシュする
#ccc_m7
Reladomoの実装例
• キャッシュ戦略
• partial
• 一度検索したものはメモリにキャッシュする
• full
• 起動時にメモリにキャッシュする
システム稼働中に
SQLでデータベースを直接更新したら
キャッシュ...
#ccc_m7
Reladomoの実装例
• キャッシュ戦略
• partial
• 一度検索したものはメモリにキャッシュする
• full
• 起動時にメモリにキャッシュする
システム稼働中に
SQLでデータベースを直接更新したら
キャッシュ...
#ccc_m7
Reladomoの実装例
• Auto Scale(クラスタリング)対策
• Reladomo Notification
Reladomoが動作するJVM間で通知し、キャッシュなど情報を共有
#ccc_m7
Reladomoの実装例
• Auto Scale(クラスタリング)対策
• Reladomo Notification
Reladomoが動作するJVM間で通知し、キャッシュなど情報を共有
ひとつのEC2でしか動かしていないの...
#ccc_m7
メリット / デメリット / 課題
• メリット
• Bi-temporalなデータを扱うなら唯一の選択
• SQLを書かなくてOK
• デメリット
• MySQL非対応
• SQLを書けない
• Reladomoを前提としたテ...
#ccc_m7
まとめ
• データの履歴管理をするならReladomo一択
• 自分でSQLを書きたいならDomaかMyBatis
• 既存のシステムに導入するには難あり
• (あたりまえだが)公式ドキュメントは熟読しよう
• 非公式ドキュメン...
Upcoming SlideShare
Loading in …5
×

Reladomoを使ったトランザクション履歴管理をプロダクトに適用した際のメリット/デメリット/課題など

155 views

Published on

Reladomo の適用に際して感じたメリット/デメリット、実際に直面した課題など

Published in: Engineering
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Reladomoを使ったトランザクション履歴管理をプロダクトに適用した際のメリット/デメリット/課題など

  1. 1. Reladomoを使った トランザクション履歴管理を プロダクトに適用した際の メリット/デメリット/課題など JJUG CCC 2019 Spring #jjug_ccc #ccc_m7 2019-05-18 株式会社オープントーン 渡邉 一夫
  2. 2. #ccc_m7 自己紹介 • 名前:渡邉 一夫 ( Twitter → @nave_kazu ) • エンジニア歴:20年 • 所属:株式会社オープントーン • 秋葉原 • 勤怠管理システム • 観光ビッグデータ • ヘルス・メディテック • AWSのAPNパートナー • エンジニア募集中!
  3. 3. #ccc_m7 自己紹介 • 名前:渡邉 一夫 ( Twitter → @nave_kazu ) • Java歴:20年弱 • MS Visual J++ 6.0でアプレットを作ったのが初めてのJava • 独習Javaで言語仕様やJava SEのAPIを理解 • SJC-P と SJC-WCを取得
  4. 4. #ccc_m7 自己紹介 • 名前:渡邉 一夫 ( Twitter → @nave_kazu ) • Java歴:20年弱 • 今はDB設計してSpring BootでWeb APIを書いたり、 AngularやVue.jsでクライアントを書いたり、 AWSでインフラ構築したり、、、フルスタックエンジニア • JJUG CCCは2014年ごろから参加 • JJUG CCC 2018 Fallで登壇 • SQL実行ツールを作るのがライフワーク
  5. 5. #ccc_m7 自己紹介 • 名前:渡邉 一夫 ( Twitter → @nave_kazu ) • その他 • 共著 システム開発のための見積りのすべてがわかる本 • AWS 認定ソリューションアーキテクト–アソシエイト取得
  6. 6. #ccc_m7 自己紹介 • HEAVY ROTATION → BAND-MAID
  7. 7. #ccc_m7 自己紹介 • HEAVY ROTATION → BAND-MAID メイド喫茶のノリをバンドでやってみた 5ピースガールズバンド コスチューム → メイド服 ライブ → お給仕 ライブ参加 → ご帰宅 ファン → ご主人様・お嬢様 ライブMC 「おかえりなさいませご主人様お嬢様」
  8. 8. #ccc_m7 自己紹介 • HEAVY ROTATION → BAND-MAID メイド喫茶のノリをバンドでやってみた 5ピースガールズバンド コスチューム → メイド服 ライブ → お給仕 ライブ参加 → ご帰宅 ファン → ご主人様・お嬢様 ライブMC 「おかえりなさいませご主人様お嬢様」 ゴリッゴリのハードロック
  9. 9. #ccc_m7 アジェンダ • Reladomoとは? • 履歴管理のいろいろ • Reladomoのプロダクト適用例 • Reladomoの実装例
  10. 10. #ccc_m7 Reladomoとは? • ゴールドマン・サックスが開発するORM • XMLでテーブル定義をしDDL・エンティティ自動生成 • 履歴管理(バイテンポラル)に特化している • 型付けされたクエリー言語(SQLは書かない) • etc
  11. 11. #ccc_m7 履歴管理いろいろ(Chaining) • 履歴管理なし (Snapshot) • 「今」しか扱わない • 営業時間のみ (Business-Only) • 業務上の意味のある時間(Business date)を管理する • 処理時間のみ (Audit-Only) • システムへの反映時間(Processing date)を管理する • 営業時間・処理時間両方 (Bi-temporal) • 営業時間と処理時間の両方を管理する
  12. 12. #ccc_m7 履歴管理いろいろ(Chaining) • シナリオ (ユーザー管理) • 「小鳩ミク」さんを登録する • 利用開始は4月1日から (Business date) • 登録は3月25日に行う(Processing date) • 住所変更する • 5月1日に住所変更したい(Business date) • 申請は5月3日にあった(Processing date) • 住所変更の訂正をする • 誤りを5月4日に訂正したい (Processing date) • 利用停止する • 申請が5月31日にあった(Business / Processing date) • 即日停止としたい
  13. 13. #ccc_m7 履歴管理いろいろ(Chaining) • 履歴管理なし (Snapshot) • 「小鳩ミク」さんを登録する • 利用開始は4月1日から (Business date) • 登録は3月25日に行う(Processing date) ユーザーID 名前 住所 1 小鳩ミク 東京都 登録した時点でシステムに反映
  14. 14. #ccc_m7 履歴管理いろいろ(Chaining) • 履歴管理なし (Snapshot) • 「小鳩ミク」さんを登録する • 利用開始は4月1日から (Business date)← 表現できない! • 登録は3月25日に行う(Processing date) ← 表現できない! ユーザーID 名前 住所 1 小鳩ミク 東京都 登録した時点でシステムに反映
  15. 15. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間のみ (Business-Only) • 「小鳩ミク」さんを登録する • 利用開始は4月1日から (Business date) • 登録は3月25日に行う(Processing date)← 表現できない! ユーザーID 名前 住所 from_z thru_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 利用開始日を「from_z」で表現 利用終了日を「thru_z」で表現 開始日はBusiness date、終了日はINFINITY(無限)とする INFINITY はPostgreSQLの場合 9999/12/1 23:59:00.000
  16. 16. #ccc_m7 履歴管理いろいろ(Chaining) • 処理時間のみ (Audit-Only) • 「小鳩ミク」さんを登録する • 利用開始は4月1日から (Business date)← 表現できない! • 登録は3月25日に行う(Processing date) システム有効開始日を「in_z」で表現 システム有効終了日を「out_z」で表現 開始日はProcessing date、終了日はINFINITY(無限)とする ユーザーID 名前 住所 in_z out_z 1 小鳩ミク 東京都 2019/3/25 9999/12/1
  17. 17. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間・処理時間両方 (Bi-temporal) • 「小鳩ミク」さんを登録する • 利用開始は4月1日から (Business date) • 登録は3月25日に行う(Processing date) ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 9999/12/1 営業時間のみ (Business-Only)で使った「from_z」と「thru_z」、 処理時間のみ (Audit-Only)で使った「in_z」と「out_z」の両方を使うことで 利用開始日と登録があった日の両方を表現できる
  18. 18. #ccc_m7 履歴管理いろいろ(Chaining) • 履歴管理なし(Snapshot) • 住所変更する • 5月1日に住所変更したい(Business date) ← 表現できない! • 申請は5月3日にあった(Processing date) ← 表現できない! ユーザーID 名前 住所 1 小鳩ミク 埼玉県 変更した時点でシステムに反映
  19. 19. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間のみ (Business-Only) • 住所変更する • 5月1日に住所変更したい(Business date) • 申請は5月3日にあった(Processing date) ← 表現できない! ユーザーID 名前 住所 from_z thru_z 1 小鳩ミク 東京都 2019/4/1 2019/5/1 1 小鳩ミク 埼玉県 2019/5/1 9999/12/1 東京都の時の利用終了日を「2019/5/1」に更新 埼玉県のレコードを追加し、利用開始日を「2019/5/1」とする 埼玉県の利用終了日をINFINITY「9999/12/1」とする 最新の情報が欲しい場合はthru_zがINFINITYのものを検索する
  20. 20. #ccc_m7 履歴管理いろいろ(Chaining) • 処理時間のみ (Audit-Only) • 住所変更する • 5月1日に住所変更したい(Business date) ← 表現できない! • 申請は5月3日にあった(Processing date) 東京都の時のシステム有効終了日を「2019/5/3」に更新 埼玉県のレコードを追加し、システム有効開始日を「2019/5/3」とする 埼玉県のシステム有効終了日をINFINITY「9999/12/1」とする 最新の情報が欲しい場合はout_zがINFINITYのものを検索する ユーザーID 名前 住所 in_z out_z 1 小鳩ミク 東京都 2019/3/25 2019/5/3 1 小鳩ミク 埼玉県 2019/5/3 9999/12/1
  21. 21. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間・処理時間両方 (Bi-temporal) • 住所変更する • 5月1日に住所変更したい(Business date) • 申請は5月3日にあった(Processing date) ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 1 小鳩ミク 埼玉県 2019/5/1 9999/12/1 2019/5/3 9999/12/1 5/3までの情報として初期データのシステム終了日を「2019/5/3」に更新して締める 5/3からの情報として、東京都と埼玉県のレコードを作成する 東京都の利用開始日と終了日をそれぞれ「2019/4/1」と「2019/5/1」にする 埼玉県の利用開始日と終了日とそれぞれ「2019/5/1」とINFINITYにする なぜこんな複雑な更新を? → 後ほど説明
  22. 22. #ccc_m7 履歴管理いろいろ(Chaining) • 履歴管理なし(Snapshot) • 住所変更の訂正をする • 誤りを5月4日に訂正したい (Processing date) ← 表現できない! ユーザーID 名前 住所 1 小鳩ミク 神奈川県 変更した時点でシステムに反映
  23. 23. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間のみ (Business-Only) • 住所変更の訂正をする • 誤りを5月4日に訂正したい (Processing date) ← 表現できない! ユーザーID 名前 住所 from_z thru_z 1 小鳩ミク 東京都 2019/4/1 2019/5/1 1 小鳩ミク 神奈川県 2019/5/1 9999/12/1 利用開始日・終了日に変更がないので、「埼玉県」を「神奈川県」に更新して終了 誤りがあったことはなかったことにする
  24. 24. #ccc_m7 履歴管理いろいろ(Chaining) • 処理時間のみ (Audit-Only) • 住所変更の訂正をする • 誤りを5月4日に訂正したい (Processing date) 監査(Audit)が目的なので、 変更前の「埼玉県」のシステム有効終了日を「2019/5/4」に更新 神奈川県のレコードを追加し、システム有効開始日を「2019/5/4」、 システム有効終了日をINFINITY「9999/12/1」とする ユーザーID 名前 住所 in_z out_z 1 小鳩ミク 東京都 2019/3/25 2019/5/3 1 小鳩ミク 埼玉県 2019/5/3 2019/5/4 1 小鳩ミク 神奈川県 2019/5/4 9999/12/1
  25. 25. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間・処理時間両方 (Bi-temporal) • 住所変更の訂正をする • 誤りを5月4日に訂正したい (Processing date) ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 1 小鳩ミク 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 1 小鳩ミク 神奈川県 2019/5/1 9999/12/1 2019/5/4 9999/12/1 5/4までの情報として、埼玉県のシステム終了日を「2019/5/4」に更新して締める 5/4からの情報として、神奈川県のレコードを作成する 神奈川県の利用開始日と終了日とそれぞれ「2019/5/1」とINFINITYにする
  26. 26. #ccc_m7 履歴管理いろいろ(Chaining) • 履歴管理なし(Snapshot) • 利用停止する • 申請が5月31日にあった(Business / Processing date)← 表現できない! • 即日停止としたい ユーザーID 名前 住所 変更した時点でシステムに反映 利用停止を、どう表現する? 物理削除?ステータス管理?論理削除?
  27. 27. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間のみ (Business-Only) • 利用停止する • 申請が5月31日にあった(Business / Processing date) • 即日停止としたい ユーザーID 名前 住所 from_z thru_z 1 小鳩ミク 東京都 2019/4/1 2019/5/1 1 小鳩ミク 神奈川県 2019/5/1 2019/6/1 神奈川県の利用終了日を「2019/6/1」とする
  28. 28. #ccc_m7 履歴管理いろいろ(Chaining) • 処理時間のみ (Audit-Only) • 利用停止する • 申請が5月31日にあった(Business / Processing date) • 即日停止としたい 神奈川県のシステム有効終了日を「2019/6/1」とする ユーザーID 名前 住所 in_z out_z 1 小鳩ミク 東京都 2019/3/25 2019/5/3 1 小鳩ミク 埼玉県 2019/5/3 2019/5/4 1 小鳩ミク 神奈川県 2019/5/4 2019/6/1
  29. 29. #ccc_m7 履歴管理いろいろ(Chaining) • 営業時間・処理時間両方 (Bi-temporal) • 利用停止する • 申請が5月31日にあった(Business / Processing date) • 即日停止としたい ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 1 小鳩ミク 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 1 小鳩ミク 神奈川県 2019/5/1 9999/12/1 2019/5/4 2019/6/1 1 小鳩ミク 神奈川県 2019/5/1 2019/6/1 2019/6/1 9999/12/1 元々の神奈川県のシステム終了日を「2019/6/1」に更新して締める 6/1からの情報として、神奈川県のレコードを作成する 新しい神奈川県の利用開始日と終了日とそれぞれ「2019/5/1」と「2019/6/1」にする
  30. 30. #ccc_m7 Bi-temporalを深掘り 住所 from_z thru_z in_z out_z Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z)
  31. 31. #ccc_m7 Bi-temporalを深掘り • 「小鳩ミク」さんを登録する 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 9999/12/1 A Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) A
  32. 32. #ccc_m7 Bi-temporalを深掘り • 住所変更する 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A Inf 6/1 5/3 5/1 4/1 3/25 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) BusinessTime(from_z/thru_z) A システム終了日を「2019/5/3」に更新して締める
  33. 33. #ccc_m7 Bi-temporalを深掘り • 住所変更する 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 9999/12/1 C Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) システム開始日「2019/5/3」の新たなレコードを追加 B C 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) A
  34. 34. #ccc_m7 Bi-temporalを深掘り • 住所変更の訂正をする 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) 訂正対象のシステム終了日を 「2019/5/4」に更新して締める 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) B C A
  35. 35. #ccc_m7 Bi-temporalを深掘り • 住所変更の訂正をする 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C 神奈川県 2019/5/1 9999/12/1 2019/5/4 9999/12/1 D Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) 訂正後のレコードを追加する D 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) B C A
  36. 36. #ccc_m7 Bi-temporalを深掘り • 利用停止する 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C 神奈川県 2019/5/1 9999/12/1 2019/5/4 2019/6/1 D Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) 最新行のシステム終了日を 「2019/6/1」に更新して締める 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A
  37. 37. #ccc_m7 Bi-temporalを深掘り • 利用停止する 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C 神奈川県 2019/5/1 9999/12/1 2019/5/4 2019/6/1 D 神奈川県 2019/5/1 2019/6/1 2019/6/1 9999/12/1 E Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) 利用停止のレコードを追加 E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A
  38. 38. #ccc_m7 Bi-temporalを深掘り • 4月中旬の状態 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C 神奈川県 2019/5/1 9999/12/1 2019/5/4 2019/6/1 D 神奈川県 2019/5/1 2019/6/1 2019/6/1 9999/12/1 E Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) SELECT * FROM USER WHERE in_z <= ‘2019-04-15’ AND out_z > ‘2019-04-15’ E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A
  39. 39. #ccc_m7 Bi-temporalを深掘り • 5月中旬の状態 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C 神奈川県 2019/5/1 9999/12/1 2019/5/4 2019/6/1 D 神奈川県 2019/5/1 2019/6/1 2019/6/1 9999/12/1 E Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A SELECT * FROM USER WHERE in_z <= ‘2019-05-15’ AND out_z > ‘2019-05-15’
  40. 40. #ccc_m7 Bi-temporalを深掘り • 最新の状態 住所 from_z thru_z in_z out_z 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 A 東京都 2019/4/1 2019/5/1 2019/5/3 9999/12/1 B 埼玉県 2019/5/1 9999/12/1 2019/5/3 2019/5/4 C 神奈川県 2019/5/1 9999/12/1 2019/5/4 2019/6/1 D 神奈川県 2019/5/1 2019/6/1 2019/6/1 9999/12/1 E Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A SELECT * FROM USER WHERE out_z = ‘9999-12-01’
  41. 41. #ccc_m7 Bi-temporalを深掘り こんな複雑な仕組みを SQLで実装するのは面倒・・・ → Reladomoで解決!
  42. 42. #ccc_m7 Reladomoのプロダクト適用例 • Duolingo • Duolingo社の語学学習サービス • 英語以外も充実 • ハイ・ヴァリリア語も学べる • リスニング、リーディング、ライティング • ソーシャル機能 • ノルマ&報酬制度 • 1レッスン10問で全問正解まで終わらない → 終わりま10 • 終わりま10を語学以外の学習に使いたい
  43. 43. #ccc_m7 Reladomoのプロダクト適用例 • Study up! • 個人プロダクト • AWS ソリューションアーキテクト アソシエイトの次、 プロフェッショナルを勉強するには? • 書籍がない・・・ • じゃぁ、自分で学習用のサイトを作ろう! • https://studyup.info/ • (今のところ)無料
  44. 44. #ccc_m7 Reladomoのプロダクト適用例 • Demo
  45. 45. #ccc_m7 Reladomoのプロダクト適用例 • Reladomoの適用箇所 • 回答結果の履歴を保持 → • 最新の正解率 → • 過去5回の平均正解率 → • 過去10回の平均正解率 → ※ 正解率 ・・・ 10問の初回回答結果から算出 → 10問中8問正解=80%
  46. 46. #ccc_m7 Reladomoのプロダクション適用例 • Study up! on AWS
  47. 47. #ccc_m7 Reladomoのプロダクション適用例 • Study up! on AWS ちと高い(お値段)
  48. 48. #ccc_m7 Reladomoのプロダクション適用例 • Study up! on AWS
  49. 49. #ccc_m7 Reladomoの実装例 • XMLでテーブル定義 • ビルドプロセスでDDL生成 • ビルドプロセスでコード生成 • 開発のフロー • ConnectionManagerの作成 • CRUD操作の例 • リレーションの定義 • ユニットテスト • プライマリキー生成戦略 • キャッシュ戦略 • Auto Scale(クラスタリング)対策
  50. 50. #ccc_m7 Reladomoの実装例 • XMLでテーブル定義 – テーブル名・クラス名定義 user.xml <MithraObject objectType=“transactional” xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <PackageName>some.package</PackageName> <ClassName>User</ClassName> <DefaultTable>USER</DefaultTable> </MithraObject> パッケージ名、 エンティティクラス名、 テーブル名
  51. 51. #ccc_m7 Reladomoの実装例 • XMLでテーブル定義 – カラム定義 user.xml <MithraObject objectType=“transactional” xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <PackageName>some.package</PackageName> <ClassName>User</ClassName> <DefaultTable>USER</DefaultTable> <Attribute name="userId" javaType="long" columnName="user_id" nullable="false“ primaryKey="true"/> <Attribute name=“name” javaType="String" columnName="name" nullable="false" maxLength="100"/> <Attribute name="address" javaType="String" columnName="address" nullable="false" maxLength="100"/> </MithraObject> カラムリスト
  52. 52. #ccc_m7 Reladomoの実装例 • XMLでテーブル定義 – カラム定義 user.xml <MithraObject objectType=“transactional” xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <PackageName>some.package</PackageName> <ClassName>User</ClassName> <DefaultTable>USER</DefaultTable> <Attribute name="userId" javaType="long" columnName="user_id" nullable="false“ primaryKey="true"/> <Attribute name=“name” javaType="String" columnName="name" nullable="false" maxLength="100"/> <Attribute name="address" javaType="String" columnName="address" nullable="false" maxLength="100"/> </MithraObject> カラムコメント(日本語カラム名) 入れたいな・・・ カラムリスト
  53. 53. #ccc_m7 Reladomoの実装例 • XMLでテーブル定義 – Bi-temporal user.xml <MithraObject objectType="transactional" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <PackageName>some.package</PackageName> <ClassName>User</ClassName> <DefaultTable>USER</DefaultTable> <AsOfAttribute name="businessDate" fromColumnName="from_z" toColumnName="thru_z" toIsInclusive="false" isProcessingDate="false" infinityDate=“[(中略)DefaultInfinityTimestamp.getDefaultInfinity()]" futureExpiringRowsExist="true" /> <AsOfAttribute name="processingDate" fromColumnName="in_z" toColumnName="out_z" toIsInclusive=“false” isProcessingDate="true" infinityDate="[(中略)DefaultInfinityTimestamp.getDefaultInfinity()]" defaultIfNotSpecified="[(中略)DefaultInfinityTimestamp.getDefaultInfinity()]" /> <Attribute name="userId" javaType="long" columnName="user_id" nullable="false“ primaryKey="true"/> <Attribute name=“name” javaType="String" columnName="name" nullable="false" maxLength="100"/> <Attribute name="address" javaType="String" columnName="address" nullable="false" maxLength="100"/> </MithraObject> Bi-temporal (営業時間、処理時間)
  54. 54. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 pom.xmlの抜粋 <configuration> <tasks> <property name="plugin_classpath" refid="maven.plugin.classpath"/> <taskdef name="gen-reladomo-db" classpath="plugin_classpath" classname=“(中略)MithraDbDefinitionGenerator"/> <gen-reladomo-db xml="${project.basedir}/src/main/reladomoxml/MithraClassList.xml" generatedDir="${project.build.directory}/generated-resources/db" databaseType="postgres"/> </tasks> </configuration>
  55. 55. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 MithraClassList.xml <Mithra xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <MithraObjectResource name="User"/> ・・・・ </Mithra> 生成対象の エンティティを指定
  56. 56. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 pom.xmlの抜粋 <configuration> <tasks> <property name="plugin_classpath" refid="maven.plugin.classpath"/> <taskdef name="gen-reladomo-db" classpath="plugin_classpath" classname=“(中略)MithraDbDefinitionGenerator"/> <gen-reladomo-db xml="${project.basedir}/src/main/reladomoxml/MithraClassList.xml" generatedDir="${project.build.directory}/generated-resources/db" databaseType="postgres"/> </tasks> </configuration> sybase udb82 mssql postgres oracle
  57. 57. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 pom.xmlの抜粋 <configuration> <tasks> <property name="plugin_classpath" refid="maven.plugin.classpath"/> <taskdef name="gen-reladomo-db" classpath="plugin_classpath" classname=“(中略)MithraDbDefinitionGenerator"/> <gen-reladomo-db xml="${project.basedir}/src/main/reladomoxml/MithraClassList.xml" generatedDir="${project.build.directory}/generated-resources/db" databaseType="postgres"/> </tasks> </configuration> sybase udb82 mssql postgres oracle MySQL ない! MariaDB ない! Amazon Aurora ない!
  58. 58. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 • AWS RDSの t2.micro(1CPU 1GiBmem) の料金比較 • AWS RDSの t2.2xlarge(8CPU 32GiBmem) の料金比較 RDS hour (USD) month (USD) month (JPY) Oracle 0.044 31.68 3,516.48 PostgreSQL 0.028 20.16 2,237.76 MySQL 0.026 18.72 2,077.92 RDS hour (USD) month (USD) month (JPY) Oracle 1.6448 1,184.256 131,452.416 PostgreSQL 0.8960 645.12 71,608.32 MySQL 0.8360 601.92 66,813.12 ※ストレージ料金除く
  59. 59. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 • AWS RDSの t2.micro(1CPU 1GiBmem) の料金比較 • AWS RDSの t2.2xlarge(8CPU 32GiBmem) の料金比較 MySQL ないのは つらい RDS hour (USD) month (USD) month (JPY) Oracle 0.044 31.68 3,516.48 PostgreSQL 0.028 20.16 2,237.76 MySQL 0.026 18.72 2,077.92 RDS hour (USD) month (USD) month (JPY) Oracle 1.6448 1,184.256 131,452.416 PostgreSQL 0.8960 645.12 71,608.32 MySQL 0.8360 601.92 66,813.12 ※ストレージ料金除く
  60. 60. #ccc_m7 Reladomoの実装例 • ビルドプロセスでDDL生成 • create table、PK、外部キーが生成される create table user ( user_id bigint not null, ← PK name varchar(100) not null, address varchar(100) not null, from_z timestamp not null, thru_z timestamp not null, ← PK in_z timestamp not null, out_z timestamp not null ← PK ); alter table user add constraint user_pk primary key (user_id, thru_z, out_z);
  61. 61. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 pom.xmlの抜粋 <configuration> <tasks> <property name="plugin_classpath" refid="maven.plugin.classpath"/> <taskdef name="gen-reladomo" classpath="plugin_classpath" classname="com.gs.fw.common.mithra.generator.MithraGenerator"/> <gen-reladomo xml="${project.basedir}/src/main/reladomoxml/MithraClassList.xml" generateGscListMethod="true" generatedDir="${project.build.directory}/generated-sources/reladomo" nonGeneratedDir="${project.basedir}/src/main/java" /> </tasks> </configuration>
  62. 62. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList
  63. 63. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList 検索に用いる
  64. 64. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList 1レコードを表現
  65. 65. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList 複数行検索に用いる
  66. 66. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList テーブル情報取得用
  67. 67. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList 抽象クラス・Finderはビルド時に毎回生成
  68. 68. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList 具象クラスは一度だけ生成
  69. 69. #ccc_m7 Reladomoの実装例 • ビルドプロセスでコード生成 user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList 具象クラスは一度だけ生成 たとえば firstName + lastNameから getFullName()メソッドを定義
  70. 70. #ccc_m7 Reladomoの実装例 • 開発のフロー user.xml user.ddl …etc User.java …etc DB View Procedure …etc 可視化
  71. 71. #ccc_m7 Reladomoの実装例 • 開発のフロー user.xml user.ddl …etc User.java …etc DB View Procedure …etc 設計者がXMLを 編集するの? DBからリバースして 生成してくれないの? 可視化
  72. 72. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – クラス作成 public class ConnectionManager implements SourcelessConnectionManager { private XAConnectionManager createConnectionManager() { xaConnectionManager = new XAConnectionManager(); xaConnectionManager.setDriverClassName(“org.postgresql.Driver”); xaConnectionManager.setJdbcConnectionString(“jdbc:postgresql://xxx.rds.amazonaws.com:5432/xxx”); xaConnectionManager.setJdbcUser(“xxxxx”); xaConnectionManager.setJdbcPassword(“xxxxx”); (中略) return xaConnectionManager; } @Override public DatabaseType getDatabaseType() { return PostgresDatabaseType.getInstance(); }
  73. 73. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – クラス作成 public class ConnectionManager implements SourcelessConnectionManager { private XAConnectionManager createConnectionManager() { xaConnectionManager = new XAConnectionManager(); xaConnectionManager.setDriverClassName(“org.postgresql.Driver”); xaConnectionManager.setJdbcConnectionString(“jdbc:postgresql://xxx.rds.amazonaws.com:5432/xxx”); xaConnectionManager.setJdbcUser(“xxxxx”); xaConnectionManager.setJdbcPassword(“xxxxx”); (中略) return xaConnectionManager; } @Override public DatabaseType getDatabaseType() { return PostgresDatabaseType.getInstance(); } お約束のドライバークラス、 接続文字列、ユーザー名、 パスワード
  74. 74. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – クラス作成 public class ConnectionManager implements SourcelessConnectionManager { private XAConnectionManager createConnectionManager() { xaConnectionManager = new XAConnectionManager(); xaConnectionManager.setDriverClassName(“org.postgresql.Driver”); xaConnectionManager.setJdbcConnectionString(“jdbc:postgresql://xxx.rds.amazonaws.com:5432/xxx”); xaConnectionManager.setJdbcUser(“xxxxx”); xaConnectionManager.setJdbcPassword(“xxxxx”); (中略) return xaConnectionManager; } @Override public DatabaseType getDatabaseType() { return PostgresDatabaseType.getInstance(); } 使用するRDBMSの指定
  75. 75. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – クラス作成 public class ConnectionManager implements SourcelessConnectionManager { private XAConnectionManager createConnectionManager() { xaConnectionManager = new XAConnectionManager(); xaConnectionManager.setDriverClassName(“org.postgresql.Driver”); xaConnectionManager.setJdbcConnectionString(“jdbc:postgresql://xxx.rds.amazonaws.com:5432/xxx”); xaConnectionManager.setJdbcUser(“xxxxx”); xaConnectionManager.setJdbcPassword(“xxxxx”); (中略) return xaConnectionManager; } @Override public DatabaseType getDatabaseType() { return PostgresDatabaseType.getInstance(); } 使用するRDBMSの指定 MySQL ないのは つらい
  76. 76. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – XML作成 MithraRuntimeConfig.xml <MithraRuntime> <ConnectionManager className="some.package.ConnectionManager"> <MithraObjectConfiguration cacheType="partial" className="some.package.User"/> ・・・ </ConnectionManager> </MithraRuntime> ConnectionManagerクラスと 使用するエンティティを列挙
  77. 77. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – XML作成 MithraRuntimeConfig.xml <MithraRuntime> <ConnectionManager className="some.package.ConnectionManager"> <MithraObjectConfiguration cacheType="partial" className="some.package.User"/> ・・・ </ConnectionManager> </MithraRuntime> キャッシュ戦略 ・・・後述
  78. 78. #ccc_m7 Reladomoの実装例 • ConnectionManagerの作成 – アプリ起動時にXML読込 try (InputStream is = ReladomoInitializer.class.getClassLoader() .getResourceAsStream(“MithraRuntimeConfig.xml”)) { MithraManagerProvider.getMithraManager().readConfiguration(is); (中略) }
  79. 79. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert)
  80. 80. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert) user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList
  81. 81. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert) MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { }); トランザクション宣言 ラムダ式内に実装
  82. 82. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert) MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { User user = new User(System.currentTimeMillis()); }); エンティティインスタンスを作成 同時に営業開始日時をセット
  83. 83. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert) MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { User user = new User(System.currentTimeMillis()); user.setUserId(1); user.setName("小鳩ミク"); user.setAddress("東京都"); }); 他の情報を設定
  84. 84. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert) MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { User user = new User(System.currentTimeMillis()); user.setUserId(1); user.setName("小鳩ミク"); user.setAddress("東京都"); user.insert(); return user; }); insertメソッドで挿入
  85. 85. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – C(insert) User user = MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { User user = new User(System.currentTimeMillis()); user.setUserId(1); user.setName("小鳩ミク"); user.setAddress("東京都"); user.insert(); return user; }); insert結果を返すことも可能
  86. 86. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – R(select) user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList
  87. 87. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – R(select) Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().equalsEdgePoint(); Operation pr = UserFinder.processingDate().equalsInfinity(); Finderを使って検索条件を作成
  88. 88. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – R(select) Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().equalsEdgePoint(); Operation pr = UserFinder.processingDate().equalsInfinity(); User user = UserFinder.findOne(id.and(bz).and(pr)); findOneメソッドで1件検索 select * from user where user_id = 1 and out_z = '9999-12-01 23:59:00.000' Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A
  89. 89. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – R(select) Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().equalsEdgePoint(); Operation pr = UserFinder.processingDate().equalsInfinity(); UserList userList = UserFinder.findMany(id.and(bz).and(pr)); findManyメソッドで複数件検索 Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A select * from user where user_id = 1 and out_z = '9999-12-01 23:59:00.000'
  90. 90. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – R(select) Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().equalsEdgePoint(); Operation pr = UserFinder.processingDate().eq(Timestamp.valueOf("2019-05-15")); UserList userList = UserFinder.findMany(id.and(bz).and(pr)); 過去を切り取る select * from user where user_id = 1 and in_z <= '2019-05-15 00:00:00.000' and out_z > '2019-05-15 00:00:00.000' Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A
  91. 91. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – R(select) Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().eq(Timestamp.valueOf("2019-05-20")); Operation pr = UserFinder.processingDate().equalsInfinity(); User user = UserFinder.findOne(id.and(bz).and(pr)); businessDateの指定も可能 Inf 6/1 5/3 5/1 4/1 3/25 BusinessTime(from_z/thru_z) E 3/25 4/1 5/1 3 4 6/1 Inf Processing Time (in_z/out_z) D B C A select * from user where user_id = 1 and from_z <= '2019-05-20 00:00:00.000' and thru_z > '2019-05-20 00:00:00.000‘ and out_z = '9999-12-01 23:59:00.000'
  92. 92. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – U(update) user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList
  93. 93. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – U(update) MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().equalsEdgePoint(); Operation pr = UserFinder.processingDate().equalsInfinity(); User user = UserFinder.findOne(id.and(bz).and(pr)); user.setAddress(“神奈川県"); return user; }); findOne/Manyで検索した後 セッターメソッドで値を更新 トランザクション終了時に updateを実行
  94. 94. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – U(update) ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 9999/12/1 ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/3 2019/5/3 9999/12/1 1 小鳩ミク 神奈川県 2019/5/3 9999/12/1 2019/5/3 9999/12/1 ↓ update user set out_z = '2019-05-03‘ where user_id = 1 AND thru_z = '9999-12-01' AND out_z = '9999-12-01’; insert into user (user_id,name,address,from_z,thru_z,in_z,out_z) values (1,'小鳩ミク','東京都','2019-04-01','2019-05-03','2019-05-03','9999-12-01’); insert into user (user_id,name,address,from_z,thru_z,in_z,out_z) values (1,‘小鳩ミク’,‘神奈川県','2019-05-03','9999-12-01','2019-05-03','9999-12-01’);
  95. 95. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – D(delete) user.xml UserAbstract UserDatabaseObjectAbstract UserFinder UserListAbstract User UserDatabaseObjectUserList
  96. 96. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – D(delete) MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> { Operation id = UserFinder.userId().eq(1); Operation bz = UserFinder.businessDate().equalsEdgePoint(); Operation pr = UserFinder.processingDate().equalsInfinity(); User user = UserFinder.findOne(id.and(bz).and(pr)); user.terminate(); return user; }); findOne/Manyで検索した後 terminate()で締める
  97. 97. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – D(delete) ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/3 2019/5/3 9999/12/1 1 小鳩ミク 神奈川県 2019/5/3 9999/12/1 2019/5/3 9999/12/1 ↓ ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/3 2019/5/3 9999/12/1 1 小鳩ミク 神奈川県 2019/5/3 9999/12/1 2019/5/3 2019/6/1 1 小鳩ミク 神奈川県 2019/5/3 2019/6/1 2019/6/1 9999/12/1
  98. 98. #ccc_m7 Reladomoの実装例 • CRUD操作の例 – D(delete) ↓ update user_Bi-temporal set out_z = '2019-06-01' where user_id = 1 AND thru_z = '9999-12-01' AND out_z = '9999-12-01'; insert into user_Bi-temporal(user_id,name,address,from_z,thru_z,in_z,out_z) values (1,'小鳩ミク','神奈川','2019-05-03','2019-06-01','2019-06-01','9999-12-01'); ユーザーID 名前 住所 from_z thru_z in_z out_z 1 小鳩ミク 東京都 2019/4/1 9999/12/1 2019/3/25 2019/5/3 1 小鳩ミク 東京都 2019/4/1 2019/5/3 2019/5/3 9999/12/1 1 小鳩ミク 神奈川県 2019/5/3 9999/12/1 2019/5/3 2019/6/1 1 小鳩ミク 神奈川県 2019/5/3 2019/6/1 2019/6/1 9999/12/1
  99. 99. #ccc_m7 Reladomoの実装例 • リレーションの定義 • Study up!の例 問題マスター (QuestionMaster) 問題 (Question) 1 多 ・EC2の基本 ・EC2は何の略? ・AMIで選択できるOSイメージは? ・大幅な割引を適用できる仕組みは? ・固定の外部IPアドレスを割り当てる 仕組みは? ※問題マスターのIDで関連する
  100. 100. #ccc_m7 Reladomoの実装例 • リレーションの定義 QuestionMaster.xml <Attribute name=“questionMasterId” javaType="int“ columnName="question_master_id"nullable="false" primaryKey="true"/> <Relationship cardinality="one-to-many" relatedObject="Question" name="questions"> this.questionMasterId = Question.questionMasterId </Relationship> Question.xml <Attribute name="questionId" javaType="int“ columnName=“question_id” nullable="false" primaryKey="true"/> <Attribute name="questionMasterId" javaType="int“ columnName="question_master_id" nullable="false"/>
  101. 101. #ccc_m7 Reladomoの実装例 • リレーションの定義 QuestionMaster Question + getQuestions() : QuestionList Operation operation = QuestionMasterFinder.questionMasterId().eq(1); QuestionMaster questionMaster = QuestionMasterFinder.findOne(operation); QuestionList list = questionMaster.getQuestions(); Question question = list.get(0); String contents = question.getContents(); + getContents() : String
  102. 102. #ccc_m7 Reladomoの実装例 • リレーションの定義 問題マスターを全件読み、問題文を出力 Operation operation = QuestionMasterFinder.all(); QuestionMasterList list = QuestionMasterFinder.findMany(operation); ① for (QuestionMaster master : list) { for (Question question : master.getQuestions()) { ② System.out.println("問題:" + question.getContents()); ・・・ ① select * from question_master ② select * from question where question_master_id = 1 select * from question where question_master_id = 2 select * from question where question_master_id = 3 ・・・
  103. 103. #ccc_m7 Reladomoの実装例 • リレーションの定義 問題マスターを全件読み、問題文を出力 Operation operation = QuestionMasterFinder.all(); QuestionMasterList list = QuestionMasterFinder.findMany(operation); ① for (QuestionMaster master : list) { for (Question question : master.getQuestions()) { ② System.out.println("問題:" + question.getContents()); ・・・ ① select * from question_master ② select * from question where question_master_id = 1 select * from question where question_master_id = 2 select * from question where question_master_id = 3 ・・・ N+1クエリ問題
  104. 104. #ccc_m7 Reladomoの実装例 • リレーションの定義 問題マスターを全件読み、問題文を出力 Operation operation = QuestionMasterFinder.all(); QuestionMasterList list = QuestionMasterFinder.findMany(operation); ① for (QuestionMaster master : list) { for (Question question : master.getQuestions()) { ② System.out.println("問題:" + question.getContents()); ・・・ ① select * from question_master ② select * from question where question_master_id = 1 select * from question where question_master_id = 2 select * from question where question_master_id = 3 N+1クエリ問題 DeepFetchがあるよ
  105. 105. #ccc_m7 Reladomoの実装例 • リレーションの定義 問題マスターを全件読み、問題文を出力 Operation operation = QuestionMasterFinder.all(); QuestionMasterList list = QuestionMasterFinder.findMany(operation); ① list.deepFetch(QuestionMasterFinder.questions()); for (QuestionMaster master : list) { for (Question question : master.getQuestions()) { ② System.out.println("問題:" + question.getContents()); ・・・ ① select * from question_master ② select * from question where question_master_id in ( 1 , 2 , 3 )
  106. 106. #ccc_m7 Reladomoの実装例 • リレーションの定義 問題マスターを全件読み、問題文を出力 Operation operation = QuestionMasterFinder.all(); QuestionMasterList list = QuestionMasterFinder.findMany(operation); ① list.deepFetch(QuestionMasterFinder.questions()); for (QuestionMaster master : list) { for (Question question : master.getQuestions()) { ② System.out.println("問題:" + question.getContents()); ・・・ ① select * from question_master ② select * from question where question_master_id in ( 1 , 2 , 3 ) 一度findManyやfindOneで 検索しないといけない JOINしてSQL 1発で取れないのか?
  107. 107. #ccc_m7 Reladomoの実装例 • ユニットテスト • H2データベース(on memory)でテスト • テスト用ConnectionManagerを作成 • テストデータファイルでデータ投入
  108. 108. #ccc_m7 Reladomoの実装例 • ユニットテスト • H2データベース(on memory)でテスト • テスト用ConnectionManagerを作成 • テストデータファイルでデータ投入 プロダクションと 同じデータベースを使いたい 性能を計るテストには 向かない
  109. 109. #ccc_m7 Reladomoの実装例 • ユニットテスト • テスト用ConnectionManagerを作成 private MithraTestResource testResource; @Before public void setup() throws Exception { testResource = new MithraTestResource("MithraRuntimeConfig_test.xml"); ConnectionManagerForTests connectionManager = ConnectionManagerForTests.getInstance("test_db"); testResource.createSingleDatabase(connectionManager, "test_data.txt"); testResource.setUp(); }
  110. 110. #ccc_m7 Reladomoの実装例 • ユニットテスト • テスト用ConnectionManagerを作成 MithraRuntimeConfig_test.xml <MithraRuntime> <ConnectionManager className="com.gs.fw.common.mithra.test.ConnectionManagerForTests"> <Property name="resourceName" value="test_db"/> <MithraObjectConfiguration cacheType="partial" className="some.package.User"/> ・・・ </ConnectionManager> </MithraRuntime>
  111. 111. #ccc_m7 Reladomoの実装例 • ユニットテスト • テスト用ConnectionManagerを作成 MithraRuntimeConfig_test.xml <MithraRuntime> <ConnectionManager className="com.gs.fw.common.mithra.test.ConnectionManagerForTests"> <Property name="resourceName" value="test_db"/> <MithraObjectConfiguration cacheType="partial" className="some.package.User"/> ・・・ </ConnectionManager> </MithraRuntime> プロダクション用のXMLとほぼ同じ。 テスト用のConnectionManagerを指定
  112. 112. #ccc_m7 Reladomoの実装例 • ユニットテスト • テストデータファイルでデータ投入 private MithraTestResource testResource; @Before public void setup() throws Exception { testResource = new MithraTestResource("MithraRuntimeConfig_test.xml"); ConnectionManagerForTests connectionManager = ConnectionManagerForTests.getInstance("test_db"); testResource.createSingleDatabase(connectionManager, "test_data.txt"); testResource.setUp(); }
  113. 113. #ccc_m7 Reladomoの実装例 • ユニットテスト • テストデータファイルでデータ投入 test_data.txt class some.package.User userId, name, address, businessDateFrom, businessDateTo, processingDateFrom, processingDateTo 1, “小鳩ミク”, “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 2, ”彩姫” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 3, ”遠乃 歌波” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 4, ”廣瀬 茜” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 5, ”ミサ” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ class some.package.XXX ・・・ class some.package.XXX ・・・
  114. 114. #ccc_m7 Reladomoの実装例 • ユニットテスト • テストデータファイルでデータ投入 test_data.txt class some.package.User userId, name, address, businessDateFrom, businessDateTo, processingDateFrom, processingDateTo 1, “小鳩ミク”, “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 2, ”彩姫” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 3, ”遠乃 歌波” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 4, ”廣瀬 茜” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ 5, ”ミサ” , “東京都”, "2019-01-01", "9999-12-01", "2019-01-01", "9999-12-01“ class some.package.XXX ・・・ class some.package.XXX ・・・ エンティティクラス名 フィールドリスト データ 複数エンティティ対応
  115. 115. #ccc_m7 Reladomoの実装例 • ユニットテスト • テストデータファイルでデータ投入 private MithraTestResource testResource; @After public void tearDown() throws Exception { testResource.tearDown(); } テストリソースの後始末
  116. 116. #ccc_m7 Reladomoの実装例 • プライマリキー生成戦略 • Max • Sequence
  117. 117. #ccc_m7 Reladomoの実装例 • プライマリキー生成戦略 user.xml <MithraObject objectType="transactional" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <Attribute name="userId" javaType="long" columnName="user_id" nullable="false“ primaryKey="true“ primaryKeyGeneratorStrategy="Max"/> </MithraObject> 対象テーブルの最大値で PKを作成
  118. 118. #ccc_m7 Reladomoの実装例 • プライマリキー生成戦略 user.xml <MithraObject objectType="transactional" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="mithraobject.xsd"> <Attribute name="userId" javaType="long" columnName="user_id" nullable="false“ primaryKey="true“ primaryKeyGeneratorStrategy="SimulatedSequence"> <SimulatedSequence sequenceName="sequenceName" sequenceObjectFactoryName="sequenceObjectFactory" hasSourceAttribute="false" batchSize="10" initialValue="1" incrementSize="1"/> </Attribute> </MithraObject> Reladomoが管理する シーケンス
  119. 119. #ccc_m7 Reladomoの実装例 • キャッシュ戦略 • データをキャッシュしてデータベースアクセスを最小に • エンティティ単位にキャッシュ方法を指定可能 MithraRuntimeConfig.xml <MithraRuntime> <ConnectionManager className="some.package.ConnectionManager"> <MithraObjectConfiguration cacheType="partial" className="some.package.User"/> ・・・ </ConnectionManager> </MithraRuntime> キャッシュの方法を エンティティ単位で指定可能
  120. 120. #ccc_m7 Reladomoの実装例 • キャッシュ戦略 • partial • 一度検索したものはメモリにキャッシュする • full • 起動時にメモリにキャッシュする
  121. 121. #ccc_m7 Reladomoの実装例 • キャッシュ戦略 • partial • 一度検索したものはメモリにキャッシュする • full • 起動時にメモリにキャッシュする システム稼働中に SQLでデータベースを直接更新したら キャッシュには反映されない・・・
  122. 122. #ccc_m7 Reladomoの実装例 • キャッシュ戦略 • partial • 一度検索したものはメモリにキャッシュする • full • 起動時にメモリにキャッシュする システム稼働中に SQLでデータベースを直接更新したら キャッシュには反映されない・・・ 後述のReladomo Notificationが 解決してくれるかも
  123. 123. #ccc_m7 Reladomoの実装例 • Auto Scale(クラスタリング)対策 • Reladomo Notification Reladomoが動作するJVM間で通知し、キャッシュなど情報を共有
  124. 124. #ccc_m7 Reladomoの実装例 • Auto Scale(クラスタリング)対策 • Reladomo Notification Reladomoが動作するJVM間で通知し、キャッシュなど情報を共有 ひとつのEC2でしか動かしていないので わかりません・・・。
  125. 125. #ccc_m7 メリット / デメリット / 課題 • メリット • Bi-temporalなデータを扱うなら唯一の選択 • SQLを書かなくてOK • デメリット • MySQL非対応 • SQLを書けない • Reladomoを前提としたテーブル設計が必要 • 課題 • キャッシュ更新どうする? • Springのトランザクション(@Transactional)と連携させる には? • 任意のテーブル同士をJOINしたい場合は?
  126. 126. #ccc_m7 まとめ • データの履歴管理をするならReladomo一択 • 自分でSQLを書きたいならDomaかMyBatis • 既存のシステムに導入するには難あり • (あたりまえだが)公式ドキュメントは熟読しよう • 非公式ドキュメントは少(マイナーライブラリ) • Reladomo Kataで試そう

×