Red Hat Data Virtualization 複数 DB の結合
Data Virtualization を実現するには以下 3 種類の方法があります。
- Data Virtualization Operator を使用
- Fuse Online からデザイン
- SpringBoot で実装
今回のお話は SpringBoot を使って実装する方法をもっと具体的にしたものです。
0. 仮想化対象のデータベース
customer テーブル(Postgresql)
address テーブル(MySQL)
customer テーブルに address テーブルを左結合します。その際 CUSTOMER_ID を使用します。このようなとき、Teiid SpringBoot ではどのように実装するのかまとめます。
上記にデータベースのイメージをあげているので以下のコマンドで起動すれば仮想化対象のデータベースは準備完了です。
$ docker run -d --name customerdb --rm -p 5432:5432 kkosugi/customerdb:v1
$ docker run -d --name addressdb --rm -p 3306:3306 kkosugi/addressdb:v1
1. Spring Initializr でプロジェクトの雛形を生成
2.1.12 (2020/1月時点で 2.1 台の最後のリリース) を選択して Maven プロジェクトを作成します。
プロジェクトが作成されたらダウンロードして IDE が使用するワークスペースの下にコピーします。
Spring Initializr を使用することのメリットは Maven がインストールされていない環境でも Maven が動作できるよう mvnw を作ってくれるところにあります。
2. pom.xml の編集
IDE にプロジェクトをインポートして、pom.xml に幾つかの変更を加えます。
- properties
- dependencyManagement
- dependency
properties
version.teiid.spring-boot で teiid のバージョンを追加します。今回は 2020/1 時点で最新の 1.3.0 を指定。
<properties>
<java.version>11</java.version>
<version.teiid.spring-boot>1.3.0</version.teiid.spring-boot>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
dependencyMangement
pom.xml の後方にまるっとコピー。Maven の settings.xml にコピーする方法もありますが、全プロジェクトが参照できてしまうため Teiid SpringBoot の pom.xml に記載すれば問題ないと思います。
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.teiid</groupId>
<artifactId>teiid-spring-boot-starter-parent</artifactId>
<version>${version.teiid.spring-boot}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
dependency
データベース仮想化対象への接続に使用する JDBC(例は Postgresql と MySQL)と、teiid-spring-boot-starter を指定します。spring-odata は OData を使用しない場合は不要です。ライブラリは Maven Central Repository のもので問題ありません。
<dependency>
<groupId>org.teiid</groupId>
<artifactId>teiid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.teiid</groupId>
<artifactId>spring-odata</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
3. ソースコードの追加
まず、main 文は SpringBoot Initializr が作ってくれるので省略。Red Hat のドキュメントを参照すると mvn archetype generate で作っちゃうので main 文も自分で書かなきゃいけないです。そしてこの資料はタイポがあって単純にコピー&ペーストではうまく機能しないので気を付けてください。
おまじないのように以下のコードを追加。
これは何しているかというと SpringBoot のコンフィグファイルから値を読み取って、JDBC の DataSource を作っているだけです。prefix = “spring.datasource.customerds” の部分とメソッド名 customerds() の太字は合わせてください。
spring.datasource.xxxx は application.yml / application.properties で登場します。
4. SpringBoot コンフィグファイル
今回は application.yml でご紹介。
prefix に出てきた spring.datasoruce.customerds で Postgresql への接続を定義、addressds で MySQL への接続を定義しています。
teiid.jdbc-enabling を true にしないと Teiid SpringBoot に JDBC 接続できなくなるので注意です。SpringBoot 内でしか Postgresql や MySQL へのデータソースを使えなくなる Embedded モードになるので、この場合更なるコーディングが必要となります。
5. VDB ファイル
VDB ファイルは必須ではないのですが、今回のように異なる RDBMS にあるテーブル同士を結合したいなんて時は必要になります。
-- This is simple VDB that connects to a single PostgreSQL database and exposes it
-- as a Virtual Database.
-- create database
CREATE DATABASE sampledb OPTIONS (ANNOTATION 'Customer VDB');
USE DATABASE sampledb;
-- create translators and connections to source
CREATE FOREIGN DATA WRAPPER postgresql;
CREATE FOREIGN DATA WRAPPER mysql;
CREATE SERVER customerds TYPE 'NONE' FOREIGN DATA WRAPPER postgresql OPTIONS ("jndi-name" 'customerds');
CREATE SERVER addressds TYPE 'NONE' FOREIGN DATA WRAPPER mysql OPTIONS ("jndi-name" 'addressds');
-- create schema, then import the metadata from the PostgreSQL database
CREATE SCHEMA a SERVER customerds;
CREATE SCHEMA b SERVER addressds;
CREATE VIRTUAL SCHEMA portfolio;
SET SCHEMA a;
IMPORT FOREIGN SCHEMA public FROM SERVER customerds INTO a OPTIONS("importer.useFullSchemaName" 'true');
SET SCHEMA b;
IMPORT FOREIGN SCHEMA address FROM SERVER addressds INTO b OPTIONS("importer.useFullSchemaName" 'true');
SET SCHEMA portfolio;
CREATE VIEW CustomerZip(id long PRIMARY KEY, name string, ssn string, zip string) AS
SELECT b.ID as id, b.NAME as name, b.SSN as ssn, c.ZIP as zip
FROM a.public.customer b LEFT OUTER JOIN b.address.ADDRESS c
ON b.ID = c.CUSTOMER_ID;
Teiid SpringBoot の起動
$ ./mvnw clean package spring-boot:run
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------< com.redhat.integration:multi-rdbms >-----------------
[INFO] Building multi-rdbms 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ multi-rdbms ---
[INFO] Deleting /Users/kkosugi/IdeaProjects/data-virtualization/multi-rdbms/target
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ multi-rdbms ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ multi-rdbms ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to /Users/kkosugi/IdeaProjects/data-virtualization/multi-rdbms/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ multi-rdbms ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/kkosugi/IdeaProjects/data-virtualization/multi-rdbms/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ multi-rdbms ---
[INFO] Changes detected - recompiling the module!
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ multi-rdbms ---
〜略〜
今回 VDB として sampledb を作成し portfolio というスキーマを定義していますが、その通りにログが出力されていることがわかります。
TEIID50029 VDB sampledb.1 model "portfolio" metadata is currently being loaded. Start Time: 2020/01/28 12:25
JDBC クライアントから接続
DataGrip などの JDBC クライアントを使用して Teiid SpringBoot に JDBC アクセスしてみましょう。JDBC の接続文字列は以下のとおりです。
jdbc:teiid:sampledb@mm://localhost:31000
OData へ接続
ブラウザから以下の URL を実行して動作を確認します。
- http://localhost:8080/odata
- http://localhost:8080/odata/portfolio/CustomerZip
- http://localhost:8080/odata/portfolio/CustomerZip?$format=json
- http://localhost:8080/odata/portfolio/CustomerZip(12)?$format=json
参考までに 4 は以下のような表示になります。
クリーンアップ
Teiid SpringBoot の停止
control + c で停止
仮想化対象のデータベースの停止
$ docker stop customerdb
$ docker stop addressdb