主要NoSQLおよびリレーショナルデータベースにおけるJavaクライアント実装比較

依存関係の構成

各データベースシステムとJavaアプリケーションを連携させるため、Mavenプロジェクトの依存関係定義ファイルに以下のライブラリを追加します。

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>
    <dependency>
        <groupId>redis.clients</groupId>
        <artifactId>jedis</artifactId>
        <version>3.7.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-shaded-client</artifactId>
        <version>2.4.15</version>
    </dependency>
</dependencies>

JDBCを用いたMySQL操作

リレーショナルデータベースへのアクセスにはJDBC APIを利用します。リソースの確実な解放とSQLインジェクション対策のため、try-with-resources構文およびPreparedStatementを採用しています。

package jp.tech.dataaccess.sql;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class JdbcLearnerManager {
    private static final String DB_URL = "jdbc:mysql://127.0.0.1:3306/academy_db";
    private static final String DB_USER = "admin";
    private static final String DB_PASS = "securePass99";

    public static void main(String[] args) {
        String insertQuery = "INSERT INTO LearnerProfile (Full_Name, Lang_Score, Logic_Score, Tech_Score) VALUES (?, ?, ?, ?)";
        String fetchQuery = "SELECT Full_Name, Lang_Score FROM LearnerProfile WHERE Full_Name = ?";

        try (Connection con = DriverManager.getConnection(DB_URL, DB_USER, DB_PASS);
             PreparedStatement insertPstmt = con.prepareStatement(insertQuery);
             PreparedStatement fetchPstmt = con.prepareStatement(fetchQuery)) {

            insertPstmt.setString(1, "takahashi");
            insertPstmt.setInt(2, 88);
            insertPstmt.setInt(3, 92);
            insertPstmt.setInt(4, 95);
            int insertedRows = insertPstmt.executeUpdate();
            System.out.println("登録完了。対象行数: " + insertedRows);

            fetchPstmt.setString(1, "takahashi");
            try (ResultSet res = fetchPstmt.executeQuery()) {
                if (res.next()) {
                    String targetName = res.getString("Full_Name");
                    int langVal = res.getInt("Lang_Score");
                    System.out.printf("対象者: %s | 言語スコア: %d%n", targetName, langVal);
                }
            }
        } catch (SQLException ex) {
            System.err.println("DB接続エラー: " + ex.getMessage());
        } catch (Exception ex) {
            System.err.println("予期せぬエラー: " + ex.getMessage());
        }
    }
}

列指向ストアHBaseのクライアント実装

HBaseへの接続にはHBaseConfigurationConnectionFactoryを利用します。行キーと列ファミリ、修飾子のバイト列変換はBytesユーティリティクラスで処理します。

package jp.tech.dataaccess.nosql;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;

public class HBaseRecordHandler {
    private static final String TBL = "AcademicRecords";
    private static final String CF = "metrics";
    private static final String COL_A = "Lang";
    private static final String COL_B = "Logic";
    private static final String COL_C = "Tech";

    public static void main(String[] args) {
        Configuration hConfig = HBaseConfiguration.create();
        hConfig.set("hbase.zookeeper.quorum", "zk-node1,zk-node2");

        try (Connection hConn = ConnectionFactory.createConnection(hConfig);
             Table hTable = hConn.getTable(TableName.valueOf(TBL))) {

            insertRecord(hTable, "takahashi", 88, 92, 95);
            fetchLangMetric(hTable, "takahashi");

        } catch (IOException e) {
            System.err.println("HBaseアクセス失敗: " + e.getMessage());
        } catch (Exception e) {
            System.err.println("システムエラー: " + e.getMessage());
        }
    }

    private static void insertRecord(Table tbl, String rowKey, int valA, int valB, int valC) throws IOException {
        Put entry = new Put(Bytes.toBytes(rowKey));
        entry.addColumn(Bytes.toBytes(CF), Bytes.toBytes(COL_A), Bytes.toBytes(String.valueOf(valA)));
        entry.addColumn(Bytes.toBytes(CF), Bytes.toBytes(COL_B), Bytes.toBytes(String.valueOf(valB)));
        entry.addColumn(Bytes.toBytes(CF), Bytes.toBytes(COL_C), Bytes.toBytes(String.valueOf(valC)));
        tbl.put(entry);
        System.out.println("レコード投入完了: " + rowKey);
    }

    private static void fetchLangMetric(Table tbl, String rowKey) throws IOException {
        Get query = new Get(Bytes.toBytes(rowKey));
        query.addColumn(Bytes.toBytes(CF), Bytes.toBytes(COL_A));
        Result res = tbl.get(query);

        if (res.isEmpty()) {
            System.out.println("該当データなし: " + rowKey);
            return;
        }
        byte[] rawVal = res.getValue(Bytes.toBytes(CF), Bytes.toBytes(COL_A));
        String metric = rawVal != null ? Bytes.toString(rawVal) : "未設定";
        System.out.println("対象キー: " + rowKey + " | Langスコア: " + metric);
    }
}

インメモリキーバリューストアRedisの操作

Redisクライアントには接続プーリング機構を備えたJedisを使用します。ハッシュデータ型を活用して複数のスコアを1つのキーに紐付けて管理します。

package jp.tech.dataaccess.nosql;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.HashMap;
import java.util.Map;

public class RedisMetricStore {
    private static final String NODE_HOST = "10.0.0.50";
    private static final int NODE_PORT = 6380;
    private static final String AUTH_TOKEN = "RedisSecret2024";

    public static void main(String[] args) {
        JedisPoolConfig poolSettings = new JedisPoolConfig();
        poolSettings.setMaxTotal(10);
        poolSettings.setMaxIdle(5);
        poolSettings.setMinIdle(2);

        try (JedisPool pool = new JedisPool(poolSettings, NODE_HOST, NODE_PORT, 3000, AUTH_TOKEN)) {
            try (Jedis client = pool.getResource()) {
                saveStudentMetrics(client, "takahashi", 88, 92, 95);
                retrieveLangScore(client, "takahashi");
            }
        } catch (Exception e) {
            System.err.println("Redis操作例外: " + e.getMessage());
        }
    }

    private static void saveStudentMetrics(Jedis client, String id, int a, int b, int c) {
        String mapKey = "profile:" + id;
        Map<String, String> scoreMap = new HashMap<>();
        scoreMap.put("Lang", String.valueOf(a));
        scoreMap.put("Logic", String.valueOf(b));
        scoreMap.put("Tech", String.valueOf(c));
        client.hset(mapKey, scoreMap);
        System.out.println("ハッシュデータ登録完了");
    }

    private static void retrieveLangScore(Jedis client, String id) {
        String targetKey = "profile:" + id;
        String val = client.hget(targetKey, "Lang");
        System.out.println("取得結果 [" + targetKey + "].Lang = " + (val != null ? val : "null"));
    }
}

ドキュメント指向データベースMongoDBの操作

MongoDB Java Driverの現行バージョンでは、ネストされたドキュメント構造とプロジェクションによるクエリ結果の絞り込みがサポートされています。

package jp.tech.dataaccess.nosql;

import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import org.bson.Document;
import org.bson.conversions.Bson;

public class MongoDocManager {
    private static final String URI = "mongodb://127.0.0.1:27017";
    private static final String TARGET_DB = "campus";
    private static final String TARGET_COL = "profiles";

    public static void main(String[] args) {
        try (MongoClient client = MongoClients.create(URI)) {
            MongoDatabase db = client.getDatabase(TARGET_DB);
            MongoCollection<Document> col = db.getCollection(TARGET_COL);

            insertLearnerDoc(col, "takahashi", 88, 92, 95);
            queryMetricsProjection(col, "takahashi");
        } catch (Exception ex) {
            System.err.println("Mongo接続エラー: " + ex.getMessage());
        }
    }

    private static void insertLearnerDoc(MongoCollection<Document> col, String name, int l, int m, int t) {
        Document metrics = new Document("Lang", l).append("Logic", m).append("Tech", t);
        Document doc = new Document("identifier", name).append("results", metrics);
        col.insertOne(doc);
        System.out.println("ドキュメント挿入成功");
    }

    private static void queryMetricsProjection(MongoCollection<Document> col, String name) {
        Bson condition = Filters.eq("identifier", name);
        Bson fields = Projections.fields(
                Projections.include("results"),
                Projections.excludeId()
        );

        Document found = col.find(condition).projection(fields).first();
        if (found != null) {
            Document metrics = found.get("results", Document.class);
            if (metrics != null) {
                System.out.println("検索対象: " + name);
                metrics.forEach((k, v) -> System.out.println(" - " + k + ": " + v));
            }
        } else {
            System.out.println("該当レコードなし");
        }
    }
}

タグ: MySQL HBase redis MongoDB java-jdbc

9月7日 21:46 投稿