0

「非正規化された」コレクションを作成するときに、NONSTRICT_READ_WRITE と READ_WRITE CacheConcurrencyStrategy の違いに遭遇しています...エンティティとしてモデル化された結合テーブルがありますが、結合先のテーブルへの読み取り専用リンクも含まれているという考えです。

私のエンティティ、おおよそ:

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Actor {
    @Id
    Integer id;
    @Column
    String name;
}

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Movie {
    @Id
    Integer id;
    @Column
    String title;
}

@Entity
@org.hibernate.annotations.Entity(dynamicUpdate = true)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
class Credit {
    @Column
    String roleName;

    @ManyToOne(targetEntity = Movie.class, optional = true)
    @JoinColumn(name = "movie_id", insertable = false, updatable = false)
    @NotFound(action = NotFoundAction.IGNORE)
    Movie movie;

    @Column(name = "movie_id")
    Long movieId;

    @ManyToOne(targetEntity = Actor.class, optional = true)
    @JoinColumn(name = "actor_id", insertable = false, updatable = false)
    @NotFound(action = NotFoundAction.IGNORE)
    Actor actor;

    @Column(name = "actor_id")
    Long actorId;
}

第 2 レベルのオブジェクト キャッシュが有効になっています (ehcache を使用)。

私のアプリケーションは、Movies と Actors を書きます...そしてしばらくしてから、Credit を書くことでそれらをリンクします。クレジットを書くときは、roleName、movieId、actorId の各フィールドに入力するだけで、Movie オブジェクトと Actor オブジェクトは提供しません。

NONSTRICT_READ_WRITE キャッシュを使用して、その Credit オブジェクトを読み戻すことができ、参照された Movie および Actor オブジェクトが含まれます。

READ_WRITE キャッシングを使用してクレジットを読み戻すと、Movie フィールドと Actor フィールドが空のクレジットが返されます。休止状態のキャッシュをクリアすると、そのクレジットを読み戻すと、予想どおり Movie および Actor オブジェクトが含まれます。これは TRANSACTIONAL キャッシングでも同様です (もちろん、NONE キャッシングではそうではありません)。

そのため、READ_WRITE キャッシュを使用している場合、hibernate は Actor および Movie フィールドが null の 2 番目のレベルのキャッシュにクレジットを挿入しているように見えます。これが起こらないようにし、常にデータベースから読み取ってこれらの結合されたフィールドを取得する方法はありますか? CacheConcurrencyStrategy.NONE でフィールドだけに注釈を付けようとしましたが、これは機能しません。

4

1 に答える 1

0

奇妙なマッピング (少なくとも非標準のマッピング) が原因で、おそらく休止状態のバグに出くわしたと思います。1 つは id で、もう 1 つはエンティティーの 2 つのフィールドを持つ本当の理由はありません。

を使用してIDをエンティティ参照に変えることができますsession.load-これはプロキシを作成するだけで、DBからデータをロードしません。

movieId と actorId フィールドを取り除き、movie/actor フィールドの insertable / updateable false を削除すると、READ_WRITEまたはNON_STRICT_READ_WRITE

Credit c = new Credit()
Movie m = session.load(movieId);
Actor a = session.load(actorId);
c.setMovie(m);
c.setActor(a);
session.save(c);

Hibernate は完全なオブジェクトを二次キャッシュに保存しません。私はそれを平らな形で保存し(水和 - よりdbテーブルに似ています)、そこからオブジェクトを再構築します。したがって、オブジェクトを null でキャッシュに保存し、更新しないという主張は正しくありません。他にも何かが起こっています。

との主な違いはREAD_WRITENON_STRICT_READ_WRITEREAD_WRITE の場合は更新中にキャッシュ内のエントリがロックされ、NON_STRICT_READ_WRITE ではロックされないことです。これは、このエンティティを複数のスレッドで同時に更新している場合にのみ影響します。

于 2012-09-08T07:32:50.287 に答える