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 ステートメントは、isbntitle の 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 タイプ

int4

int32

int8

int64

float4

float

float8

double

numeric

double

bool

bool

char

string

varchar

string

texttinytextmediumtextlongtext

string

byteatinyblobBlobmediumbloblongblob

bytes

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 を使用してスキーマを追加して、スキーマを登録できます。

手順

  1. データベースドライバーを Data Grid デプロイメントに追加します。

    • リモートキャッシュ: データベースドライバーを、Data Grid Server インストールの server/lib ディレクトリーにコピーします。
    • 組み込みキャッシュ: infinispan-cachestore-sql 依存関係を pom ファイルに追加します。

      <dependency>
        <groupId>org.infinispan</groupId>
        <artifactId>infinispan-cachestore-sql</artifactId>
      </dependency>
  2. Data Grid 設定を開いて編集します。
  3. SQL テーブルキャッシュストアを追加します。

    宣言的

    table-jdbc-store xmlns="urn:infinispan:config:store:sql:13.0"

    プログラマティック

    persistence().addStore(TableJdbcStoreConfigurationBuilder.class)

  4. データベースダイアレクトを dialect="" または dialect() のいずれかで指定します (例:dialect="H2" または dialect="postgres")
  5. 以下のように、必要なプロパティーで SQL キャッシュストアを設定します。

    • クラスター全体で同じキャッシュストアを使用するには、shared="true" または shared(true) を設定します。
    • 読み取り専用のキャッシュストアを作成するには、read-only="true" または .ignoreModifications(true) を設定します。
  6. table-name="<database_table_name>" または table.name("<database_table_name>") を使用して、キャッシュを読み込むデータベーステーブルに名前を付けます。
  7. schema 要素または .schemaJdbcConfigurationBuilder() メソッドを追加し、複合キーまたは値の Protobuf スキーマ設定を追加します。

    1. package 属性または package() メソッドを使用してパッケージ名を指定します。
    2. message-name 属性または messageName() メソッドを使用して複合値を指定します。
    3. key-message-name 属性または keyMessageName() メソッドを使用して複合キーを指定します。
    4. スキーマで値内にキーが含まれている場合は、embedded-key 属性または embeddedKey() メソッドに true の値を設定します。
  8. 変更を設定に保存します。
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 を使用してスキーマを追加して、スキーマを登録できます。

手順

  1. データベースドライバーを Data Grid デプロイメントに追加します。

    • リモートキャッシュ: データベースドライバーを、Data Grid Server インストールの server/lib ディレクトリーにコピーします。
    • 組み込みキャッシュ: infinispan-cachestore-sql 依存関係を pom ファイルに追加し、データベースドライバーがアプリケーションクラスパス上にあることを確認します。

      <dependency>
        <groupId>org.infinispan</groupId>
        <artifactId>infinispan-cachestore-sql</artifactId>
      </dependency>
  2. Data Grid 設定を開いて編集します。
  3. SQL クエリーキャッシュストアを追加します。

    宣言的

    query-jdbc-store xmlns="urn:infinispan:config:store:jdbc:13.0"

    プログラマティック

    persistence().addStore(QueriesJdbcStoreConfigurationBuilder.class)

  4. データベースダイアレクトを dialect="" または dialect() のいずれかで指定します (例:dialect="H2" または dialect="postgres")
  5. 以下のように、必要なプロパティーで SQL キャッシュストアを設定します。

    • クラスター全体で同じキャッシュストアを使用するには、shared="true" または shared(true) を設定します。
    • 読み取り専用のキャッシュストアを作成するには、read-only="true" または .ignoreModifications(true) を設定します。
  6. データでキャッシュを読み込み、queries 要素または queries() メソッドでデータベーステーブルを変更する SQL クエリーステートメントを定義します。

    クエリーステートメント説明

    SELECT

    単一のエントリーをキャッシュに読み込みます。ワイルドカードを使用できますが、キーのパラメーターを指定する必要があります。ラベル付きの式を使用できます。

    SELECT ALL

    複数のエントリーをキャッシュに読み込みます。返された列の数がキーと値の列数と一致する場合は、* ワイルドカードを使用できます。ラベル付きの式を使用できます。

    SIZE

    キャッシュ内のエントリー数をカウントします。

    DELETE

    キャッシュからエントリーを 1 つ削除します。

    DELETE ALL

    キャッシュからすべてのエントリーを削除します。

    UPSERT

    キャッシュのエントリーを修正します。

    注記

    DELETEDELETE ALL、および UPSERT ステートメントは読み取り専用キャッシュストアには適用されませんが、キャッシュストアが変更を許可する場合は必要です。

    DELETE ステートメントのパラメーターは、SELECT ステートメントのパラメーターに完全に一致する必要があります。

    UPSERT ステートメントの変数には、SELECT および SELECT ALL ステートメントが返すものと同じ数の一意に名前が付けられた変数が必要です。たとえば、SELECTfoobar を返す場合、このステートメントは変数として :foo および :bar のみを取る必要があります。ただし、ステートメントに同じ名前の変数を複数回適用することができます。

    SQL クエリーには、JOINON およびデータベースがサポートするその他の句を含めることができます。

  7. schema 要素または .schemaJdbcConfigurationBuilder() メソッドを追加し、複合キーまたは値の Protobuf スキーマ設定を追加します。

    1. package 属性または package() メソッドを使用してパッケージ名を指定します。
    2. message-name 属性または messageName() メソッドを使用して複合値を指定します。
    3. key-message-name 属性または keyMessageName() メソッドを使用して複合キーを指定します。
    4. スキーマで値内にキーが含まれている場合は、embedded-key 属性または embeddedKey() メソッドに true の値を設定します。
  8. 変更を設定に保存します。

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 は、以下の場合にこのメッセージをログに記録します。

  • データベーステーブルが存在しない。
  • データベーステーブル名は大文字と小文字が区別され、データベースプロバイダーに応じて、すべての小文字またはすべての大文字のいずれかである必要があります。
  • データベーステーブルにプライマリーキーが定義されていない。

この問題を解決するには、以下を行う必要があります。

  1. SQL キャッシュストア設定を確認し、既存のテーブルの名前を指定するようにしてください。
  2. データベーステーブル名が大文字/小文字の要件に準拠することを確認します。
  3. データベーステーブルに、適切な行を一意に識別するプライマリーキーがあることを確認します。
Red Hat logoGithubRedditYoutubeTwitter

詳細情報

試用、購入および販売

コミュニティー

Red Hat ドキュメントについて

Red Hat をお使いのお客様が、信頼できるコンテンツが含まれている製品やサービスを活用することで、イノベーションを行い、目標を達成できるようにします。

多様性を受け入れるオープンソースの強化

Red Hat では、コード、ドキュメント、Web プロパティーにおける配慮に欠ける用語の置き換えに取り組んでいます。このような変更は、段階的に実施される予定です。詳細情報: Red Hat ブログ.

会社概要

Red Hat は、企業がコアとなるデータセンターからネットワークエッジに至るまで、各種プラットフォームや環境全体で作業を簡素化できるように、強化されたソリューションを提供しています。

© 2024 Red Hat, Inc.