EJB 3.0(Public Draft)入門記 Java Persistence API Chapter3 その4

エンティティのDBへの同期について。


3.2.3 Synchronization to the Database

永続エンティティのステートはトランザクションのコミット時に同期化されるそうです。この同期化とはエンティティやエンティティのリレーションシップへの更新がDBに書き込まれることを意味してるそうです。

管理された(managed)エンティティの双方向のリレーションシップはリレーションシップの所有側で保持される参照を基準にして永続化されるらしい。で、所有側と非所有側でそれぞれメモリ上の参照を矛盾のないように保持させるのは開発者の責任らしいです。

非所有側への変更は所有側へ反映されて、所有側への変更を非所有側へ反映するかは開発者が選択できる、といったようなことが書かれているような気がします。このあたりは、考えたりコードを動かしたりしてみたもののよくわかりませんでした。開発者が選択できるとあるりますがどうやって選択できるのか書いていないような?

永続性プロバイダランタイム(the persistence provider runtime)はトランザクションのコミット時以外、たとえばクエリ実行の前などにデータベースとの同期をとることができます。強制的に同期をとるためにflushメソッドが使えるそうです。flushはpersistence contextに関連づいたエンティティに適用されるそうです。同期のセマンティクスをコントロールするためにFlushModeアノテーションが使えるらしいです。Chapter 8 のFlushModeアノテーションの説明を見てみると、COMMITとかAUTOとかNEVERが選択できるみたいですが、まだこのアノテーションは検討中なんだそうです。


あるエンティティXに適用されるflush操作のセマンティクスは次のとおりです。

  • Xからのリレーションシップで参照されるすべてのエンティティYについて、Yへのリレーションシップにcascade=PERSISTもしくはcascade=ALLが指定されている場合、persist操作がYに適用される。
  • Xからのリレーションシップで参照されるエンティティYについて、Yへのリレーションシップにcascade=PERSISTもしくはcascade=ALLが指定されていない場合
    • Yが新規(new)もしくは削除され(removed)ていれば、flush操作によってIllegalStateExceptionがスローされる。トランザクションのコミットは失敗する。
    • Yが切り離され(detached)ていれば、セマンティクスはリレーションシップの所有権がXかYどちらにあるかで異なる。Xが所有権を持つ場合、リレーションシップの変更はDBと同期される。Yが所有権を持つ場合、振る舞いは定義されていない。
  • Xが削除された(removed)エンティティならば、DBから削除される。カスケードのオプションは関係しない。

うーん、XからYへの「リレーションシップにcascade=PERSISTもしくはcascade=ALLが指定されていない場合」がなぜそうなるのかよくわかりません...、予想したようには動かないです。IllegalStateExceptionなんておきないし。とりあえず、そういうものだということにしておきます。ちょっとくやしいけど。