Skip to content

Ignite上のデータをDBに永続化

Ignite上にキャッシュされたデータをDB上に永続化するための設定です。

cf. https://ignite.apache.org/docs/ignite2/latest/persistence/external-storage

事前準備

下記SQLによって構築されるデータベースに向けてデータを永続化することを想定します:

CREATE DATABASE eadb;
USE eadb;

CREATE TABLE IF NOT EXISTS users (
    id bigint PRIMARY KEY
    , name varchar(8)
    , password varchar(32)
    , age int
);

設定

エンティティ提供モジュール

mvnコマンドで作成したmavenプロジェクト上に実装することを想定しています。

依存関係追加

lombokを使う場合はpom.xmlに下記を追記します:

    <dependencies>
        <!-- Source: https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.44</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.13.0</version>
                <configuration>
                    <annotationProcessorPaths>
                        <path>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                            <version>1.18.44</version>
                        </path>
                    </annotationProcessorPaths>
                </configuration>
            </plugin>
        </plugins>
    </build>

エンティティ実装

エンティティを提供するモジュールはIgniteおよび業務アプリケーションの両方から参照されるため、独立したモジュールとして用意します。下記要領でエンティティクラスを実装します:

package nob.example.domain.entity;

import lombok.AllArgsConstructor;
import lombok.Getter;

/**
 * usersテーブル向けのエンティティクラスです。
 *
 * @author nob
 */
@Getter
@AllArgsConstructor
public class Users {

    /** 管理ID */
    private Long id;

    /** ユーザ名 */
    private String name;

    /** パスワード */
    private String password;

    /** 年齢 */
    private Integer age;
}

実装後、mvn clean installコマンドでjarファイルを用意してください。

Ignite

依存モジュールの準備

先に作成したエンティティ提供モジュールおよびmysql-connector-jについて、libs/nob/配下に配置し、下記環境変数でこれらのモジュールをIgniteが認識できるようにします:

export USER_LIBS=${IGNITE_HOME}/libs/nob

設定ファイル作成

キャッシュの永続化について記載した下記設定ファイルについて、config/nob-config.xmlとして配置します:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="         http://www.springframework.org/schema/beans              http://www.springframework.org/schema/beans/spring-beans.xsd              http://www.springframework.org/schema/util              http://www.springframework.org/schema/util/spring-util.xsd">
    <!-- データベース接続先設定 -->
    <bean class="com.mysql.cj.jdbc.MysqlDataSource" id="mysqlDataSource">
        <property name="URL" value="jdbc:mysql://localhost:3306/eadb"/>
        <property name="user" value="root"/>
        <property name="password" value="password"/>
    </bean>
    <bean class="org.apache.ignite.configuration.IgniteConfiguration">
        <property name="cacheConfiguration">
            <list>
                <bean class="org.apache.ignite.configuration.CacheConfiguration">
                    <property name="name" value="UsersCache"/>
                    <property name="cacheMode" value="PARTITIONED"/>
                    <property name="atomicityMode" value="ATOMIC"/>
                    <property name="cacheStoreFactory">
                        <bean class="org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory">
                            <property name="dataSourceBean" value="mysqlDataSource"/>
                            <property name="dialect">
                                <bean class="org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect"/>
                            </property>
                            <property name="types">
                                <list>
                                    <!-- usersテーブル向けキャッシュ設定 -->
                                    <bean class="org.apache.ignite.cache.store.jdbc.JdbcType">
                                        <property name="cacheName" value="UsersCache"/>
                                        <property name="keyType" value="java.lang.Long"/>
                                        <property name="valueType" value="nob.example.domain.entity.Users"/>
                                        <property name="databaseTable" value="users"/>
                                        <property name="keyFields">
                                            <list>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.BIGINT"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="id"/>
                                                    <constructor-arg value="java.lang.Long"/>
                                                    <constructor-arg value="id"/>
                                                </bean>
                                            </list>
                                        </property>
                                        <property name="valueFields">
                                            <list>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.VARCHAR"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="name"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="name"/>
                                                </bean>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.VARCHAR"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="password"/>
                                                    <constructor-arg value="java.lang.String"/>
                                                    <constructor-arg value="password"/>
                                                </bean>
                                                <bean class="org.apache.ignite.cache.store.jdbc.JdbcTypeField">
                                                    <constructor-arg>
                                                        <util:constant static-field="java.sql.Types.INTEGER"/>
                                                    </constructor-arg>
                                                    <constructor-arg value="age"/>
                                                    <constructor-arg value="java.lang.Integer"/>
                                                    <constructor-arg value="age"/>
                                                </bean>
                                            </list>
                                        </property>
                                    </bean>
                                </list>
                            </property>
                        </bean>
                    </property>
                    <!-- see; https://www.javadoc.io/doc/org.apache.ignite/ignite-core/2.17.0/org/apache/ignite/configuration/CacheConfiguration.html -->
                    <property name="readThrough" value="true"/>
                    <property name="writeThrough" value="true"/>
                    <property name="writeBehindEnabled" value="true"/>
                    <property name="writeBehindFlushFrequency" value="5000"/>
                    <!-- Ignite上でSQLクエリを有効化する -->
                    <property name="queryEntities">
                        <list>
                            <bean class="org.apache.ignite.cache.QueryEntity">
                                <property name="keyType" value="java.lang.Long"/>
                                <property name="valueType" value="nob.example.domain.entity.Users"/>
                                <property name="keyFieldName" value="id"/>
                                <property name="keyFields">
                                    <list>
                                        <value>id</value>
                                    </list>
                                </property>
                                <property name="fields">
                                    <map>
                                        <entry key="id" value="java.lang.Long"/>
                                        <entry key="name" value="java.lang.String"/>
                                        <entry key="password" value="java.lang.String"/>
                                        <entry key="age" value="java.lang.Integer"/>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </property>
                </bean>
            </list>
        </property>
    </bean>
</beans>

起動

下記コマンドでIgniteを起動します:

./bin/ignite.sh config/nob-config.xml

業務アプリケーションモジュール

Spring Initializrによって作成されたSpring Bootプロジェクト上に実装することを想定しています。

依存関係追加

下記をpom.xmlに追加します:

    <dependencies>
        <!-- Source: https://mvnrepository.com/artifact/org.apache.ignite/ignite-core -->
        <dependency>
            <groupId>org.apache.ignite</groupId>
            <artifactId>ignite-core</artifactId>
            <version>2.17.0</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>nob.example</groupId>
            <artifactId>sharedapp</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

データ登録処理実装

package nob.example.easyapp;

import org.apache.ignite.Ignite;
import org.apache.ignite.IgniteCache;
import org.apache.ignite.Ignition;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import nob.example.domain.entity.Users;

@SpringBootApplication
public class EasyappApplication {

    public static void main(String[] args) {

        IgniteConfiguration cfg = new IgniteConfiguration();
        cfg.setClientMode(true);

        try (Ignite ignite = Ignition.start(cfg)) {

            IgniteCache<Long, Users> cache = ignite.cache("UsersCache");

            Users users = new Users(1L, "nob", "passwd", 13);
            cache.put(users.getId(), users);
        }
    }
}

動作確認

-- キャッシュ上のデータ確認
SELECT * FROM "UsersCache"."USERS";
-- DB上のデータ確認
SELECT * FROM users;