12

エンティティのバージョン属性を使用したオプティミスティックロックは正常に機能し、実装が簡単です。

<version property="VERSION" type="int" column="EX_VERSION" />

エンティティには、次のタイプのプロパティがあります。

private int VERSION;
public int getVERSION() { return VERSION; }
public void setVERSION(int VERSION) { this.VERSION = VERSION; }

ここまでは順調ですね。これで、サービスメソッドは上記のエンティティのデータ転送オブジェクト(DTO)を返します。これは、ビューがHTMLで表示します。更新ページの場合、VERSION属性はHTMLの非表示フィールドに格納され、フォームとともに送信されます。

目的は、versionプロパティを使用して、表示される情報に古いバージョンが付随している場合にユーザーの更新が失敗するようにすることです。

コントローラは、更新された情報(バージョンプロパティを含む)を含むDTOを使用してサービスメソッドを呼び出すことでユーザーの更新要求に応答し、サービスメソッドはデータアクセスオブジェクト(DAO)を使用して変更を永続化します。

public void update(SimpleDTO dto) {
    SimplyEntity entity = getSimpleDao().load(dto.getId());
    copyProperties(dto, entity); // all properties, including VERSION copied to entity
    getSimpleDao().update(entity);
}

問題は、copyProperties(...)によってエンティティにコピーされたバージョンプロパティがHibernateによって尊重されないことです。次のフォーラムで理由を突き止めました:https ://forum.hibernate.org/viewtopic.php?f = 1&t = 955893&p = 2418068

つまり、load()が呼び出されると、Hibernateはバージョンプロパティをセッションキャッシュにキャッシュし、その値が後で何に変更されてもかまいません。これが正しい動作であることに同意しますが、BossesからHTMLフォームプロパティを介してバージョンを渡すように指示されています(これに適したパターンがある場合は、ぜひ聞いてください)。

私が今探求している解決策の1つは、更新が行われる前に、hibernateTemplate.evict(simpleEntity)を使用してバージョンが設定された後、セッションからエンティティを削除することです。これがうまくいくことを願っていますが、効率的ではないようです。

セッションキャッシュからだけでなく、インスタンス自体のバージョンプロパティを確認するようにHibernateに依頼したいと思います。

回答ありがとうございます!

--LES

4

1 に答える 1

11

本当にDTO を使用する必要がありますか? 実際のエンティティを渡している場合は、この問題は発生しませんでした。また、エンティティを再度ロードする必要もありません。これは、パフォーマンスにとってまったく優れたものではありません。

しかし、DTO を使用する正当な理由があるとしても、新しくリロードしたエンティティのバージョン番号を保存する前に更新しようとする理由がよくわかりません。ワークフローで考えられるさまざまなシナリオを検討してください。

  1. エンティティは最初にロードされ、バージョンは V1 です
  2. UI に移動する DTO に転送され、戻ってきて、保存する準備が整います。
  3. エンティティが再度読み込まれ、バージョン = V2

現在、次の 2 つの可能性があります。

  1. V1 == V2. ピーチ、何もしなくていいよ。
  2. V1 は V2 よりも小さいです。つまり、編集中に他の誰かがエンティティを更新したことを意味します。保存は失敗するため、バージョンを V1 に設定して保存しようとする理由はありません。V2 で保存する (他のユーザーの変更を上書きする) か、今すぐ失敗するか (Hibernate を使用せずに) のいずれかです。
于 2009-09-14T23:03:12.380 に答える