6.10. SQL キャッシュストア
SQL キャッシュストアを使用すると、既存のデータベーステーブルから Data Grid キャッシュを読み込むことができます。Data Grid は、2 種類の SQL キャッシュストアを提供します。
- テーブル
- Data Grid は、1 つのデータベーステーブルからエントリーを読み込みます。
- Query
- Data Grid は SQL クエリーを使用して、単一または複数のデータベーステーブルからエントリーを読み込み (これらのテーブルのサブ列からの読み込みを含む)、挿入、更新、および削除操作を実行します。
コードチュートリアルにアクセスして、SQL キャッシュストアの動作を試します。Persistence code tutorial with remote caches を参照してください。
SQL テーブルとクエリーストアの両方は以下のようになります。
- 永続ストレージに対する読み取りおよび書き込み操作を許可します。
- 読み取り専用で、キャッシュローダーとして機能します。
単一のデータベース列または複数のデータベース列の複合に対応するキーと値をサポートします。
複合キーと値の場合は、キーと値を記述する Protobuf スキーマ (
.proto
ファイル) で Data Grid を指定する必要があります。Data Grid Server を使用すると、schema コマンドを使用して、Data Grid Console または Command Line Interface(CLI) からschema
を追加できます。
SQL キャッシュストアは有効期限またはセグメンテーションをサポートしません。
6.10.1. キーおよび値のデータ型
Data Grid は、適切なデータ型を使用して、SQL キャッシュストアを介してデータベーステーブルの列からキーと値を読み込みます。以下の CREATE
ステートメントは、isbn
と title
の 2 つの列が含まれる books という名前のテーブルを追加します。
2 列のデータベーステーブル
CREATE TABLE books ( isbn NUMBER(13), title varchar(120) PRIMARY KEY(isbn) );
SQL キャッシュストアでこのテーブルを使用すると、Data Grid は isbn
列をキーとして、title
列を値として使用してキャッシュに追加します。
6.10.1.1. 複合キーと値
複合プライマリーキーまたは複合値を含むデータベーステーブルで SQL ストアを使用できます。
複合キーまたは値を使用するには、データ型を記述する Protobuf スキーマで Data Grid を指定する必要があります。また、SQL ストアに schema
設定を追加し、キーと値のメッセージ名を指定する必要があります。
Data Grid は、ProtoStream プロセッサーで Protobuf スキーマを生成することを推奨します。次に、Data Grid コンソール、CLI、または REST API を使用してリモートキャッシュの Protobuf スキーマをアップロードできます。
複合値
以下のデータベーステーブルは、title
および author
列の複合値を保持します。
CREATE TABLE books ( isbn NUMBER(13), title varchar(120), author varchar(80) PRIMARY KEY(isbn) );
Data Grid は、isbn
列をキーとして使用してキャッシュにエントリーを追加します。値の場合、Data Grid には title
列と author
列をマッピングする Protobuf スキーマが必要です。
package library; message books_value { optional string title = 1; optional string author = 2; }
複合キーと値
以下のデータベーステーブルは複合プライマリーキーと複合値を保持し、それぞれに 2 列があります。
CREATE TABLE books ( isbn NUMBER(13), reprint INT, title varchar(120), author varchar(80) PRIMARY KEY(isbn, reprint) );
キーと値の両方で、Data Grid には列をキーと値にマッピングする Protobuf スキーマが必要です。
package library; message books_key { required string isbn = 1; required int32 reprint = 2; } message books_value { optional string title = 1; optional string author = 2; }
6.10.1.2. 埋め込みキー
以下の例のように、Protobuf スキーマは値の中にキーを含めることができます。
組み込みキーを使用した Protobuf スキーマ
package library; message books_key { required string isbn = 1; required int32 reprint = 2; } message books_value { required string isbn = 1; required string reprint = 2; optional string title = 3; optional string author = 4; }
埋め込みキーを使用するには、SQL ストア設定に embedded-key="true"
属性または embeddedKey(true)
メソッドを含める必要があります。
6.10.1.3. SQL から Protobuf タイプへ
以下の表に、SQL データ型のデフォルトを Protobuf データ型にマッピングしています。
SQL 型 | Protobuf タイプ |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
6.10.2. データベーステーブルからの Data Grid キャッシュの読み込み
Data Grid にデータベーステーブルからデータを読み込ませる場合は、SQL テーブルキャッシュストアを設定に追加します。データベースに接続すると、Data Grid はテーブルからメタデータを使用して列名とデータタイプを検出します。また、Data Grid は、データベースのどの列がプライマリーキーの一部であるかを自動的に決定します。
前提条件
-
JDBC 接続の詳細を把握している。
JDBC 接続ファクトリーを直接キャッシュ設定に追加できます。
実稼働環境でのリモートキャッシュでは、マネージドデータソースを Data Grid Server 設定に追加し、キャッシュ設定で JNDI 名を指定する必要があります。 複合キーまたは複合値の Protobuf スキーマを生成し、スキーマを Data Grid に登録します。
ヒントData Grid は、ProtoStream プロセッサーで Protobuf スキーマを生成することを推奨します。リモートキャッシュでは、Data Grid コンソール、CLI、または REST API を使用してスキーマを追加して、スキーマを登録できます。
手順
データベースドライバーを Data Grid デプロイメントに追加します。
-
リモートキャッシュ: データベースドライバーを、Data Grid Server インストールの
server/lib
ディレクトリーにコピーします。 組み込みキャッシュ:
infinispan-cachestore-sql
依存関係をpom
ファイルに追加します。<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-cachestore-sql</artifactId> </dependency>
-
リモートキャッシュ: データベースドライバーを、Data Grid Server インストールの
- Data Grid 設定を開いて編集します。
SQL テーブルキャッシュストアを追加します。
宣言的
table-jdbc-store xmlns="urn:infinispan:config:store:sql:13.0"
プログラマティック
persistence().addStore(TableJdbcStoreConfigurationBuilder.class)
-
データベースダイアレクトを
dialect=""
またはdialect()
のいずれかで指定します (例:dialect="H2"
またはdialect="postgres")
。 以下のように、必要なプロパティーで SQL キャッシュストアを設定します。
-
クラスター全体で同じキャッシュストアを使用するには、
shared="true"
またはshared(true)
を設定します。 -
読み取り専用のキャッシュストアを作成するには、
read-only="true"
または.ignoreModifications(true)
を設定します。
-
クラスター全体で同じキャッシュストアを使用するには、
-
table-name="<database_table_name>"
またはtable.name("<database_table_name>")
を使用して、キャッシュを読み込むデータベーステーブルに名前を付けます。 schema
要素または.schemaJdbcConfigurationBuilder()
メソッドを追加し、複合キーまたは値の Protobuf スキーマ設定を追加します。-
package
属性またはpackage()
メソッドを使用してパッケージ名を指定します。 -
message-name
属性またはmessageName()
メソッドを使用して複合値を指定します。 -
key-message-name
属性またはkeyMessageName()
メソッドを使用して複合キーを指定します。 -
スキーマで値内にキーが含まれている場合は、
embedded-key
属性またはembeddedKey()
メソッドにtrue
の値を設定します。
-
- 変更を設定に保存します。
SQL テーブルストアの設定
以下の例では、Protobuf スキーマで定義された複合値を使用して、books という名前のデータベーステーブルから分散キャッシュを読み込みます。
XML
<distributed-cache> <persistence> <table-jdbc-store xmlns="urn:infinispan:config:store:sql:13.0" dialect="H2" shared="true" table-name="books"> <schema message-name="books_value" package="library"/> </table-jdbc-store> </persistence> </distributed-cache>
JSON
{ "distributed-cache": { "persistence": { "table-jdbc-store": { "dialect": "H2", "shared": "true", "table-name": "books", "schema": { "message-name": "books_value", "package": "library" } } } } }
YAML
distributedCache: persistence: tableJdbcStore: dialect: "H2" shared: "true" tableName: "books" schema: messageName: "books_value" package: "library"
ConfigurationBuilder
ConfigurationBuilder builder = new ConfigurationBuilder(); builder.persistence().addStore(TableJdbcStoreConfigurationBuilder.class) .dialect(DatabaseType.H2) .shared("true") .tableName("books") .schemaJdbcConfigurationBuilder() .messageName("books_value") .packageName("library");
6.10.3. SQL クエリーを使用したデータのロードおよび操作の実行
SQL クエリーキャッシュストアを使用すると、データベーステーブルのサブ列からなど、複数のデータベーステーブルからキャッシュを読み込み、挿入、更新、および削除操作を実行することができます。
前提条件
-
JDBC 接続の詳細を把握している。
JDBC 接続ファクトリーを直接キャッシュ設定に追加できます。
実稼働環境でのリモートキャッシュでは、マネージドデータソースを Data Grid Server 設定に追加し、キャッシュ設定で JNDI 名を指定する必要があります。 複合キーまたは複合値の Protobuf スキーマを生成し、スキーマを Data Grid に登録します。
ヒントData Grid は、ProtoStream プロセッサーで Protobuf スキーマを生成することを推奨します。リモートキャッシュでは、Data Grid コンソール、CLI、または REST API を使用してスキーマを追加して、スキーマを登録できます。
手順
データベースドライバーを Data Grid デプロイメントに追加します。
-
リモートキャッシュ: データベースドライバーを、Data Grid Server インストールの
server/lib
ディレクトリーにコピーします。 組み込みキャッシュ:
infinispan-cachestore-sql
依存関係をpom
ファイルに追加し、データベースドライバーがアプリケーションクラスパス上にあることを確認します。<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-cachestore-sql</artifactId> </dependency>
-
リモートキャッシュ: データベースドライバーを、Data Grid Server インストールの
- Data Grid 設定を開いて編集します。
SQL クエリーキャッシュストアを追加します。
宣言的
query-jdbc-store xmlns="urn:infinispan:config:store:jdbc:13.0"
プログラマティック
persistence().addStore(QueriesJdbcStoreConfigurationBuilder.class)
-
データベースダイアレクトを
dialect=""
またはdialect()
のいずれかで指定します (例:dialect="H2"
またはdialect="postgres")
。 以下のように、必要なプロパティーで SQL キャッシュストアを設定します。
-
クラスター全体で同じキャッシュストアを使用するには、
shared="true"
またはshared(true)
を設定します。 -
読み取り専用のキャッシュストアを作成するには、
read-only="true"
または.ignoreModifications(true)
を設定します。
-
クラスター全体で同じキャッシュストアを使用するには、
データでキャッシュを読み込み、
queries
要素またはqueries()
メソッドでデータベーステーブルを変更する SQL クエリーステートメントを定義します。クエリーステートメント 説明 SELECT
単一のエントリーをキャッシュに読み込みます。ワイルドカードを使用できますが、キーのパラメーターを指定する必要があります。ラベル付きの式を使用できます。
SELECT ALL
複数のエントリーをキャッシュに読み込みます。返された列の数がキーと値の列数と一致する場合は、
*
ワイルドカードを使用できます。ラベル付きの式を使用できます。SIZE
キャッシュ内のエントリー数をカウントします。
DELETE
キャッシュからエントリーを 1 つ削除します。
DELETE ALL
キャッシュからすべてのエントリーを削除します。
UPSERT
キャッシュのエントリーを修正します。
注記DELETE
、DELETE ALL
、およびUPSERT
ステートメントは読み取り専用キャッシュストアには適用されませんが、キャッシュストアが変更を許可する場合は必要です。DELETE
ステートメントのパラメーターは、SELECT
ステートメントのパラメーターに完全に一致する必要があります。UPSERT
ステートメントの変数には、SELECT
およびSELECT ALL
ステートメントが返すものと同じ数の一意に名前が付けられた変数が必要です。たとえば、SELECT
がfoo
とbar
を返す場合、このステートメントは変数として:foo
および:bar
のみを取る必要があります。ただし、ステートメントに同じ名前の変数を複数回適用することができます。SQL クエリーには、
JOIN
、ON
およびデータベースがサポートするその他の句を含めることができます。schema
要素または.schemaJdbcConfigurationBuilder()
メソッドを追加し、複合キーまたは値の Protobuf スキーマ設定を追加します。-
package
属性またはpackage()
メソッドを使用してパッケージ名を指定します。 -
message-name
属性またはmessageName()
メソッドを使用して複合値を指定します。 -
key-message-name
属性またはkeyMessageName()
メソッドを使用して複合キーを指定します。 -
スキーマで値内にキーが含まれている場合は、
embedded-key
属性またはembeddedKey()
メソッドにtrue
の値を設定します。
-
- 変更を設定に保存します。
関連情報
6.10.3.1. SQL クエリーストアの設定
このセクションでは、person と address の 2 つのデータベーステーブルのデータを含む分散キャッシュを読み込む SQL クエリーキャッシュストアの設定例を説明します。
SQL ステートメント
person および address テーブルの SQL データ定義言語 (DDL) ステートメントは以下のとおりです。
person テーブルの SQL ステートメント
CREATE TABLE Person ( name VARCHAR(255) NOT NULL, picture VARBINARY(255), sex VARCHAR(255), birthdate TIMESTAMP, accepted_tos BOOLEAN, notused VARCHAR(255), PRIMARY KEY (name) );
address テーブルの SQL ステートメント
CREATE TABLE Address ( name VARCHAR(255) NOT NULL, street VARCHAR(255), city VARCHAR(255), zip INT, PRIMARY KEY (name) );
Protobuf スキーマ
person および address テーブルの Protobuf スキーマは以下のとおりです。
person テーブルの Protobuf スキーマ
package com.example enum Sex { FEMALE = 1; MALE = 2; } message Person { optional string name = 1; optional Address address = 2; optional bytes picture = 3; optional Sex sex = 4; optional fixed64 birthDate = 5 [default = 0]; optional bool accepted_tos = 6 [default = false]; }
address テーブルの Protobuf スキーマ
package com.example message Address { optional string street = 1; optional string city = 2 [default = "San Jose"]; optional int32 zip = 3 [default = 0]; }
キャッシュ設定
以下の例では、JOIN
句を含む SQL クエリーを使用して、person テーブルおよび address テーブルから分散キャッシュを読み込みます。
XML
<distributed-cache> <persistence> <query-jdbc-store xmlns="urn:infinispan:config:store:jdbc:13.0" dialect="POSTGRES" shared="true"> <queries key-columns="name"> <select-single>SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name WHERE t1.name = :name</select-single> <select-all>SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name</select-all> <delete-single>DELETE FROM Person t1 WHERE t1.name = :name; DELETE FROM Address t2 where t2.name = :name</delete-single> <delete-all>DELETE FROM Person; DELETE FROM Address</delete-all> <upsert>INSERT INTO Person (name, picture, sex, birthdate, accepted_tos) VALUES (:name, :picture, :sex, :birthdate, :accepted_tos); INSERT INTO Address(name, street, city, zip) VALUES (:name, :street, :city, :zip)</upsert> <size>SELECT COUNT(*) FROM Person</size> </queries> <schema message-name="Person" package="com.example" embedded-key="true"/> </query-jdbc-store> </persistence> <distributed-cache>
JSON
{ "distributed-cache": { "persistence": { "query-jdbc-store": { "dialect": "POSTGRES", "shared": "true", "key-columns": "name", "queries": { "select-single": "SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name WHERE t1.name = :name", "select-all": "SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name", "delete-single": "DELETE FROM Person t1 WHERE t1.name = :name; DELETE FROM Address t2 where t2.name = :name", "delete-all": "DELETE FROM Person; DELETE FROM Address", "upsert": "INSERT INTO Person (name, picture, sex, birthdate, accepted_tos) VALUES (:name, :picture, :sex, :birthdate, :accepted_tos); INSERT INTO Address(name, street, city, zip) VALUES (:name, :street, :city, :zip)", "size": "SELECT COUNT(*) FROM Person" }, "schema": { "message-name": "Person", "package": "com.example", "embedded-key": "true" } } } } }
YAML
distributedCache: persistence: queryJdbcStore: dialect: "POSTGRES" shared: "true" keyColumns: "name" queries: selectSingle: "SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name WHERE t1.name = :name" selectAll: "SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name" deleteSingle: "DELETE FROM Person t1 WHERE t1.name = :name; DELETE FROM Address t2 where t2.name = :name" deleteAll: "DELETE FROM Person; DELETE FROM Address" upsert: "INSERT INTO Person (name, picture, sex, birthdate, accepted_tos) VALUES (:name, :picture, :sex, :birthdate, :accepted_tos); INSERT INTO Address(name, street, city, zip) VALUES (:name, :street, :city, :zip)" size: "SELECT COUNT(*) FROM Person" schema: messageName: "Person" package: "com.example" embeddedKey: "true"
ConfigurationBuilder
ConfigurationBuilder builder = new ConfigurationBuilder(); builder.persistence().addStore(QueriesJdbcStoreConfigurationBuilder.class) .dialect(DatabaseType.POSTGRES) .shared("true") .keyColumns("name") .queriesJdbcConfigurationBuilder() .select("SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name WHERE t1.name = :name") .selectAll("SELECT t1.name, t1.picture, t1.sex, t1.birthdate, t1.accepted_tos, t2.street, t2.city, t2.zip FROM Person t1 JOIN Address t2 ON t1.name = t2.name") .delete("DELETE FROM Person t1 WHERE t1.name = :name; DELETE FROM Address t2 where t2.name = :name") .deleteAll("DELETE FROM Person; DELETE FROM Address") .upsert("INSERT INTO Person (name, picture, sex, birthdate, accepted_tos) VALUES (:name, :picture, :sex, :birthdate, :accepted_tos); INSERT INTO Address(name, street, city, zip) VALUES (:name, :street, :city, :zip)") .size("SELECT COUNT(*) FROM Person") .schemaJdbcConfigurationBuilder() .messageName("Person") .packageName("com.example") .embeddedKey(true);
6.10.4. SQL キャッシュストアに関するトラブルシューティング
SQL キャッシュストアに関する一般的な問題およびエラーと、そのトラブルシューティング方法を確認してください。
ISPN008064: No primary keys found for table <table_name>, check case sensitivity
Data Grid は、以下の場合にこのメッセージをログに記録します。
- データベーステーブルが存在しない。
- データベーステーブル名は大文字と小文字が区別され、データベースプロバイダーに応じて、すべての小文字またはすべての大文字のいずれかである必要があります。
- データベーステーブルにプライマリーキーが定義されていない。
この問題を解決するには、以下を行う必要があります。
- SQL キャッシュストア設定を確認し、既存のテーブルの名前を指定するようにしてください。
- データベーステーブル名が大文字/小文字の要件に準拠することを確認します。
- データベーステーブルに、適切な行を一意に識別するプライマリーキーがあることを確認します。