Help us understand the problem. What is going on with this article?

MySQL Connector/J 8.0.15 で X DevAPI を使ってドキュメントデータベース操作をしてみる

More than 1 year has passed since last update.

MySQL 8.0 では、

  • JSON 機能
  • X DevAPI

を活用すればドキュメントデータベース(ドキュメントストア)としても使えるよ、ということなので、遅ればせながら Java(8)環境で MySQL Connector/J を使って試してみました。


【参考】


準備

以下を同一のマシン(Windows PC でも Linux 仮想マシンでも OK)にインストールします。

  • MySQL Community Server 8.0.15
  • Java SE 8 JDK / JRE(とりあえず OpenJDK ベースものなら大丈夫かと)
  • MySQL Connector/J 8.0.15
  • テストコード(後述)

※テストコードから MySQL Connector/J にパスを通した状態で .jar 化するなどしてください。面倒なのでわたしは Windows 10 に MySQL Community Server をインストールし、Maven で MySQL Connector/J を組み込んで Eclipse 上でコードを実行しました。

次に、MySQL(Community)Server 上にテスト用のユーザを登録しておきます(コマンドラインからでも MySQL Workbench からでも OK)。

  • ユーザ名はtestuser@localhost
  • パスワードはT35_U53r
  • SELECT, INSERT, UPDATE, DELETE 権限
  • 認証はcaching_sha2_passwordでもmysql_native_passwordでも OK

最後に、CREATE DATABASEなどで DB(スキーマ)test_dbを作成して準備完了です。

テストコードの説明

↓が簡単なドキュメント処理をするテストコードです。

テストコード
package site.hmatsu47.DocDbTest;

import java.util.List;

import com.mysql.cj.xdevapi.Collection;
import com.mysql.cj.xdevapi.DbDoc;
import com.mysql.cj.xdevapi.DocResult;
import com.mysql.cj.xdevapi.Schema;
import com.mysql.cj.xdevapi.Session;
import com.mysql.cj.xdevapi.SessionFactory;


public class Main {

    public static void main(String args[]) {
        // サーバに接続
        Session session = new SessionFactory().getSession("mysqlx://localhost:33060/test_db?user=testuser&password=T35_U53r");

        // DBに接続
        Schema db = session.getSchema("test_db");

        // コレクション'test_collection'を作成
        Collection col = db.createCollection("test_collection", true);

        // コレクションにドキュメントを追加
        col.add("{\"id\":1, \"name\":\"さくらばさん\", \"Program\":\"Java Champion\"}")
                .execute();
        col.add("{\"id\":2, \"name\":\"よくさん\", \"Program\":\"Oracle ACE\"}")
                .execute();
        col.add("{\"id\":3, \"name\":\"せろさん\", \"Program\":[\"Java Champion\",\"Oracle Groundbreaker Ambassador\"]}")
                .execute();
        col.add("{\"id\":4, \"name\":\"とみたさん\", \"Program\":\"Oracle ACE Associate\"}")
                .execute();
        col.add("{\"id\":5, \"name\":\"みたにさん\", \"Program\":\"Oracle ACE\"}")
                .execute();

        // 本題とは関係ないのですが、OracleのACE・Groundbreaker・Java ChampionのDBにじゅくちょーさんが見当たらないのです…

        // コレクションの「id」列にインデックスを追加
        col.createIndex("id_index", "{\"fields\": [{\"field\": \"$.id\", \"type\": \"INT\"}]}");

        // コレクションから「Program LIKE '%Oracle%'」を探して表示
        searchProgram(col, "Oracle");

        System.out.println();

        // コレクションから「Program LIKE '%Java%'」を探して表示
        searchProgram(col, "Java");

        System.out.println();

        // コレクションから「id=2」を探して表示
        searchId(col, 2);

        System.out.println();

        // コレクションから「id=4」を探して表示
        searchId(col, 4);

        // コレクションを削除
        db.dropCollection("test_collection");
    }

    // コレクションから対象ドキュメントの「Program」を文字列検索して表示する
    private static void searchProgram(Collection col, String keyword) {

        System.out.println("Search: " + keyword);
        DocResult docs = col.find("Program like :program")
                .bind("program", "%" + keyword + "%").execute();

        // 結果を取得して表示
        List<DbDoc> docl = docs.fetchAll();
        docl.forEach(doc -> System.out.println(doc.toFormattedString()));
    }

    // コレクションから対象ドキュメントの「id」を数値検索して表示する
    private static void searchId(Collection col, long value) {

        System.out.println("Search: " + value);
        DocResult docs = col.find("id = :id")
                .bind("id", value).execute();

        // 結果を取得して表示
        System.out.println(docs.fetchOne().toFormattedString());
    }
}

new SessionFactory().getSession()で引数にURLを指定して DB サーバに接続し、session.getSchema();で引数にスキーマ(DB)名を指定して DB に接続しています。

なお、URLはその名の通りURLですので、パスワードに記号を使っている場合は適宜エスケープ処理をしてください(わたしはうっかりミスをして小一時間悩みました)。

その後、順に

  • ドキュメントコレクションの新規作成(同名のものが既に存在するときはそのまま使う)
  • ドキュメントコレクションにドキュメントを追加(計 5 行)
  • インデックス作成
  • 文字列LIKE検索
  • 数値検索(インデックス使用を意図したもの)
  • ドキュメントコレクションの削除

を行っています。

見ての通り、文字列LIKE検索では、1 つのドキュメントに同じ名前の要素を複数持つ場合でも正しく検索されていることがわかります。

実行途中にテーブル設計を見るとこうなります(SHOW CREATE TABLE test_db.test_collection;

test_collectionのテーブル設計
CREATE TABLE `test_collection` (
  `doc` json DEFAULT NULL,
  `_id` varbinary(32) GENERATED ALWAYS AS (json_unquote(json_extract(`doc`,_utf8mb4'$._id'))) STORED NOT NULL,
  `$ix_i_C6EF652A87142734264FBA60F41C59108CF4D8CA` int(11) GENERATED ALWAYS AS (json_extract(`doc`,_utf8mb4'$.id')) VIRTUAL,
  PRIMARY KEY (`_id`),
  KEY `id_index` (`$ix_i_C6EF652A87142734264FBA60F41C59108CF4D8CA`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

また、実行結果はこうなります。

実行結果
Search: Oracle
{
"Program" : "Oracle ACE",
"_id" : "00005c8ded80000000000000006b",
"id" : 2,
"name" : "よくさん"
}
{
"Program" : ["Java Champion", "Oracle Groundbreaker Ambassador"],
"_id" : "00005c8ded80000000000000006c",
"id" : 3,
"name" : "せろさん"
}
{
"Program" : "Oracle ACE Associate",
"_id" : "00005c8ded80000000000000006d",
"id" : 4,
"name" : "とみたさん"
}
{
"Program" : "Oracle ACE",
"_id" : "00005c8ded80000000000000006e",
"id" : 5,
"name" : "みたにさん"
}

Search: Java
{
"Program" : "Java Champion",
"_id" : "00005c8ded80000000000000006a",
"id" : 1,
"name" : "さくらばさん"
}
{
"Program" : ["Java Champion", "Oracle Groundbreaker Ambassador"],
"_id" : "00005c8ded80000000000000006c",
"id" : 3,
"name" : "せろさん"
}

Search: 2
{
"Program" : "Oracle ACE",
"_id" : "00005c8ded80000000000000006b",
"id" : 2,
"name" : "よくさん"
}

Search: 4
{
"Program" : "Oracle ACE Associate",
"_id" : "00005c8ded80000000000000006d",
"id" : 4,
"name" : "とみたさん"
}

その他

X DevAPI には、ほかにも

  • 非同期処理
  • リレーショナルな DB スキーマに対する CRUD 等の操作
  • トランザクション処理

など、いくつかの機能があります。


hmatsu47
名古屋で士業向けWebサービスのインフラ構築管理、たまにアプリケーション開発をやっています。 業務利用しているもの、個人研究など、気長にのんびり投稿していきます。ニッチ狙いが多めです。 IPA RISS(001158)・NW・DB/日商・大商2級コレクター?(簿記・ビジネス法務・ビジネス会計)。 https://hmatsu47.qrunch.io/
https://hmatsu47.hatenablog.com/
infra-workshop
インフラ技術を勉強したい人たちのためのオンライン勉強会です
https://wp.infra-workshop.tech/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away