Successfully reported this slideshow.
Your SlideShare is downloading. ×

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

Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Ad
Upcoming SlideShare
Reladomo in Scala #scala_ks
Reladomo in Scala #scala_ks
Loading in …3
×

Check these out next

1 of 78 Ad

More Related Content

Slideshows for you (19)

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

Advertisement

Recently uploaded (20)

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

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

×