同時実行戦略

Hibernate で第 2 レベルのキャッシュを有効にした後、どの Entity オブジェクトをどのようにキャッシュするかを Hibernate に説明する必要があります。

これを行うために、Hibernate にはエンティティ クラス用の特別なアノテーション@Cacheがあります。例:

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

このアノテーションは、2 次キャッシュを使用するエンティティごとに記述する必要があります。例:

@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
    @Id
    private Integer id;
    private Set<Task> tasks;
}

Hibernate では、キャッシュされたエンティティが別のスレッドからアクセスされる場合、そのエンティティに対して可能なアクセス戦略が 4 つあります。

  • 読み取り専用
  • 読み書き
  • 非厳密読み取り書き込み
  • トランザクション的な

読み取り専用。決して変更されない、データに適した同時実行戦略。Hibernate はこれらのオブジェクトをメモリに保存するだけです。参考データとしてのみご利用ください。

データベースには、決して変更されない多くの情報が保存されます。たとえば、テーブルには、追加されるだけで、変更または削除されないイベントのリストが保持されます。Hibernate を通じてこのテーブルを操作する必要がある場合は、読み取り専用キャッシュ戦略が適しています。

読み取り-書き込み(読み取り-書き込み)。この戦略は、主に読み取り可能なデータに使用します。ただし、Hibernate は、このデータの変更の試みを追跡します (頻度は非常に低いと予想されます)。

主に、めったに変更されず、頻繁に読み取られたり要求されたりするオブジェクトをキャッシュする必要があります。このようなオブジェクトがある場合は、それらに対して読み取り/書き込み戦略を使用する必要があります。

非厳密読み取り書き込み。この戦略では、キャッシュとデータベース間の一貫性は保証されません。データがほとんど変更されず、データが古い可能性がわずかにあることが重大な問題ではない場合は、この戦略を使用してください。

読み取り/書き込み戦略とは異なり、この戦略は、可変データが読み取り用にロックされていないことを前提としています。その結果、ある場所ではオブジェクトが変更され、別の場所では誰かが古いバージョンを読んでいる可能性があります。

たとえば、あるユーザーがコメントを変更しても、他のユーザーにはしばらくの間、古いバージョンが表示されたままになります。これが問題にならない場合は、非厳密読み取り書き込み戦略を使用してください。

トランザクション。この戦略は、まれに更新される同時トランザクションでデータが古くならないようにすることが重要な、主に読み取り専用データに使用します。

データをキャッシュに保存する

2 次キャッシュについて覚えておくべきもう 1 つの重要な詳細は、Hibernate がクラス自体のオブジェクトを保存しないことです。情報を文字列、数値などの配列として保存します。

そして、オブジェクト識別子は、この情報へのポインタとして機能します。概念的には、これはマップのようなもので、オブジェクトの ID がキーであり、データ配列が値です。次のように想像できます。

1 -> { "Ivanov", 1, null , {1,2,5} }
2 -> { "Petrov", 2, null , {1,2,5} }
3 -> { "Sidorov", 3, null , {1,2,5} }

これは、各オブジェクトが占める追加メモリの量を考慮すると、非常に合理的です。

上記に加えて、Entity クラスの依存関係もデフォルトではキャッシュされないことに注意してください。たとえば、上記のクラスEmployeeを考慮すると、フェッチ時にタスク コレクションは2 次キャッシュからではなくデータベースから取得されます。

依存関係もキャッシュしたい場合、クラスは次のようになります。

@Entity
@Table(name = "employee")
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Employee {
    @Id
    private Integer id;

   @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
   private Set<Task> tasks;
}

最後の詳細 - 2 次キャッシュからの読み取りは、目的のオブジェクトが 1 次キャッシュで見つからなかった場合にのみ行われます。

キャッシュモード

Hibernate では、非常に柔軟なキャッシュ管理が可能です。キャッシュ モードは、個々のセッションごとに、またはデータベース リクエストごとに設定できます。

このようなモードは 5 つあります。

  • 得る
  • 無視
  • 普通
  • 置く
  • リフレッシュ

以下の表は彼らの仕事を説明しています:

キャッシュモード 説明
得る データはキャッシュから読み取られますが、キャッシュには追加されません。
無視 セッションはキャッシュと対話しません。
普通 データはキャッシュから読み取られ、キャッシュに追加されます。
置く データはキャッシュから取得されるのではなく、キャッシュに追加されます。
リフレッシュ データはキャッシュから取得されるのではなく、キャッシュに追加されます。このモードでは、hibernate.cache.use_minimal_puts 設定が追加で使用されます。

セッションのキャッシュ モードを設定する例:

session.setCacheMode(CacheMode.GET);
Employee director = session.createQuery("from Employee where id = 4").uniqueResult();

また、セッションとリクエストのモードを設定する例も示します。

session.setCacheMode(CacheMode.GET);
Query query = session.createQuery("from Employee where id = 4");
query.setCacheMode(CacheMode.IGNORE); // Ignore cache work for this request
Employee director = query.uniqueResult();