GAE/J の キーについて
ちょっと混乱したのでメモ。昨日書いた *1 ことは若干勘違いが入っていた。
keyToString、stringToKey と 文字列のキーかどうかは関係ないんだね。
文字列のキーをkeyToStringしたところで、Keyインスタンス自体のエンコード済み文字列(?)が返ってくる。これはURLのGETパラメーターに渡して文字列からKeyを復元するときに利用出来る。
今見たらjavadocにも書いてあった。
static java.lang.String keyToString(Key key)
http://code.google.com/intl/ja/appengine/docs/java/javadoc/com/google/appengine/api/datastore/KeyFactory.html
Key を Web セーフな文字列に変換します。
static Key stringToKey(java.lang.String encoded)
String で表現されている Key を Key インスタンスの表現に変換します。
keyToStringから返ってくる文字列にはインスタンス全ての情報が詰まっているようだ。
それに対して文字列のKeyは、KeyFactory.createKey(kind, name) で生成するが、kindやもしあれば親キーの情報を自分で設定する必要がある。
設定したnameを取り出したいときはkey.getName()でOK。
http://code.google.com/intl/ja/appengine/docs/java/datastore/creatinggettinganddeletingdata.html
ここにはキーは4種類あるけど、これはJDOを使った場合のことで低レベルAPI的には全てKeyクラスになる?
GWTと同様にマニュアルやAPI DOC
日本語のjavadoc と 英語のjavadoc は結構異なっている。
GWTでKey.getName()が使えることが分かったし、今作ってるアプリの構造を全体的に考え直さないといけないかもしれない。
keyに文字列を設定して、アプリ側でそれを表示するようにした場合、モデル同士の関連はModelRefではなくKeyを直接持っていた方が便利そうだ。GWTでModelRefは使いづらい。
一対多関連も、モデルAにモデルBのキーのリストを持つようにするとモデルAを取得しただけでモデルBを識別する文字列のリストが分かる。
そうすると、例えばユーザーごとに写真をアップロードするアプリを考えた場合に、写真に付ける名前をそのままキーにすると複数ユーザーで同時に使えない。写真をフォルダに入れる場合も、同じフォルダ名が使えない。
エンティティグループを使って ユーザー > フォルダ1 > フォルダ2 > 写真 のようにしたい。が、このときトランザクションは全く不要だ。
独自のルールで文字列を階層化するのがいいのかな。
例えば
ユーザー1:仮ID 1001 フォルダ1:仮ID 1001 フォルダ2:仮ID 1002 写真1 ↓ 1001:1001:1002:写真1
のようにするとか。写真1のキーからはフォルダ1などの文字列を取得できる必要はなく(というかツリービューのようなもので開いていくなら既にどこかにデータがあるはず)ただ一意なキーを保てれば良い。
IDと文字列の両方を指定できるKeyが欲しいところだ。カウンタ用モデルを作るのは避けたいが…いっそのことユーザー別に全エンティティに対応するカウンタを作ろうか。ページャのためのカウントにも使えて一石二鳥かもしれない。ユーザー別だから全部同じモデルに突っ込んでも更新が重なることはなさそうだし。
もうちょっと考える。