More Related Content Similar to Reladomo入門 JJUGナイトセミナー #jjug (20) Reladomo入門 JJUGナイトセミナー #jjug6. 5
Reladomoの哲学
Reladomo Philosophy & Vision
Long Lived Code [LLC]
Don’t Repeat Yourself [DRY]
Agile [AGL]
Domain based Object Oriented paradigm [DOO]
Correctness & Consistency [CC]
18. 17
Finder API:一件検索
Operation findTaroOp =
PersonFinder.firstName().eq(“太郎");
Person john =
PersonFinder.findOne(findTaroOp);
Finder APIを用いてOperationを作成
Finder.findOne()で一件検索
結果はEntityオブジェクトで取得
20. 19
Finder API:Operationの例1
Operation op1 = PersonFinder.firstName().eq("大輔");
// SQL: WHERE first_name = '大輔’
Operation op2 = PersonFinder.lastName().endsWith("藤");
// SQL: WHERE last_name LIKE '%藤’
Operation op1OrOp2 = op1.or(op2);
// SQL: WHERE (( first_name = '大輔') OR ( last_name LIKE '%藤'))
Operation op1AndOp2 = op1.and(op2);
// SQL: WHERE (( first_name = '大輔') AND ( last_name LIKE '%藤'))
21. 20
Finder API:Operationの例2
Operation op3 =
PersonFinder.age().in(IntHashSet.newSetWith(22, 24, 30));
// SQL: WHERE age in (22, 24, 30)
Operation op4 =
PersonFinder.age().notIn(IntHashSet.newSetWith(22, 25));
// SQL: WHERE age in (22, 25)
Operation op5 =
PersonFinder.age().greaterThan(25);
// SQL: WHERE age > 25
その他複雑なクエリを型安全に記述することが可能
24. 23
Operation findTaroOp = PersonFinder.firstName().eq("太郎");
Person taro = PersonFinder.findOne(findTaroOp);
Operation op1 = PersonFinder.firstName().eq("大輔");
Operation op2 = PersonFinder.lastName().endsWith("藤");
PersonList people2 = PersonFinder.findMany(op1.or(op2));
people2.forceResolve();
Operation op3 = PersonFinder.age().greaterThan(25);
PersonList people3 = PersonFinder.findMany(op3);
people3.forceResolve();
3種類の条件の違うクエリーは直接DBを叩く
ReIadomoのキャッシュ
25. 24
2017-07-23 18:02:06:881 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person -
connection:2005169944 find with: select t0.person_id,t0.first_name,t0.last_name,t0.age from person t0
where t0.first_name = '太郎’
2017-07-23 18:02:06:891 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 1 objects,
83.0 ms per
2017-07-23 18:02:06:992 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person -
connection:2005169944 find with: select t0.person_id,t0.first_name,t0.last_name,t0.age from person t0
where (( t0.first_name = '大輔') or ( t0.last_name like '%藤'))
2017-07-23 18:02:06:994 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 3 objects,
1.3333333333333333 ms per
2017-07-23 18:02:06:997 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person -
connection:2005169944 find with: select t0.person_id,t0.first_name,t0.last_name,t0.age from person t0
where t0.age > 25
2017-07-23 18:02:07:005 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 1 objects,
8.0 ms per
ReIadomoのキャッシュ
3回のDBアクセス
26. 25
Operation findAllOp = PersonFinder.all();
PersonList people = PersonFinder.findMany(findAllOp);
people.forceResolve(); //Reladomoは通常遅延ロードするので
例示のために強制ロード
Operation findTaroOp =
PersonFinder.firstName().eq("太郎");
… 前ページと同じ3つのクエリー
前ページと同じ3種類のクエリーの直前に全選択の
クエリーを走らせると…
ReIadomoのキャッシュ
27. 26
2017-07-23 19:34:04:415 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person -
connection:112049309 find with: select t0.person_id,t0.first_name,t0.last_name,t0.age from person
t02017-07-23 19:34:04:458 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 4
objects, 25.5 ms per
ReIadomoのキャッシュ
1回のDBアクセスで全選択
DBへのIOは全選択クエリーの1回のみ
その後のクエリーはキャッシュから取得
32. 31
PersonList newPeople = new PersonList();
newPeople.add(new Person("二郎", "山田", 45));
newPeople.add(new Person("さくら", "鈴木", 28));
newPeople.insertAll();
Reladomoの挿入処理:バッチ挿入
Listインスタンスを作成
新規作成したEntityをListに追加
InsertAll()メソッドで複数挿入
33. 32
Reladomoの挿入処理:オブジェクトの同一性
// 参照を取得後に挿入処理
Person jiro = new Person("二郎", "山田", 45);
jiro.insert();
// DBから取得
Operation op = PersonFinder.firstName().eq(“二郎");
Person jiroDb = PersonFinder.findOne(op);
// 作成されたオブジェクトはDBから取得したものと同値かつ同一
Assert.assertTrue(jiro.equals(jiroFromDb));
Assert.assertTrue(jiro == jiroFromDb);
Reladomoは永続化されたオブジェクトはメモリ上に
唯一つのみ存在することを保証する
35. 34
Operation tanakaOp = PersonFinder.lastName().eq("田中");
Person tanaka = PersonFinder.findOne(tanakaOp);
tanaka.setAge(25);
Reladomoの更新処理:単一更新
Entityインスタンスを検索
setXxx()メソッドで更新
*トランザクション外での更新は即時反映される
37. 36
Reladomoの更新処理:バッチ更新
Entityインスタンスを検索
トランザクション内での複数更新はバッチ更新される
Person tanaka = PersonFinder.findOne(PersonFinder.lastName().eq("田中"));
Person sato = PersonFinder.findOne(PersonFinder.lastName().eq("佐藤"));
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
tanaka.setAge(25);
sato.setAge(23);
return null;
});
2017-07-23 21:38:39:403 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - batch update of 2
objects with: update person set age = ? where person_id = ?
2017-07-23 21:38:39:404 [main] DEBUG com.gs.fw.common.mithra.batch.sqllogs.Person - batch
updating with: update person set age = 25 where person_id = 0
2017-07-23 21:38:39:405 [main] DEBUG com.gs.fw.common.mithra.batch.sqllogs.Person - batch
updating with: update person set age = 23 where person_id = 1
46. 45
Reladomoの関連:Finderによる柔軟な検索1
2017-07-24 21:51:55:924 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person -
connection:1954406292 find with: select t0.person_id,t0.first_name,t0.last_name,t0.age from person t0
inner join (select distinct t1.owner_id c0 from pet t1 where t1.pet_type_id = 0) as d1 on t0.person_id =
d1.c0
2017-07-24 21:51:55:977 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 1 objects,
347.0 ms per
生成されるSQL
48. 47
Reladomoの関連:Finderによる柔軟な検索2
2017-07-25 07:09:31:305 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - connection:708533063
find with: select t0.pet_id,t0.name,t0.owner_id,t0.age,t0.pet_type_id from pet t0 inner join person t1 on
t0.owner_id = t1.person_id where t1.last_name = '佐藤’
2017-07-25 07:09:31:316 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - retrieved 2 objects,
49.5 ms per
生成されるSQL
49. 48
Reladomoの関連:deepFetch
Relationshipを解決する際のN+1問題を避けるための機構
//ペット飼っている人を取得
Operation op = PersonFinder.pets().exists();
PersonList petOwners = PersonFinder.findMany(op);
petOwners.deepFetch(PersonFinder.pets());
petOwners.deepFetch(PersonFinder.pets().petType());
petOwners.forEach(petOwner -> {
petOwner.getPets().forEach(pet -> {
System.out.println(
petOwner.getLastName() + "さんは" +
pet.getName() + "という名の" +
pet.getPetType().getPetType() + "を飼っています");
});
});
取得したい関連を
deepFetch指定
50. 49
Reladomoの関連:deepFetch
deepFetchを使わない場合に発行されるSQL
2017-07-25 07:23:05:473 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - connection:576020159 find with:
select t0.person_id,t0.first_name,t0.last_name,t0.age from person t0 inner join (select distinct t1.owner_id c0 from pet
t1) as d1 on t0.person_id = d1.c
02017-07-25 07:23:05:493 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 2 objects, 51.0 ms per
2017-07-25 07:23:05:604 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - connection:576020159 find with:
select t0.pet_id,t0.name,t0.owner_id,t0.age,t0.pet_type_id from pet t0 where t0.owner_id = 1
2017-07-25 07:23:05:608 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - retrieved 2 objects, 6.0 ms per2017-
07-25 07:23:05:645 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - connection:576020159 find with: select
t0.pet_type_id,t0.pet_type from pet_type t0 where t0.pet_type_id = 0
2017-07-25 07:23:05:647 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - retrieved 1 objects, 3.0 ms
per2017-07-25 07:23:05:658 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - connection:576020159 find
with: select t0.pet_type_id,t0.pet_type from pet_type t0 where t0.pet_type_id = 3
2017-07-25 07:23:05:658 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - retrieved 1 objects, 2.0 ms per
2017-07-25 07:23:05:659 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - connection:576020159 find with:
select t0.pet_id,t0.name,t0.owner_id,t0.age,t0.pet_type_id from pet t0 where t0.owner_id = 2
2017-07-25 07:23:05:660 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - retrieved 2 objects, 0.5 ms per
2017-07-25 07:23:05:661 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - connection:576020159 find with:
select t0.pet_type_id,t0.pet_type from pet_type t0 where t0.pet_type_id = 1
2017-07-25 07:23:05:662 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - retrieved 1 objects, 2.0 ms per
2017-07-25 07:23:05:663 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - connection:576020159 find with:
select t0.pet_type_id,t0.pet_type from pet_type t0 where t0.pet_type_id = 2
2017-07-25 07:23:05:664 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - retrieved 1 objects, 1.0 ms per
51. 50
Reladomoの関連:deepFetch
deepFetchを使った場合に発行されるSQL
2017-07-25 07:27:16:540 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - connection:587153993 find with:
select t0.person_id,t0.first_name,t0.last_name,t0.age from person t0 inner join (select distinct t1.owner_id c0 from pet
t1) as d1 on t0.person_id = d1.c0
2017-07-25 07:27:16:564 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - retrieved 2 objects, 58.0 ms per
2017-07-25 07:27:16:650 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - connection:587153993 find with:
select t0.pet_id,t0.name,t0.owner_id,t0.age,t0.pet_type_id from pet t0 where t0.owner_id in ( 1,2)
2017-07-25 07:27:16:652 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Pet - retrieved 4 objects, 1.75 ms per
2017-07-25 07:27:16:661 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - connection:587153993 find with:
select t0.pet_type_id,t0.pet_type from pet_type t0 where t0.pet_type_id in ( 0,1,2,3)
2017-07-25 07:27:16:666 [main] DEBUG com.gs.fw.common.mithra.sqllogs.PetType - retrieved 4 objects, 1.25 ms per
64. 63
バイテンポラルモデルサポート:初期状態
Operation findTanakaOp = PersonFinder.lastName().eq("田中")
.and(PersonFinder.businessDate().eq(parse("2017/01/01")));
Person tanaka = PersonFinder.findOne(findTanakaOp);
Assert.assertEquals(0, tanaka.getPets().size());
1月1日時点ではペットを飼っていなかった田中さん
74. 73
Reladomoをもっと学ぶには
つづきはReladomo Kata / Reladomo Tourで
Reladomo Kata GitHub (Reladomo チュートリアル)
Guided Tour of Reladomo
Reladomo Kataは、JUnit上でテストをパスしながら学べる
トレーニング教材
本資料を学んだ方はKata内のmini-kataで手を動かして試し
てみることをおススメします