appengine java night #2a

23
appengine java night #2 実践 Low-Level API ~クエリ編~ shin1ogawa@株式会社トップゲート

Upload: shinichi-ogawa

Post on 24-Jan-2015

2.262 views

Category:

Technology


1 download

DESCRIPTION

 

TRANSCRIPT

Page 1: Appengine Java Night #2a

appengine java night #2実践 Low-Level API ~クエリ編~

shin1ogawa@株式会社トップゲート

Page 2: Appengine Java Night #2a

自己紹介...shin1ogawaです!Google, Java, AppEngine, Eclipse, Wicket, Maven, Hudson, 構成管理... • 参加しているOSSプロダクトやコミュニティ

• [SF.jp]Jiemamy...データベースの進化的設計

• [SF.jp]gae-j-samples...GAE/Jのサンプル、GAE/J/Maven統合プラグイン

• [SF.jp]gaejtools...GAE/J用のユーティリティ(予定)

• [SF.jp]asclipse...Amateras AIR GEAR用のAS3構文解析ライブラリ

• java-ja, wicket-ja,

株式会社トップゲート(http://www.topgate.co.jp)で、GoogleAppEngineやGoogleAppsを使用したソリューションを提供する為のお仕事をしています。

Page 3: Appengine Java Night #2a

Low-Level API#1の復習

Page 4: Appengine Java Night #2a

復習) Key• KeyのみでEntityGroupが構成される• Entityの属性にEntityGroup的に子供の…とかそんなのはいっさい無い。

• Keyオブジェクトに保持されている情報• ApplicationID• 親EntityのKey, 自身のKind名• name文字列or自動採番されたlong値

• 文字列としてエンコードされた表現で保存される

Page 5: Appengine Java Night #2a

復習) KeyFactory

• 何種類かのcreateKey()メソッドでKeyオブジェクトを生成できる

• keyToString()メソッドでKeyオブジェクトをエンコードされた文字列に変換できる。

• stringToKey()メソッドで、エンコードされた文字列からKeyオブジェクトに変換できる。

Page 6: Appengine Java Night #2a

復習) Entity

• setProperty(“属性名”, Object 属性値)• Object getProperty(“属性名”)• boolean hasProperty(“属性名”)• <missing>を判断できる

• 必ずしも、設定した型で値が保存されているとは限らない• HashSet等のCollectionはArrayList• intはLong…

Page 7: Appengine Java Night #2a

復習) DatastoreService

• 保存• Key put(Entity)• List<Key> put(Iterable<Entity>)

• 削除• void delete(Key... keys)• void delete(Iterable<Key>)

• 上記のメソッドはすべて、第一引数にTransactionを指定できる。

Page 8: Appengine Java Night #2a

復習) DatastoreService

• キーによる取得• Entity get(Key key)• 存在しないKeyを指定した場合は EntityNotFoundExceptionが飛ぶ。

• Map<Key, Entity> get( Iterable<Key> key)• 存在しないKeyが含まれていた場合は、返り値のMapに要素が入ってこない。

Page 9: Appengine Java Night #2a

復習) DatastoreService

• Transactionの開始,取得• beginTransaction()• getCurrentTransaction()• ...ほかにもいくつか。

• Transactionの操作• commit()• rollback()• isActive()

Page 10: Appengine Java Night #2a

復習) DatastoreService

• 1.2.5より前ではKeyを自動生成する場合はEntityを保存した後にしかそのKeyを取得できなかったが、1.2.5からは明示的に自動採番済みのKeyを取得する事ができる。• KeyRange allocalteIds( [親Key], Kind, 確保する数)

• KeyRange• getStart(), getEnd(), iterator()

Page 11: Appengine Java Night #2a

Datastore Service保存のサンプル(Entityの準備)KeyRange parentKeys = service.allocateIds("Parent", 1);Key parentKey = parentKeys.getStart();KeyRange childKeys = service.allocateIds(parentKey, "Child", 2);Iterator<Key> childKeysIterator = childKeys.iterator();Entity parent = new Entity(parentKey);Entity child1 = new Entity(childKeys.next());Entity child2 = new Entity(childKeys.next());

Page 12: Appengine Java Night #2a

Datastore Service保存のサンプル(保存)

Transaction tx = service.beginTransaction();try { List<Entity> entities = Arrays.asList(parent, child1, child2 service.put(tx, entities); tx.commit();} finally { if (tx.isActive()) { tx.rollback(); }}

Page 13: Appengine Java Night #2a

Low-Level APIここから#2の内容

Page 14: Appengine Java Night #2a

Datastore ServiceQuery• new Query(String kind)• JDOっぽく、フィルタ条件やソート条件を指定する場合

• new Query(String kind, Key ancestorKey)• 指定したKindで、指定した親キーに属するエンティティを取得する。

• new Query(Key ancestorKey)• 指定した親キーに属するエンティティを、すべてのKindにまたがって、末端のエンティティまで取得する。• ローカル環境では動作しない、という不具合が残念!

Page 15: Appengine Java Night #2a

Datastore ServiceQuery• フィルタ条件の指定• Query addFilter(String propertyName,

FilterOperator operator, Object value)• ソート条件の指定• Query addSort(String propertyName,

SortDirection direction)• 取得対象をキーのみにしぼる• Query setKeysOnly()• Keyにしかアクセスしないのでずいぶん早くなる。

主キーを意味する属性名は Entity.KEY_RESERVED_PROPERTY

Page 16: Appengine Java Night #2a

Datastore ServicePreparedQuery• DatastoreService#prepare()メソッドにQueryオブジェクトを渡す事で、PreaparedQueryが取得できる。

• 件数を取得する• int countEntities()

• 一件だけ取得する• Entity asSingleResult()• 条件にマッチするエンティティが無ければnullが返る。• 複数のEntityが条件にマッチした場合は

TooManyResultsExceptionが投げられる。

Page 17: Appengine Java Night #2a

Datastore ServicePreparedQuery• 複数件を取得する• List<Entity> asList(FetchOptions)• まとめてフェッチする事ができる。

• Iterator<Entity> asIterator([FetchOptions])• いわゆるカーソルのような操作になる。

• Iterable<Entity> asIterable([FetchOptions])• iterator()を取得した瞬間にDatastoreにアクセスする。そこから先はasIterator()と同じ動作。

• FetchOptions• フェッチのためのオプション。offset, limit等。

Page 18: Appengine Java Night #2a

Datastore ServiceQueryのサンプルQuery query = new Query(“Entity”);query.addFilter(“name”, FilterOperator.GREATER_THAN_OR_EQUAL, “hoge”) .addSort("name", SortDirection.ASCENDING) .addSort("__key__", SortDirection.ASCENDING);

DatastoreService service = DatastoreServiceFactory.getDatastoreService();List<Entity> entities = service.prepare(query).asList( FetchOptions.Builder.withOffset(0).limit(100));

Page 19: Appengine Java Night #2a

Datastore ServiceQueryのサンプル: EntityGroupの取得Iterator<Entity> entityGroup = service.prepare(new Query(rootKey) .addSort(“__key__”)).asIterator( FetchOptions.Builder.withOffset(0).limit(100));Parent parent = null;while (entityGroup.hasNext) { Entity entity = entityGroup.next(); if (entity.getKind().equals(“Parent”)) parent = EntityUtil.toBean(entity,Parent.class); else if (entity.getKind().equals(“Child”)) parent.getChidren().add( EntityUtil.toBean(entity, Child.class); ...

Page 20: Appengine Java Night #2a

Datastore ServiceちょっとJDOに話を戻しますJDOでたまに話題になる話についてちょっと考察。

class MyEntity { List<Child> children1; List<Child> children2;}myEntity.getChildren1().addAll(childA, childB);myEntity.getChildren2().addAll(childC, childD);manager.makePersistent(myEntity);

上記のように、同じ型の別のListを属性として持っているエンティティがあったとした時。

Page 21: Appengine Java Night #2a

Datastore ServiceちょっとJDOに話を戻しますMyEntity myEntity = manager.getObjectById(MyEntity.class, key);List<Child> children1 = myEntity.getChildren1();List<Child> children2 = myEntity.getChildren2();

この時のchildren1には、childAとchildBだけではなく、childCとchildDが格納されている。children2はnull。

Page 22: Appengine Java Night #2a

Datastore ServiceちょっとJDOに話を戻します

MyEntiy(1)

MyEntiy(1)/Child(A)

MyEntiy(1)/Child(B)

MyEntiy(1)/Child(C)

MyEntiy(1)/Child(D)

当然、親子関係は正しい構成で保存されているが、Child(A-D)がそれぞれどの属性に保持されていたか?は知りようが無い!

このように、実装を意識する事でハマリは遭遇しにくかったり、ハマった時も理解できる。

Page 23: Appengine Java Night #2a

ご清聴ありがとうございました!

shin1ogawa@株式会社トップゲート