SlideShare a Scribd company logo
1 of 78
Reladomo入門
株式会社FOLIO 伊藤博志
JJUGナイトセミナー 2017.7.26
Reladomo is an open source software Licensed under Apache 2.0 License,
Copyright 2016 Goldman Sachs, Its name may be a trademark of its owner.
1
Agenda
1. 自己紹介
2. Reladomoの基本
3. Reladomoのコード生成
4. Reladomoの検索・挿入・更新・削除処理
5. Reladomoの関連
6. GS Collectionsサポート
7. ユニットテストサポート
8. バイテンポラルモデル
2
自己紹介
趣味:ドラム演奏
JavaOneコミュニティバンド
Null Pointersで演奏経験あり(日本人初)
Head of Engineering @ FOLIO
伊藤 博志
Eclipse Collections:共同プロジェクトリード兼コミッター
Reladomo:コントリビューター
OpenJDK:コントリビューター
JJUG CCC、Java Day Tokyo、JavaOne San Francisco登壇
2017年5月に株式会社FOLIO入社。
3
Reladomoの基本
4
Reladomoとは
https://github.com/goldmansachs/reladomo
 ゴールドマン・サックス社が2016年9月にGitHubに
OSSとして公開したJava ORMフレームワーク
 Apache License 2.0
 ORMフレームワークであり、オブジェクト指向の徹底
 xmlからコード/DDLの自動生成
 バイテンポラルデータモデルをネイティブサポート
 強力に型付けられたクエリー言語(SQLは書かない)
 ユニットテストのフルサポート
 etc.
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]
6
Reladomoのコード生成
7
コード生成:xmlファイル
<MithraObject objectType="transactional"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="reladomoobject.xsd">
<PackageName>sample.domain</PackageName>
<ClassName>Person</ClassName>
<DefaultTable>PERSON</DefaultTable>
<Attribute javaType="int" name="personId" columnName="PERSON_ID"
primaryKey="true" primaryKeyGeneratorStrategy="Max"/>
<Attribute javaType="String" name="firstName" columnName="FIRST_NAME"
nullable="false" maxLength="64"/>
<Attribute javaType="String" name="lastName" columnName="LAST_NAME"
nullable="false" maxLength="64"/>
</MithraObject>
8
コード生成:xmlファイルからJavaクラス生成
Xml file
ビルド内でコード生成
9
コード生成:Finderクラス
Xml file
検索に用いる
10
コード生成:Entityクラス
Xml file
単一レコードに対応
11
コード生成:Listクラス
Xml file
複数レコードに対応
12
コード生成:DatabaseObjectクラス
Xml file
コネクション・テーブル情報を保持
13
コード生成:抽象クラス・Finderクラス
Xml file
抽象クラス・Finderクラスは
xml変更に追従するため常にビルド時に生成する
14
コード生成:具象クラス
Xml file
具象クラスは生成コードをVCSにコミット
独自のビジネスロジックを追加可能
15
Reladomoの検索処理
16
Finder API
Finderクラスを用いてOperationを生成
型安全に検索
sqlは一切書かない
–検索条件: Operation - Finder APIから作成
–1件検索:Finder.findOne(Operation)
–複数検索:Finder.findMany(Operation)
17
Finder API:一件検索
Operation findTaroOp =
PersonFinder.firstName().eq(“太郎");
Person john =
PersonFinder.findOne(findTaroOp);
Finder APIを用いてOperationを作成
Finder.findOne()で一件検索
結果はEntityオブジェクトで取得
18
Finder API:複数検索
Operation findAllOp = PersonFinder.all();
PersonList people =
PersonFinder.findMany(findAllOp);
Finder APIを用いてOperationを作成
Finder.findMany()で複数検索
結果はListオブジェクトで取得
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 '%藤'))
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
その他複雑なクエリを型安全に記述することが可能
21
Reladomoのキャッシュ
22
ReIadomoのキャッシュ
Reladomoは複数のキャッシュ戦略を持つ
–Partial Cache
–Full Cache
–None
ランタイムの設定でエンティティごとにキャッシュ
戦略を選択可能
クエリーキャッシュとオブジェクトキャッシュ
キャッシュ機構は高度に最適化されており、データ
ベースへのアクセスを最小に保つことができる
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のキャッシュ
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アクセス
25
Operation findAllOp = PersonFinder.all();
PersonList people = PersonFinder.findMany(findAllOp);
people.forceResolve(); //Reladomoは通常遅延ロードするので
例示のために強制ロード
Operation findTaroOp =
PersonFinder.firstName().eq("太郎");
… 前ページと同じ3つのクエリー
前ページと同じ3種類のクエリーの直前に全選択の
クエリーを走らせると…
ReIadomoのキャッシュ
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回のみ
その後のクエリーはキャッシュから取得
27
Reladomoのトランザクション処理
28
Reladomoのトランザクション処理
トランザクション内で行う必要のある処理に関しては
ラムダ式内に記述しexecuteTransactionalCommand()
にわたす。
以下、例によってはこのトランザクションのコード
を省略している。
MithraManagerProvider.getMithraManager().executeTransactionalCommand(tx -> {
//検索・挿入・更新・削除処理の記述
return someObject;
});
29
Reladomoの挿入処理
30
Reladomoの挿入処理:単一挿入
Person jiro = new Person("二郎", "山田", 45);
jiro.insert();
Entityインスタンスを作成
Insert()メソッドで挿入
31
PersonList newPeople = new PersonList();
newPeople.add(new Person("二郎", "山田", 45));
newPeople.add(new Person("さくら", "鈴木", 28));
newPeople.insertAll();
Reladomoの挿入処理:バッチ挿入
Listインスタンスを作成
新規作成したEntityをListに追加
InsertAll()メソッドで複数挿入
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は永続化されたオブジェクトはメモリ上に
唯一つのみ存在することを保証する
33
Reladomoの更新処理
34
Operation tanakaOp = PersonFinder.lastName().eq("田中");
Person tanaka = PersonFinder.findOne(tanakaOp);
tanaka.setAge(25);
Reladomoの更新処理:単一更新
Entityインスタンスを検索
setXxx()メソッドで更新
*トランザクション外での更新は即時反映される
35
Reladomoの更新処理:複数更新
複数検索でListオブジェクトを取得
Listに対してsetXxx()メソッドで複数更新
PersonList people =
PersonFinder.findMany(PersonFinder.all());
people.setAge(20);
2017-07-23 21:45:08:489 [main] DEBUG com.gs.fw.common.mithra.sqllogs.Person - multi update of 6
objects with: update person set age = ? where person_id in (?...)
2017-07-23 21:45:08:489 [main] DEBUG com.gs.fw.common.mithra.batch.sqllogs.Person - multi
updating with: update person set age = 20 where person_id in (0,1,2,3,4,5)
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
37
Reladomoの削除処理
38
Reladomoの削除処理:単一削除
Entityインスタンスを検索
delete()メソッドで削除
Operation op = PersonFinder.lastName().eq("田中");
Person tanaka = PersonFinder.findOne(op);
tanaka.delete();
39
Reladomoの削除処理:複数削除
複数検索でListオブジェクトを取得
Listに対してdeleteAll()メソッドで複数削除
Operation op =
PersonFinder.lastName().in(Sets.mutable.of(“田中”, “佐藤"));
PersonList people = PersonFinder.findMany(op);
people.deleteAll();
40
Reladomoの関連
41
Reladomoの関連:サンプルモデル
42
Reladomoの関連:Person.xml
<Relationship name="pets"
relatedObject="Pet"
cardinality="one-to-many"
relatedIsDependent="true"
reverseRelationshipName="owner">
this.personId = Pet.ownerId
</Relationship>
Person PetPetPet
pets
owner
43
Reladomoの関連:Pet.xml
<Relationship name="petType"
relatedObject="PetType"
cardinality="many-to-one">
this.petTypeId = PetType.petTypeId
</Relationship>
Pet PetTypepetType
44
Reladomoの関連:Finderによる柔軟な検索1
//犬を飼っている飼い主を取得
Operation op =
PersonFinder.pets().petTypeId().eq(PetType.DOG);
Person dogOwner = PersonFinder.findOne(op);
テーブル間のjoinを柔軟に記述
通常の一件検索と同様
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
46
Reladomoの関連:Finderによる柔軟な検索2
reverseRelationshipNameで指定した逆引きのAPI(e.g. owner)も活用可
通常の複数検索と同様
//佐藤さんが飼っているペットを取得
Operation op =
PetFinder.owner().lastName().eq("佐藤");
PetList satoPets = PetFinder.findMany(op);
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
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指定
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
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
51
GS Collectionsのネイティブサポート
52
GS Collectionsサポート:使用例
データ取得後にインメモリーでさまざまなデータ
処理をしたい場合に最適
//苗字を取得
List<String> lastNames =
people.asGscList().collect(Person::getLastName);
//猫を飼っている飼い主を取得
List<Person> catOwner =
people.asGscList().select(person -> person.hasPet(PetType.CAT));
//PetTypeごとに飼い主をグルーピング
MutableListMultimap<PetType, Person> peopleByPetType =
people.asGscList().groupByEach(
person -> person.getPets().asGscList().collect(Pet::getPetType));
53
あれ、Eclipse Collectionsは?
54
Eclipse Collections対応
 まもなくサポートされる、予定。。。!
(今年初めに着手したものの、まだ終わってませんすみません。。。)
55
JUnitテストサポート
56
JUnitテストサポート
インメモリのh2データベース上にデータを初期化
57
JUnitテストサポート
DBアクセスを伴ったビジネスロジックをユニット
テストレベルで担保可能
バグの再現も容易
冪等性の担保のようなロジックもテスト可能
58
バイテンポラルモデルサポート
59
バイテンポラルモデルサポート
Reladomoのキラーコンテンツとも言える機能
2つの時間概念を同時に扱うことができる
–有効時間
–トランザクション時間
60
バイテンポラルモデル
詳しくはJJUG CCCのプレゼン資料をごらんください
61
JJUG CCCでは話せなかった「関連」
を絡めたバイテンポラルサポート
62
田中さん Petサクラ
pets
owner
バイテンポラルモデル:例 - 関連も自由自在
田中さん チビ
pets
owner
田中さん
1月1日時点ではペットを飼っていなかった田中さん
3月1日から犬のチビを飼い始めました
5月1日から猫のサクラを飼い始めました
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日時点ではペットを飼っていなかった田中さん
64
バイテンポラルモデルサポート:3/1付で挿入処理
3月1日から犬のチビを飼い始めました
Pet chibi = new Pet(parse("2017/03/01"));
chibi.setName("チビ");
chibi.setAge(3);
chibi.setPetTypeId(PetType.DOG);
chibi.setOwner(tanaka);
*このケースでは関連の解決のためsetOwnerの時点でchibiがinsertされます
65
バイテンポラルモデルサポート:5/1付で挿入処理
5月1日から猫のサクラを飼い始めました
Pet sakura = new
Pet(parse(“2017/05/01”));
sakura.setName(“サクラ");
sakura.setAge(5);
sakura.setPetTypeId(PetType.CAT);
sakura.setOwner(tanaka);
*このケースでは関連の解決のためsetOwnerの時点でsakuraがinsertされます
66
2つのPetオブジェクト挿入後の
検索結果を見てみましょう
67
Operation findTanakaAsOf20170201 =
PersonFinder.lastName().eq("田中")
.and(PersonFinder.businessDate()
.eq(parse("2017/02/01")));
Person tanakaAsOf20170201 =
PersonFinder.findOne(findTanakaAsOf20170201);
System.out.println(tanakaAsOf20170201.getPets().size()); //0
バイテンポラルモデルサポート:2/1付の検索結果
2月1日付で田中さんはペットの関連を持ちません
68
Operation findTanakaAsOf20170302 =
PersonFinder.lastName().eq("田中")
.and(PersonFinder.businessDate()
.eq(parse("2017/03/02")));
Person tanakaAsOf20170302 =
PersonFinder.findOne(findTanakaAsOf20170302);
System.out.println(
tanakaAsOf20170302
.getPets()
.asGscList()
.collect(Pet::getName)); //[チビ]
バイテンポラルモデルサポート:3/2付の検索結果
3月2日付で田中さんは「チビ」への関連を持っています
69
Operation findTanakaAsOf20170502 =
PersonFinder.lastName().eq("田中")
.and(PersonFinder.businessDate()
.eq(parse("2017/05/02")));
Person tanakaAsOf20170502 =
PersonFinder.findOne(findTanakaAsOf20170502);
System.out.println(
tanakaAsOf20170502
.getPets()
.asGscList()
.collect(Pet::getName)); //[チビ, サクラ]
バイテンポラルモデルサポート:5/2付の検索結果
5月2日付で田中さんは「チビ」と「サクラ」への関連を持っています
70
「関連」を絡めたバイテンポラルモデル
において実際にデータやクエリーがどう
表現されているのか気になる方は懇親会
で伊藤とお話ししましょう
*そのうちブログに書くかも
バイテンポラルモデルサポート:データの表現は割愛
71
まとめ
 Reladomoはオブジェクト指向の極みのようなORM
 検索はFinderによる型安全なクエリー
 挿入・更新・削除処理も一切SQLを書かずにオブジェクト
上のAPIで完結
 複雑なビジネスロジックもJUnit上で安全にテスト
 DBクエリはReladomo / インメモリ処理はGS Collections
(or Eclipse Collections)
 テンポラルデータモデルの扱いが非常に容易
72
入門を超えて
Reladomoは非常に高度な機能を持ち合わせたエンタープライ
ズグレードのORMフレームワークです
 シャーディングのネイティブサポート
 Temp tableを用いたクエリーのサポート
 入力集合と出力集合をMulti-threadで比較更新するMulti-
Threaded DB Loader
 Off-Heapキャッシュ
73
Reladomoをもっと学ぶには
つづきはReladomo Kata / Reladomo Tourで
 Reladomo Kata GitHub (Reladomo チュートリアル)
 Guided Tour of Reladomo
Reladomo Kataは、JUnit上でテストをパスしながら学べる
トレーニング教材
本資料を学んだ方はKata内のmini-kataで手を動かして試し
てみることをおススメします
74
告知
75
Scala関西Summit 2017(9月9日 土)
ScalikeJDBCやSkinny Frameworkでおなじみ
グッドフロー・テクノロジーズ瀬良さんと共同で
Reladomo in Scalaというセッションをします!
お楽しみに。
76
APPENDIX
77
リンク集
 データ履歴管理のためのテンポラルデータモデルと
Reladomoの紹介
 Reladomo GitHub
 Reladomo Kata GitHub (Reladomo チュートリアル)
 Guided Tour of Reladomo
 Reladomo Documentations

More Related Content

What's hot

Androidの通信周りのコーディングについて
Androidの通信周りのコーディングについてAndroidの通信周りのコーディングについて
Androidの通信周りのコーディングについて
Shoichi Takagi
 
モテる JavaScript
モテる JavaScriptモテる JavaScript
モテる JavaScript
Osamu Monoe
 

What's hot (19)

ElasticsearchとTasteプラグインで作るレコメンドシステム
ElasticsearchとTasteプラグインで作るレコメンドシステムElasticsearchとTasteプラグインで作るレコメンドシステム
ElasticsearchとTasteプラグインで作るレコメンドシステム
 
LastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめようLastaFluteでKotlinをはじめよう
LastaFluteでKotlinをはじめよう
 
Tokyo Webmining #12 Hapyrus
Tokyo Webmining #12 HapyrusTokyo Webmining #12 Hapyrus
Tokyo Webmining #12 Hapyrus
 
SolrとElasticsearchの比較
SolrとElasticsearchの比較SolrとElasticsearchの比較
SolrとElasticsearchの比較
 
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
 
Elasticsearchで作る形態素解析サーバ
Elasticsearchで作る形態素解析サーバElasticsearchで作る形態素解析サーバ
Elasticsearchで作る形態素解析サーバ
 
ESFluteによるElasticsearchでのO/Rマッパーを用いた開発
ESFluteによるElasticsearchでのO/Rマッパーを用いた開発ESFluteによるElasticsearchでのO/Rマッパーを用いた開発
ESFluteによるElasticsearchでのO/Rマッパーを用いた開発
 
Elasticsearch at CrowdWorks
Elasticsearch at CrowdWorksElasticsearch at CrowdWorks
Elasticsearch at CrowdWorks
 
「書ける」から「できる」になれる! ~Javaメモリ節約ノウハウ話~
「書ける」から「できる」になれる! ~Javaメモリ節約ノウハウ話~「書ける」から「できる」になれる! ~Javaメモリ節約ノウハウ話~
「書ける」から「できる」になれる! ~Javaメモリ節約ノウハウ話~
 
sbtマルチプロジェクトビルドの使いどころ
sbtマルチプロジェクトビルドの使いどころsbtマルチプロジェクトビルドの使いどころ
sbtマルチプロジェクトビルドの使いどころ
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
Elasticsearch Authプラグインでアクセスコントロール
Elasticsearch AuthプラグインでアクセスコントロールElasticsearch Authプラグインでアクセスコントロール
Elasticsearch Authプラグインでアクセスコントロール
 
SparqlEPCUが提供するlod開発プラットフォーム
SparqlEPCUが提供するlod開発プラットフォームSparqlEPCUが提供するlod開発プラットフォーム
SparqlEPCUが提供するlod開発プラットフォーム
 
JavaScriptことはじめ
JavaScriptことはじめJavaScriptことはじめ
JavaScriptことはじめ
 
Mongodb
MongodbMongodb
Mongodb
 
カジュアルにMongo dbのbackup機能説明
カジュアルにMongo dbのbackup機能説明カジュアルにMongo dbのbackup機能説明
カジュアルにMongo dbのbackup機能説明
 
Androidの通信周りのコーディングについて
Androidの通信周りのコーディングについてAndroidの通信周りのコーディングについて
Androidの通信周りのコーディングについて
 
モテる JavaScript
モテる JavaScriptモテる JavaScript
モテる JavaScript
 
最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!最強オブジェクト指向言語 JavaScript 再入門!
最強オブジェクト指向言語 JavaScript 再入門!
 

Similar to Reladomo入門 JJUGナイトセミナー #jjug

Node-v0.12の新機能について
Node-v0.12の新機能についてNode-v0.12の新機能について
Node-v0.12の新機能について
shigeki_ohtsu
 
ビッグデータ活用支援フォーラム
ビッグデータ活用支援フォーラムビッグデータ活用支援フォーラム
ビッグデータ活用支援フォーラム
Recruit Technologies
 
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
Hiroh Satoh
 

Similar to Reladomo入門 JJUGナイトセミナー #jjug (20)

20180123 power shell
20180123 power shell20180123 power shell
20180123 power shell
 
はじめてのPowerShell
はじめてのPowerShellはじめてのPowerShell
はじめてのPowerShell
 
AWS Security JAWS 経済的にハニーポットのログ分析をするためのベストプラクティス?
AWS Security JAWS 経済的にハニーポットのログ分析をするためのベストプラクティス?AWS Security JAWS 経済的にハニーポットのログ分析をするためのベストプラクティス?
AWS Security JAWS 経済的にハニーポットのログ分析をするためのベストプラクティス?
 
実践 NestJS
実践 NestJS実践 NestJS
実践 NestJS
 
Node-v0.12の新機能について
Node-v0.12の新機能についてNode-v0.12の新機能について
Node-v0.12の新機能について
 
Djangoフレームワークの紹介
Djangoフレームワークの紹介Djangoフレームワークの紹介
Djangoフレームワークの紹介
 
debexpo(mentors.d.n)をハックするには
debexpo(mentors.d.n)をハックするにはdebexpo(mentors.d.n)をハックするには
debexpo(mentors.d.n)をハックするには
 
Gaej Jdo
Gaej JdoGaej Jdo
Gaej Jdo
 
Django Rest Frameworkでお手軽にREST APIを作る
Django Rest Frameworkでお手軽にREST APIを作るDjango Rest Frameworkでお手軽にREST APIを作る
Django Rest Frameworkでお手軽にREST APIを作る
 
Tech Fielders 2009/9/18 LT
Tech Fielders 2009/9/18 LTTech Fielders 2009/9/18 LT
Tech Fielders 2009/9/18 LT
 
Das 2015
Das 2015Das 2015
Das 2015
 
React Native GUIDE
React Native GUIDEReact Native GUIDE
React Native GUIDE
 
ビッグデータ活用支援フォーラム
ビッグデータ活用支援フォーラムビッグデータ活用支援フォーラム
ビッグデータ活用支援フォーラム
 
Introduction of Python
Introduction of PythonIntroduction of Python
Introduction of Python
 
HBaseとSparkでセンサーデータを有効活用 #hbasejp
HBaseとSparkでセンサーデータを有効活用 #hbasejpHBaseとSparkでセンサーデータを有効活用 #hbasejp
HBaseとSparkでセンサーデータを有効活用 #hbasejp
 
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011
 
20180613 [TensorFlow分散学習] Horovodによる分散学習の実装方法と解説
20180613 [TensorFlow分散学習] Horovodによる分散学習の実装方法と解説20180613 [TensorFlow分散学習] Horovodによる分散学習の実装方法と解説
20180613 [TensorFlow分散学習] Horovodによる分散学習の実装方法と解説
 
Statically detecting vulnerability under memory pressure using exhaustive search
Statically detecting vulnerability under memory pressure usingexhaustive searchStatically detecting vulnerability under memory pressure usingexhaustive search
Statically detecting vulnerability under memory pressure using exhaustive search
 
5分でわかる!ownCloudアドオンの作り方
5分でわかる!ownCloudアドオンの作り方5分でわかる!ownCloudアドオンの作り方
5分でわかる!ownCloudアドオンの作り方
 
HTML5&API総まくり
HTML5&API総まくりHTML5&API総まくり
HTML5&API総まくり
 

Recently uploaded

Recently uploaded (10)

Utilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native IntegrationsUtilizing Ballerina for Cloud Native Integrations
Utilizing Ballerina for Cloud Native Integrations
 
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
論文紹介: The Surprising Effectiveness of PPO in Cooperative Multi-Agent Games
 
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
論文紹介:Selective Structured State-Spaces for Long-Form Video Understanding
 
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
論文紹介:Video-GroundingDINO: Towards Open-Vocabulary Spatio-Temporal Video Groun...
 
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアルLoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
LoRaWAN スマート距離検出デバイスDS20L日本語マニュアル
 
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その32024/04/26の勉強会で発表されたものです。
 
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
LoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイスLoRaWANスマート距離検出センサー  DS20L  カタログ  LiDARデバイス
LoRaWANスマート距離検出センサー DS20L カタログ LiDARデバイス
 
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
知識ゼロの営業マンでもできた!超速で初心者を脱する、悪魔的学習ステップ3選.pptx
 
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
Amazon SES を勉強してみる その22024/04/26の勉強会で発表されたものです。
 
新人研修 後半 2024/04/26の勉強会で発表されたものです。
新人研修 後半        2024/04/26の勉強会で発表されたものです。新人研修 後半        2024/04/26の勉強会で発表されたものです。
新人研修 後半 2024/04/26の勉強会で発表されたものです。
 

Reladomo入門 JJUGナイトセミナー #jjug