NCacheを使用してHibernateセカンドレベルキャッシュを実装する

このチュートリアルで、私たちはHibernateにて二段階キャッシュの実装を探索します。

これは、Hibernateと一緒にJavaアプリを設定し、NCacheを二段階キャッシュとして設定し、最終的に、キャッシュを使用してデータベースの負荷を軽減し、パフォーマンスを向上させることを確認するものです。

基础知识

実装に突入する前に、Hibernate、NCache、そしてHibernateの二段階キャッシュの基本を理解しましょう。

Hibernate

Hibernateは、Javaアプリ用のオープンソースのオブジェクト関連マッピング(ORM)フレームワークです。これは、Javaオブジェクトをデータベーステーブルにマッピングし、その逆も可能にして、データベースとのやり取りを簡素化します。

パフォーマンスを改善するために、Hibernateは二つのレベルのキャッシュを提供します。

1. 最初のレベルのキャッシュ

最初のレベルのキャッシュは、Hibernateのセッションに関連付けられており、デフォルトで有効化されています。これは、セッション中に取得されたオブジェクトを存储し、同じオブジェクトについてデータベースに何度もアクセスする必要を削除します。

最初のレベルのキャッシュは、セッションの範囲に限定されており、セッション間で共有されません。

また、持続的ではありませんが、セッションが閉じられるか明示的にクリアされると空きます。

2. 二段階キャッシュ

第2階層のキャッシュはセッション間で共有され、アプリケーションレベルでデータをキャッシュするように設定することができます。これは、オブジェクトを長時間保持することでデータベースへのアクセス数を減らします。

第2階層のキャッシュは明示的に設定する必要があり、NCache、Ehcacheなどの various caching providers を使用して実装できます。

NCache

NCacheは、.NETやJavaアプリケーション用の分散型キャッシュ解決策です。これは、頻繁にアクセスされるデータをキャッシュし、アプリケーションのパフォーマンスを向上させるためのIn-memoryデータストアを提供します。

NCacheは、リプレイション、分割、クライアントキャッシュなどのさまざまなキャッシングトポロジーをサポートします。

NCacheは、Hibernate内で2階層キャッシュとして使用され、データベースに直接アクセスする代わりにキャッシュからオブジェクトを保存・取得することができます。

コードセットアップ

まず、Javaアプリケーションを作成し、Hibernateをデータベースとやりとりする設定をしましょう。

私たちはMavenを依存関係とプロジェクトの構築を管理するために使用し、アプリケーションはエンティティクラスを持ってデータを定義し、クライアントクラスを持ってデータベースとやりとりします。

まず、キャッシングなしでアプリケーションをテストし、データベースとのやりとりを確認します。その後、Hibernate内で第2階層のキャッシュとしてNCacheを設定し、エンティティオブジェクトをキャッシュし、データベースへのアクセス数を減らす設定をします。

依存関係

まず、pom.xmlファイルにHibernateとNCacheの必要な依存関係を追加します。

<dependencies> <!-- Hibernate dependencies --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.6.1.Final</version> </dependency> <!-- NCache dependencies --> <dependency> <groupId>com.alachisoft.ncache</groupId> <artifactId>ncache-hibernate</artifactId> <version>5.3.3</version> </dependency> </dependencies>

注意してください、ここで参照しているバージョンは最新のリリースに基づいて変更する場合があります。プロジェクトに适したバージョンを使用してください。

エンティティクラス

次に、キャッシュしたいデータを表すエンティティクラスを作成しましょう。簡単なCustomerクラスをidnameフィールドで定義します。

@Entity @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "CustomerRegion") public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // getters and setters }

Customerクラスは@Entity@Cacheableを注釈して、キャッシュ可能なエンティティとして定義します。idフィールドは@Id@GeneratedValueで注釈され、ユニークな識別子を自動生成するように設定されています。

また、エンティティ用のキャッシング戦略とリージョンを指定するために、@Cacheアノテーションも使用します。

NONSTRICT_READ_WRITEは、Hibernateがデータの読み取りや書き込み時にキャッシュを更新し、最終的な一致性を保証するように指示します。

region属性は、データを格納するキャッシュリージョンを指定します。

このリージョンを使用してNCacheにキャッシュデータを格納するように設定します。

Hibernate設定

Hibernateとデータベースとのやり取りを行い、キャッシングを有効にするための設定が必要です。

次に、src/main/resourcesディレクトリに以下の設定を持つhibernate.cfg.xmlファイルを作成しましょう。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.show_sql">true</property> </session-factory> </hibernate-configuration>

この設定ファイルでは、データベースの接続詳細、方言、キャッシング設定を指定します。Oracleをデータベースとし、Hibernateを自動的にスキーマを更新するように設定します。

クライアントクラス

データベースと対話し、キャッシュメカニズムをテストするためのクライアントクラスを作成しましょう。Hibernateを使用してCustomerオブジェクトを保存および取得するmainクラスを書きます。

public class HibernateClient { public static void main(String[] args) { SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Customer customer = new Customer(); customer.setName("John Doe"); session.save(customer); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); Customer retrievedCustomer = session.get(Customer.class, customer.getId()); System.out.println("Retrieved Customer: " + retrievedCustomer.getName()); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); retrievedCustomer = session.get(Customer.class, customer.getId()); System.out.println("Retrieved Customer: " + retrievedCustomer.getName()); transaction.commit(); session.close(); } }

このクライアントクラスでは、Hibernateの設定を使用してSessionFactoryを作成し、データベースと対話するためにセッションを開きます。Customerオブジェクトをデータベースに保存し、idを使用してそれを取得します。

その後、retrieveCustomerメソッドを2つの別々のセッションで2回呼び出して、キャッシュなしでのデータベースのインタラクションを確認します。

同じオブジェクトを取得するためにデータベースが2回アクセスされることを観察できます。

ご覧のとおり、Hibernateクエリが2回実行されています。

NCacheサーバーの設定

HibernateのセカンドレベルキャッシュとしてNCacheを使用するには、NCacheサーバーを設定し、キャッシュされたデータを保存するように構成する必要があります。

NCacheは、WindowsおよびLinuxサーバーにインストールできる分散キャッシングソリューションを提供します。NCacheを使用してキャッシュクラスターを作成し、それを構成します。キャッシュクラスターが設定されると、Javaアプリケーションから接続できます。

HibernateでNCacheをセカンドレベルキャッシュとして有効にする

NCacheサーバーがセットアップされたら、Hibernateを構成してNCacheをセカンドレベルキャッシュプロバイダーとして使用できるようにします。Hibernateの設定ファイルを更新し、キャッシュ設定を指定してキャッシュを有効にします。

キャッシュリージョンの有効化

hibernate.cfg.xml ファイルでのキャッシュ設定を更新し、NCacheを第二段階キャッシュプロバイダとして有効にする:

<hibernate-configuration> <session-factory> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">com.alachisoft.ncache.NCacheRegionFactory</property> ... </session-factory> </hibernate-configuration>

ここで、hibernate.cache.use_second_level_cache 属性を true に設定して、第二段階キャッシュを有効にします。また、hibernate.cache.region.factory_class 属性を指定して、NCacheRegionFactory をキャッシュプロバイダとして使用します。

NCacheのプロパティー設定

NCacheは、Hibernate内でキャッシュ設定を行うための多くのプロパティーを提供します。これらは ncache-hibernate.xml ファイルで指定することができます:

<configuration> <application-config application-id="myapp" enable-cache-exception="true" default-region-name="DefaultRegion" key-case-sensitivity="false"> <cache-regions> <region name="CustomerRegion" cache-name="demoCache" priority="AboveNormal" expiration-type="Sliding" expiration-period="8"/> <region name="DefaultRegion" cache-name="demoCache" priority="default" expiration-type="None" expiration-period="0"/> </cache-regions> <database-dependencies> <dependency entity-name="hibernator.BLL.Customer" type="oledb" sql-statement="SELECT CustomerID FROM Customers WHERE CustomerID ='?';" cache-key-format="Customers#[pk]" connection-string="Provider=SQLOLEDB;Data Source=20.200.20.40,1433;Initial Catalog=Northwind;User ID=john;Password=1234;"/> </database-dependencies> </application-config> </configuration>

この設定ファイルで、CustomerRegion キャッシュリージョンを定義し、キャッシュ名、優先度、期限型、及び期限期间を指定します。expiration-typeSliding に設定し、期限期間を 8 秒に設定します。これは、8秒間の非活動後、キャッシュされたデータが期限切れになり、キャッシュから削除されることを意味します。

加えて、特定のキャッシュリージョンを設定していない他のエンティティにはデフォルトの設定の DefaultRegion を定義します。これは、明示的に設定されていないエンティティによるフォールバックリージョンとして使用されます。

複数のキャッシュリージョンを持つことで、異なる設定を異なるエンティティに基づいて定義することができ、これによりよい效能を得ることができます。

次に、データベース依存性Customers实体に定義します。これは、缓存をデータベースと同期させ、データベース内で変更が行われたときに缓存されたデータを更新・削除するために使用されます。

SQL文を指定してCustomerIDCustomersテーブルから取得し、データベースに接続する接続文字列を指定します。

缓存键フォーマットは、实体の主キーに基づいて缓存键が生成される方法を指定します。

テスト

Hibernate内で第二級缓存としてNCacheを設定した後、缓存が性能を改善することを見るためにアプリケーションをテストしましょう。クライアントクラスを再び実行し、缓存を有効にしてデータベースとの対話を観察します。

クライアントクラスを実行すると、Customerオブジェクトを取得する最初のコールはデータベースにアクセスしてデータを取得することがあります。しかし、同じオブジェクトを取得する2回目のコールは、再びデータベースにアクセスする代わりに缓存から取得するようになっています。これは、缓存がデータベースの負荷を减轻し、データを缓存から提供することで性能を向上させることを示しています。

NCacheをHibernateと共用する利点

Hibernate内でNCacheを第二級缓存として使用することで、いくつかの利点が提供されます。

  • 性能改善: NCacheは高速のインメモリストレージを提供して、キャッシュデータのレイテンシを短縮し、スループットを向上させます。また、バックグラウンドでキャッシュを更新する非同期操作も提供しており、アプリケーションパフォーマンスに影響を与えることが少ないです。
  • スケール性: アプリケーションがスケールアップするにつれて、NCacheは水平方向にスケールすることで、大量のデータとユーザーリクエストを処理することができます。クラスターで配置でき、キャッシュレプリケーションや分割などの機能をサポートして、ロードを分散します。
  • 柔軟性: NCacheは様々なキャッシングトポロジーと設定を提供して、さまざまなアプリケーション要求に适応します。また、キャッシュリージョンの使用により、異なるエンティティに基づいて必要なキャッシュ設定が可能で、これによりキャッシングの動作を细粒度に制御することができます。
  • 同期: NCacheはデータベースとキャッシュを同期させるオプションを提供しています。これにより、キャッシュデータがデータベースと同期し、最新の変更を反映します。

概要

このチュートリアルでは、Javaアプリケーション用のHibernateにて第二層のキャッシュを実装する際にNCacheを使用する方法を説明しました。

まず、Hibernate、NCache、およびHibernate第二層キャッシュの基本を理解しました。その後、Javaアプリケーションを設定し、HibernateとNCacheを第二層キャッシュとして構成しました。最後に、実装をテストして、キャッシングを使用することでデータベースアクセス次数を减少し、キャッシュからデータを提供することでパフォーマンスを改善することを確認しました。

NCacheとHibernateを使用することで、開発者はディストリビューションキャッシングの強力な力を活用して、アプリケーションのパフォーマンス、スケーラビリティ、および信頼性を向上させることができます。NCacheは、Hibernateおよび他のJavaフレームワークとしっかりと統合されている強力なキャッシングソリューションを提供しており、Javaアプリケーションでデータをキャッシングするための理想的な選択肢です。

Source:
https://dzone.com/articles/implement-hibernate-second-level-cache-with-ncache