GAE/Jでカスケードデリートができない!! (Please help!! Cascade delete doesn't work on GAE Data Store.)
Google Apps Engine(GAE)でよく言われるのが、「データストアが…」ということ。
公式HPによれば、JDO2.3、JPA1.0をサポートと言われているが、確かに制限事項が多くて、「なにが使えるのか」分からない。
とかとか、「使えない機能」はボツボツ出てくるのだが、「何が使えるの?(=こうしたいんだけど、どうやったらいいの?)」については「やってみないとわからない」というところだろうか?
「データストア(Big Table)はリレーショナルデータベース(RDB)ではない」といいつつ、エンティティー=レコード、エンティティー=テーブル、プロパティー=カラムなどというRDBのアナロジーで説明する記事を読んだりする。
実際、上のアナロジーは正しくなくて、強いていれば、エンティティー=レコード、カインド(種類)=テーブル、プロパティー=カラムというべき。
エンティティーグループは、エンティティーの階層構造を表す概念。この階層構造は、エンティティーの主キーに「ルートからのパス」として("/"で区切られて)表現される。日本語の公式HPで「種類」と訳されているのは、このカインド(kind)のことで、エンティティー名(クラス名)が採用される。
このエンティティー・グループの他に、一般のデータモデルでいうところの「所有」という「関係」が定義される。所有は、上述の階層構造でいえば「所有者の1つ下位に被所有者を置く」ということ。つまり、所有関係も、エンティティーグループのパスの概念に帰着されている。
非所有の関係とは、(所有関係をもたない)いわゆる「外部キー」だが、この機能は実装されておらず(joinも実装されておらず)、エンティティーに「外部キーにあたるもの」を保管して、各々管理せよ、となっている。
さて、「所有」に話を戻すと、被所有のエンティティーは、「親(所有者のエンティティー)の主キー情報を含む主キー」を持てばいいことになる。
だから、まず、所有者のエンティティーを作成して、そのプロパティーの1つに被所有のエンティティーをset、PersistenceManagerのmakePersistence("所有者のエンティティー")すれば、所有者のエンティティーと、被所有者のエンティティーの2つがストアされる。各々の主キーも、見たところ問題なく、ルートからのパスが自動的に設定される。
ここで、つまづいてしまった。
「所有」の関係ができる、ということは、所有者エンティティーの削除にあわせて、(自動的に)被所有者のエンティティーも削除される、カスケード・デリート(リカーシブ・デリート)ができるということだ。
HPでも、そのように説明されている。
だが、これができないーーー。deletePersistent("所有者")としても、被所有者がしっかり残ってしまう。
(HPにあるように)被所有者にmapped by属性をもたせても(こうすると、双方向の関係ができてしまうので、本意ではないのだが)、javax.persistenceのアノテーション(OneToOneとか)を引っ張り出してきても消えない。
うーーーん、と唸ってしまった。
本当にできるのか??
ググって見ると「できるような」記事があったりするので、できそうな気もする。
もしかしたら、「おまじない」みたいなものがあるかもしれない。
ソースコードがグチャグチャなので、整理してからUpしたい。