2017-08-17 9 views
1

私はデータベーステーブルでCRUDを実行するための簡単なエディタUIを持っています。 Hibernate 5.1では、プロセスは次のようになりました:デタッチされたオブジェクトを永続化するにはどうすればよいですか?

  1. セッションを作成します。データオブジェクトを読み込みます。セッションをクローズし、オブジェクトをデタッチします。
  2. デタッチされたオブジェクトを使用して、UIウィジェットを作成します。
  3. ユーザーは、UIのエントリの追加/編集/削除を許可し、切り離されたオブジェクトを変更できます。
  4. ユーザーの「保存」アクションで、新しいセッションを作成します。新しい/更新されたオブジェクトをsaveOrUpdate()で永続化します。セッションを閉じます。
  5. 必要に応じて繰り返します。

Hibernate 5.2は、Hibernate-native APIからJPA APIへの移行を強く推奨します。 JPAでは、分離されたオブジェクトを再接続することはできません。 JPAのEntityManagerからのHibernateセッションを取得し、するsaveOrUpdateを呼び出すためにそれを使用する

  1. 使用アンラップ:

    は回避策がいくつかあります。 JPAの一部ではない機能に依存しているので、私はこのオプションが嫌いです。

  2. JPA mergeを使用すると永続オブジェクトが更新されますが、関連付けが解除されないようにする必要があります。これは、私に同じオブジェクトの2つのコピーを与えます。一つは永続、一つは分離されています...これは面倒です。
  3. 手動でマージ操作を実行し、変更されたフィールドを分離オブジェクトから永続オブジェクトにコピーします。これは余分な作業です。
  4. プロセス全体を通して単一のEntityManagerインスタンスを存続させます。残念ながら、このセッションがまだ開いている間に他のスレッドがCRUD操作を実行し、永続化されたコンテキストをデータベーステーブルと同期させないようにすることができます。だから私はこのアプローチのファンでもありません。

これを行うには良い方法がありますか、それともこれらの唯一のオプションはありますか?

答えて

2

JPAでは、切り離したオブジェクトを再接続できません。

JPA仕様では、merge()の動作が定義されています。この操作は、説明されたユースケースを実装するのに役立つようです。

仕様を参照してください:

3.2.7.1マージ操作は、エンティティマネージャによって管理される永続エンティティへデタッチのエンティティからの状態の伝播を可能独立したエンティティの状態

をマージします。次のようにエンティティXに印加されるマージ操作の意味は次のとおり

  • Xは離脱エンティティXの状態は、同じIDまたは既存の管理されたエンティティのインスタンスX」にコピーされている場合Xの新しい管理対象コピーX 'が作成されます。
  • Xが新しいエンティティインスタンスである場合、新しいマネージエンティティインスタンスX 'が作成され、Xの状態が新しいマネージエンティティインスタンスX'にコピーされます。
  • Xが削除されたエンティティインスタンスの場合、マージ操作によってIllegalArgumentExceptionがスローされます(またはトランザクションのコミットが失敗します)。
  • Xが管理対象エンティティの場合、マージ操作では無視されますが、マージ操作は、カスケード要素の値がcascade = MERGEまたはcascade = ALLでアノテーションされている場合、Xからの関係によって参照されるエンティティにカスケードされます注釈。
  • カスケード要素値cascade = MERGEまたはカスケード= ALLを持つXからの関係によって参照されるすべてのエンティティYに対して、YはY 'として再帰的にマージされます。 Xによって参照されるそのようなすべてのYについて、X 'は参照Y'に設定される。
  • XがX 'にマージされたエンティティで、別のエンティティY(ここで、cascade = MERGEまたはcascade = ALLが指定されていない)への参照がある場合、Xが管理されている場合、XはX' 、その後、Xから同じ協会のナビゲーションはY.

と同じ永続アイデンティティを持つ「管理対象オブジェクトYへの参照を生成する」永続性プロバイダは、フィールドをマージしてはならないフェッチされていないことLAZYをマーク:それはしなければなりませんマージ時にこのようなフィールドを無視します。

エンティティで使用されるすべてのバージョン列は、マージ操作中および/またはフラッシュまたはコミット時に、パーシスタンスランタイム実装によってチェックされなければなりません。バージョン列が存在しない場合、マージ操作中の永続性プロバイダランタイムによって追加のバージョンチェックは行われません。

-JSR 338: JavaTM Persistence API, Version 2.1, Final Release

+1

は、そのマージを同意ここに最適なオプションです。 +1 – StanislavL

1

JPAマージとオプティミスティックロック(エンティティのバージョンベースのフィールド)が必要ですね。エンティティが変更された場合、元に戻すことはできません。

したがって、それを切り離して(バージョンを含む)マージします。

あり、オブジェクトが変更された場合、更新された値で再試行するか、またはユーザーを終了するエラーを送信何をすべきか、ビジネス・ロジックの問題がまだあるが、最終的な決定は技術の問題ではありません/

関連する問題