10.7. 自動的な状態検出
Hibernate のユーザーは次の2つのケースのどちらにも使える汎用的なメソッドを要求していました。それは、新しい識別子を生成して transient インスタンスを保存することと、その時点の識別子と関連づいている detached インスタンスを更新/再追加することのできるメソッドです。
saveOrUpdate()
はこのような機能を実現したメソッドです。
// in the first session Cat cat = (Cat) firstSession.load(Cat.class, catID); // in a higher tier of the application Cat mate = new Cat(); cat.setMate(mate); // later, in a new session secondSession.saveOrUpdate(cat); // update existing state (cat has a non-null id) secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)
saveOrUpdate()
の使用方法と意味は、新しいユーザーにとって混乱を招くかもしれません。まず第一に、あるセッションで使用したインスタンスを別の新しいセッションで使おうとしない限り、 update()
や saveOrUpdate()
や merge()
を使う必要はありません。アプリケーション全体を通じて、これらのメソッドを全く使わないこともあります。
通常、
update()
や saveOrUpdate()
は次のシナリオで使われます:
- アプリケーションが最初のセッションでオブジェクトをロードします。
- オブジェクトが UI 層に送られます。
- オブジェクトに対して変更が加えられます。
- オブジェクトがビジネスロジック層に送られます。
- アプリケーションは、2番目のセッションで
update()
を呼ぶことで、これらの変更を永続化します。
saveOrUpdate()
は以下のことを行います:
- オブジェクトがこのセッションで、すでに永続化されていれば、何もしません。
- そのセッションに関連づいている別のオブジェクトが同じ識別子を持っているなら、例外を投げます。
- オブジェクトの識別子が値を持たないならば、
save()
します。 - オブジェクトの識別子が値を持ち、その値が新たにインスタンス化されたオブジェクトのための値である場合、そのオブジェクトを
save()
します。 - オブジェクトが
<version>
や<timestamp>
でバージョンづけされていて、バージョンのプロパティ値が新しくインスタンス化されたオブジェクトに割り当てた値と同じ場合、そのオブジェクトをsave()
します。 - そうでない場合は、そのオブジェクトを
update()
します。
そして、
merge()
は以下のように非常に異なります:
- 同じ識別子を持つ永続化インスタンスがその時点でセッションと関連付いているならば、引数で受け取ったオブジェクトの状態を永続化インスタンスにコピーします。
- 永続化インスタンスがその時点でセッションに関連付いていないなら、データベースからそれをロードするか、あるいは、新しい永続化インスタンスを作成します。
- 永続化インスタンスが返されます。
- 引数として与えたインスタンスはセッションと関連を持ちません。それは、分離状態のままです。