コンテンツにスキップ

11.5 JDBC

Machbase JDBCドライバーはJava 8を基準にJDBC 4.2の主要APIを提供します。標準JDBC APIで サーバーに接続し、PreparedStatement、型指定の検索とバインディング、データベースメタデータ、 ローカルトランザクション、接続プールを使用できます。

項目
Javaバイトコード基準Java 8
ドライバーが報告するJDBCバージョン4.2
ドライバーバージョン3.0.0
JDBC URLjdbc:machbase://<host-list>/[database]
Driver.jdbcCompliant()false

jdbcCompliant()falseはJDBC 4.2 APIのサポート状況ではなく、SQL-92 Entry Level全体への 準拠状況を示します。アプリケーションでは必要な任意機能をDatabaseMetaDataの機能メソッドで確認します。

マルチデータベース

URLパスまたはdatabase接続プロパティで初期データベースを指定できます。

String url = "jdbc:machbase://127.0.0.1:5656/factory_a";
Connection conn = DriverManager.getConnection(url, "APP_A", password);

System.out.println(conn.getCatalog());
conn.setCatalog("FACTORY_A");

getCatalog()setCatalog()はサーバーの現在のデータベースと同期します。URLパスと設定プロパティを 両方指定する場合は同じ値にする必要があります。JDBCメタデータではカタログはデータベース、スキーマは 所有者です。プールされた接続の返却時に初期カタログへ復元されるか確認し、プリペアドステートメントと Appendハンドルは作成時のデータベースに固定される点を考慮します。

ドライバーのインストール

JARファイルの使用

Machbaseインストールディレクトリのmachbase.jarをクラスパスに追加します。

ls -l "$MACHBASE_HOME/lib/machbase.jar"
javac -classpath ".:$MACHBASE_HOME/lib/machbase.jar" MyApp.java
java -classpath ".:$MACHBASE_HOME/lib/machbase.jar" MyApp

JARにはMETA-INF/services/java.sql.Driverが含まれています。JDBC 4.0以降の環境では Class.forName("com.machbase.jdbc.MachDriver")を呼び出さなくてもドライバーが自動登録されます。 既存アプリケーションの明示的な呼び出しも引き続き使用できます。

Maven

<dependency>
    <groupId>com.machbase</groupId>
    <artifactId>machjdbc</artifactId>
    <version>8.0.2</version>
</dependency>

Gradle

dependencies {
    implementation 'com.machbase:machjdbc:8.0.2'
}

配布成果物のバージョンはMaven Centralで 確認します。ドライバーが実行時メタデータで返す3.0.0と配布成果物のバージョンは、別のバージョン体系です。

サーバーへの接続

ユーザー名とパスワードはソースコードに記録せず、環境変数やシークレット管理システムで渡します。

import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;

String url = "jdbc:machbase://127.0.0.1:5656/machbasedb";

Properties properties = new Properties();
properties.setProperty("user", "SYS");
properties.setProperty("password", System.getenv("MACHBASE_PASSWORD"));

try (Connection connection =
         DriverManager.getConnection(url, properties)) {
    // SQLを実行します。
}

接続オプション

接続オプションはPropertiesまたはURLクエリ文字列で指定します。randomHostPropertiesで 指定するか、複数ホストURLの^区切り文字を使用します。

オプション説明
user, passwordパスワード認証情報
TIMEZONEセッションのタイムゾーン。+0900形式を使用します。
randomHostホスト一覧から最初の接続先をランダムに選択します。
maxStatementsプールされた接続の最大キャッシュStatement数
CONNECTION_TIMEOUTソケット接続のタイムアウト(秒)。0は無制限です。
SOCKET_TIMEOUTソケット読み取りのタイムアウト(秒)。0は無制限です。
characterEncodingクライアントの文字エンコーディング
AUTH_MODEPASSWORDまたはCHALLENGE
AUTH_SIG_SCHEMEECDSARSA_PKCS1_V15RSA_PSS
AUTH_KEY_FILEPEM秘密鍵ファイルのパス
String url =
    "jdbc:machbase://127.0.0.1:5656/machbasedb?TIMEZONE=+0900";

複数ホストへの接続

Machbase 8.7.0 JDBCドライバーは、1つのURLに複数ホストを指定できます。

選択方式指定方法動作
順次選択ホストを,で区切るURLの記載順に接続を試みます。
ランダム開始ホストを^で区切るホスト一覧から最初の接続先をランダムに選びます。
ランダム開始PropertiesrandomHost=trueを指定,で区切った一覧から最初の接続先をランダムに選びます。

次のURLはdb1への接続に失敗すると、db2への接続を試みます。

String url =
    "jdbc:machbase://db1.example.com:5656,db2.example.com:5656/" +
    "machbasedb?CONNECTION_TIMEOUT=5";

^区切り文字を使用すると、最初の接続先をランダムに選択します。

String url =
    "jdbc:machbase://db1.example.com:5656^db2.example.com:5656/" +
    "machbasedb?CONNECTION_TIMEOUT=5";

randomHost設定プロパティを使用する場合は、,でホストを区切ります。

Properties properties = new Properties();
properties.setProperty("randomHost", "true");

String url =
    "jdbc:machbase://db1.example.com:5656,db2.example.com:5656/" +
    "machbasedb?CONNECTION_TIMEOUT=5";
  • 1つのURLで,^の区切り文字は併用できません。
  • 接続拒否、接続タイムアウト、ソケットエラーなど接続段階のI/Oエラーが発生すると、次のホストへの 接続を試みます。すべてのホストが失敗するとDriverManager.getConnection()SQLExceptionを返します。
  • CONNECTION_TIMEOUTはホストごとの接続試行に適用されます。そのため全体の接続待機時間は ホスト数と各ホストの応答時間によって長くなる場合があります。
  • SOCKET_TIMEOUTは接続済みソケットの読み取り待機時間を制限し、ホストの選択順序は変更しません。

複数ホストの切り替えは、新規接続または再接続時のソケット接続に適用されます。切断後に自動再接続が 成功しても、以前のStatement、PreparedStatement、ResultSetは再利用しません。実行中のSQLの成功や 安全な再実行は保証されないため、有効なトランザクションで接続エラーが発生した場合は接続を破棄し、 業務の冪等性ポリシーに従ってトランザクション全体を再実行します。

AUTH KEY認証

公開鍵によるチャレンジ認証では、パスワードの代わりにローカルの秘密鍵でサーバーチャレンジに署名します。

Properties properties = new Properties();
properties.setProperty("user", "app_user");
properties.setProperty("AUTH_MODE", "CHALLENGE");
properties.setProperty("AUTH_SIG_SCHEME", "ECDSA");
properties.setProperty(
    "AUTH_KEY_FILE", "/opt/machbase/keys/app_user_ecdsa.pem");

Connection connection = DriverManager.getConnection(
    "jdbc:machbase://127.0.0.1:5656/machbasedb", properties);
  • AUTH_MODE=CHALLENGEでは認証にpasswordを使用しません。
  • AUTH_KEY_FILEは必須です。
  • AUTH_SIG_SCHEMEを省略すると、鍵の種類に合うデフォルト署名方式を選択します。
  • POSIX環境では秘密鍵ファイルの権限を600に制限します。

クイックスタート

次の例はLOGテーブルに値を入力し、再検索します。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;

public class JdbcQuickStart {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        properties.setProperty("user", "SYS");
        properties.setProperty(
            "password", System.getenv("MACHBASE_PASSWORD"));

        try (Connection connection = DriverManager.getConnection(
                 "jdbc:machbase://127.0.0.1:5656/machbasedb",
                 properties);
             Statement statement = connection.createStatement()) {
            statement.execute(
                "CREATE LOG TABLE jdbc_sensor " +
                "(ts DATETIME, name VARCHAR(40), value DOUBLE)");

            try (PreparedStatement insert = connection.prepareStatement(
                     "INSERT INTO jdbc_sensor VALUES (?, ?, ?)")) {
                insert.setLong(1, System.currentTimeMillis() * 1_000_000L);
                insert.setString(2, "sensor-1");
                insert.setDouble(3, 25.3);
                insert.executeUpdate();
            }

            try (ResultSet result = statement.executeQuery(
                     "SELECT name, value FROM jdbc_sensor")) {
                while (result.next()) {
                    System.out.printf("%s %.1f%n",
                        result.getString("NAME"),
                        result.getDouble("VALUE"));
                }
            }
        }
    }
}

DATETIMEにエポックナノ秒値を渡す場合はlongを使用します。例のテーブルがすでに存在する場合は、 CREATE LOG TABLEを省略するか別名を使用します。

INSERT結果のROWID

Standard Editionで単一のINSERT ... VALUESが成功すると、JDBC標準の生成キーAPIで入力行の ROWIDを確認できます。

String sql = "INSERT INTO jdbc_sensor VALUES (?, ?, ?)";
try (PreparedStatement insert = connection.prepareStatement(
         sql, Statement.RETURN_GENERATED_KEYS)) {
    insert.setLong(1, System.currentTimeMillis() * 1_000_000L);
    insert.setString(2, "sensor-2");
    insert.setDouble(3, 26.1);
    insert.executeUpdate();

    try (ResultSet keys = insert.getGeneratedKeys()) {
        if (keys.next()) {
            java.sql.RowId rowId = keys.getRowId("ROWID");
        }
    }
}

結果は1つのROWID列と最大1行で構成されます。返すROWIDがない場合は空のResultSetです。 サポート状況はDatabaseMetaData.supportsGetGeneratedKeys()で確認します。 バッチ、Append、INSERT ... SELECT、UPSERTの違いは ROWIDとINSERT結果IDを参照してください。

バージョンの確認

import java.sql.DatabaseMetaData;

DatabaseMetaData metadata = connection.getMetaData();

System.out.println(metadata.getDriverName());
System.out.println(metadata.getDriverVersion());
System.out.println(metadata.getJDBCMajorVersion()); // 4
System.out.println(metadata.getJDBCMinorVersion()); // 2

関連ドキュメント

ドキュメント内容
PreparedStatementと型パラメーターメタデータ、名前付きbind、SQLType、NULL、型変換
ResultSet、Statement、LOB型指定の検索、ストリーム、LOB、タイムアウト、リソース管理
トランザクションと接続プールStandardのローカルトランザクション、DataSource、接続プール
DatabaseMetaDataテーブル、列、キー、インデックス、機能の検索
Append APIMachStatementによる高速入力
移行とトラブルシューティング旧ドライバーからの移行、非サポート機能、エラー処理
最終更新日