この記事では、Java と JDBC を使用してAzure HorizonDB (プレビュー) に情報を格納および取得するサンプル アプリケーションを作成する方法について説明します。
JDBC は、従来のリレーショナル データベースに接続するための標準的なJava API です。
この記事の手順には、PostgreSQL 認証が含まれます。
PostgreSQL 認証では PostgreSQL に格納されているアカウントを使用するため、パスワードのローテーションを自分で管理する必要があります。
Prerequisites
- Azure アカウント。 所有していない場合は、無料試用版を入手してください。
- Azure Cloud Shell または Azure CLI。 Azure Cloud Shellを使用して、自動的に認証され、必要なすべてのツールにアクセスできるようにします。
- サポートされている Java Development Kit バージョン 8 (Cloud Shell に含まれます)。
- Apache Maven ビルド ツール。
作業環境を準備する
まず、次のコマンドを使用して、いくつかの環境変数を設定します。
export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_CLUSTER_NAME=<YOUR_DATABASE_CLUSTER_NAME>
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_POSTGRESQL_ADMIN_USERNAME=demo
export AZ_POSTGRESQL_ADMIN_PASSWORD=<YOUR_POSTGRESQL_ADMIN_PASSWORD>
export AZ_POSTGRESQL_NON_ADMIN_USERNAME=demo-non-admin
export AZ_POSTGRESQL_NON_ADMIN_PASSWORD=<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
プレースホルダーを次の値に置き換えます。この値は、この記事全体で使用されます。
-
<YOUR_DATABASE_CLUSTER_NAME>: Azure HorizonDB クラスターの名前。これは、Azure サブスクリプションとリソース グループ全体で一意である必要があります。 -
<YOUR_DATABASE_NAME>: Azure HorizonDB クラスター内で使用しているデータベース名。 -
<YOUR_AZURE_REGION>: 使用する Azure リージョン。 既定ではaustraliaeastを使用できますが、住んでいる場所に近いリージョンを構成できます。az account list-locationsと入力すると、使用可能なリージョンの一覧全体を表示できます。 -
<YOUR_POSTGRESQL_ADMIN_PASSWORD>と<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>: Azure HorizonDB クラスターのパスワード。 パスワードは 8 文字以上にする必要があります。 これには、英大文字、英小文字、数字 (0 から 9)、非英数字の文字 (!、$、#、% など) のうち、3 つのカテゴリの文字が含まれている必要があります。 -
<YOUR_LOCAL_IP_ADDRESS>: Spring Boot アプリケーションを実行するローカル コンピューターの IP アドレス。 それを見つけるのに便利な方法の1つは、whatismyip.akamai.com を開く 方法です。
次に、次のコマンドを使用し、リソース グループを作成します。
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
--output tsv
Azure HorizonDB クラスターを作成する
Note
リソース名(例:テーブル名、データベース名)やリソースタグには、個人情報、機密情報を含めないでください。 これらの項目に入力したデータは顧客データとはみなされません。
次のセクションでは、データベース クラスターを作成して構成する方法について説明します。
Azure HorizonDB クラスターを作成する
管理者ユーザーを設定する
まず、マネージド Azure HorizonDB インスタンスを作成します。
Note
HorizonDB Azure作成の詳細については、「Azure HorizonDB クラスターの作成を参照してください。
az horizondb create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_CLUSTER_NAME \
--location $AZ_LOCATION \
--version 17 \
--administrator-login $AZ_POSTGRESQL_ADMIN_USERNAME \
--administrator-login-password $AZ_POSTGRESQL_ADMIN_PASSWORD \
--v-cores 2 \
--yes \
--output tsv
このコマンドは、小規模な Azure HorizonDB クラスターを作成します。
Azure HorizonDB インスタンスのファイアウォール規則を構成する
Azure HorizonDB インスタンスは既定でセキュリティで保護されています。 すべての着信接続をブロックするファイアウォールがあります。 データベースを使用するには、ローカル IP アドレスにデータベース サーバーへのアクセスを許可するファイアウォール規則を追加します。
この記事の冒頭でローカル IP アドレスを構成したので、次のコマンドを実行してサーバーのファイアウォールを開くことができます。
az horizondb firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--cluster-name $AZ_DATABASE_CLUSTER_NAME \
--firewall-rule-name $AZ_DATABASE_CLUSTER_NAME-database-allow-local-ip \
--start-ip-address $AZ_LOCAL_IP_ADDRESS \
--end-ip-address $AZ_LOCAL_IP_ADDRESS \
--output tsv
Windows コンピューター上の Linux 用 Windows サブシステム (WSL) から Azure HorizonDB クラスターに接続する場合は、WSL ホスト ID をファイアウォールに追加する必要があります。
WSL で次のコマンドを実行して、ホスト コンピューターの IP アドレスを取得します。
cat /etc/resolv.conf
nameserverという用語に従う IP アドレスをコピーし、次のコマンドを使用して WSL IP アドレスの環境変数を設定します。
AZ_WSL_IP_ADDRESS=<the-copied-IP-address>
次に、以下のコマンドを使って、サーバーのファイアウォールを WSL ベースのアプリに開放します。
az horizondb firewall-rule create \
--resource-group $AZ_RESOURCE_GROUP \
--cluster-name $AZ_DATABASE_CLUSTER_NAME \
--firewall-rule-name $AZ_DATABASE_CLUSTER_NAME-database-allow-local-ip \
--start-ip-address $AZ_WSL_IP_ADDRESS \
--end-ip-address $AZ_WSL_IP_ADDRESS \
--output tsv
Azure HorizonDB データベースを作成する
create_database.sqlという名前 の SQL スクリプトを作成して、クラスターに新しいデータベースを作成します。 次の内容を追加し、ファイルをローカルに保存します。
cat << EOF > create_database.sql
CREATE DATABASE "$AZ_DATABASE_NAME";
EOF
次のコマンドを実行して、Azure HorizonDB の完全修飾ドメイン名を取得し、clusterName 値をコピーします。
az horizondb show \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_CLUSTER_NAME \
--query "{clusterName:properties.fullyQualifiedDomainName, adminUser:properties.administratorLogin}" \
--output table
clusterName値をコピーし、次のコマンドで使用します。
AZ_HORIZONDB_FQDN=<the-copied-clusterName-value>
次に、次のコマンドを実行して SQL スクリプトを実行し、データベースを作成します。
psql "host=$AZ_HORIZONDB_FQDN user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_database.sql
次に、次のコマンドを実行して、一時 SQL スクリプト ファイルを削除します。
rm create_database.sql
Azure HorizonDB の非管理者ユーザーを作成し、アクセス許可を付与する
次に、管理者以外のユーザーを作成し、すべてのアクセス許可をデータベースに付与します。
create_user.sqlという名前の SQL スクリプトを作成して、管理者以外のユーザーを作成します。 次の内容を追加し、ファイルをローカルに保存します。
cat << EOF > create_user.sql
CREATE ROLE "$AZ_POSTGRESQL_NON_ADMIN_USERNAME" WITH LOGIN PASSWORD '$AZ_POSTGRESQL_NON_ADMIN_PASSWORD';
GRANT ALL PRIVILEGES ON DATABASE $AZ_DATABASE_NAME TO "$AZ_POSTGRESQL_NON_ADMIN_USERNAME";
EOF
次に、次のコマンドを実行して SQL スクリプトを実行し、Microsoft Entra非admin ユーザーを作成します。
psql "host=$AZ_HORIZONDB_FQDN user=$AZ_POSTGRESQL_ADMIN_USERNAME dbname=$AZ_DATABASE_NAME port=5432 password=$AZ_POSTGRESQL_ADMIN_PASSWORD sslmode=require" < create_user.sql
次に、次のコマンドを実行して、一時 SQL スクリプト ファイルを削除します。
rm create_user.sql
新しい Java プロジェクトを作成する
お気に入りの IDE を使用して、Java 8 以降を使用して新しいJava プロジェクトを作成します。 次の内容を含む pom.xml ファイルをルート ディレクトリに追加します。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.3.6</version>
</dependency>
</dependencies>
</project>
このファイルは、以下を使用するようにプロジェクトを構成する Apache Maven ファイルです。
- Java 8
- 最近の Java 用 PostgreSQL ドライバー
Azure HorizonDB に接続するための構成ファイルを準備する
src/main/resources/application.properties ファイルを作成し、次の内容を追加します。
cat << EOF > src/main/resources/application.properties
url=jdbc:postgresql://${AZ_HORIZONDB_FQDN}:5432/${AZ_DATABASE_NAME}?sslmode=require
user=${AZ_POSTGRESQL_NON_ADMIN_USERNAME}
password=${AZ_POSTGRESQL_NON_ADMIN_PASSWORD}
EOF
Note
構成プロパティ url には、データベースへの接続時に JDBC ドライバーで TLS (トランスポート層セキュリティ) が使用されるようにする ?sslmode=require が含まれています。 Azure HorizonDB には TLS が必要であり、推奨されるセキュリティプラクティスです。
データベース スキーマを生成するための SQL ファイルを作成する
src/main/resources/schema.sql ファイルを使用してデータベース スキーマを作成します。 次の内容を含むファイルを作成します。
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description text, details text, done BOOLEAN);
アプリケーションをコーディングする
データベースに接続する
次に、JDBC を使用して Azure HorizonDB インスタンスのデータを格納および取得するJava コードを追加します。
src/main/java/DemoApplication.java ファイルを作成し、次の内容を追加します。
package com.example.demo;
import java.sql.*;
import java.util.*;
import java.util.logging.Logger;
public class DemoApplication {
private static final Logger log;
static {
System.setProperty("java.util.logging.SimpleFormatter.format", "[%4$-7s] %5$s %n");
log =Logger.getLogger(DemoApplication.class.getName());
}
public static void main(String[] args) throws Exception {
log.info("Loading application properties");
Properties properties = new Properties();
properties.load(DemoApplication.class.getClassLoader().getResourceAsStream("application.properties"));
log.info("Connecting to the database");
Connection connection = DriverManager.getConnection(properties.getProperty("url"), properties);
log.info("Database connection test: " + connection.getCatalog());
log.info("Create database schema");
Scanner scanner = new Scanner(DemoApplication.class.getClassLoader().getResourceAsStream("schema.sql"));
Statement statement = connection.createStatement();
while (scanner.hasNextLine()) {
statement.execute(scanner.nextLine());
}
/*
Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);
todo = readData(connection);
todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);
deleteData(todo, connection);
*/
log.info("Closing database connection");
connection.close();
}
}
このJavaコードでは、前に作成した application.properties ファイルと schema.sql ファイルを使用して、Azure HorizonDB インスタンスに接続し、データを格納するスキーマを作成します。
このファイルでは、データの挿入、読み取り、更新、削除を行うメソッドにコメントを付けたことがわかります。この記事の残りの部分では、これらのメソッドをコーディングし、コメントを解除することができます。
Note
データベースの資格情報は、application.properties ファイルの user プロパティと password プロパティに格納されます。 プロパティ ファイルは引数として渡されるため、これらの資格情報は DriverManager.getConnection(properties.getProperty("url"), properties); を実行するときに使用されます。
以後、このメイン クラスは、次の任意のツールを使用して実行することができます。
- IDE を使用する場合: DemoApplication クラスを右クリックして実行します。
- Maven を使用する場合:
mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication"を実行することによってアプリケーションを実行できます。
コンソール ログに表示されているように、アプリケーションは Azure HorizonDB インスタンスに接続し、データベース スキーマを作成して接続を閉じる必要があります。
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Closing database connection
ドメイン クラスを作成する
Todo クラスの横に新しい DemoApplication Java クラスを作成し、以下のコードを追加します。
package com.example.demo;
public class Todo {
private Long id;
private String description;
private String details;
private boolean done;
public Todo() {
}
public Todo(Long id, String description, String details, boolean done) {
this.id = id;
this.description = description;
this.details = details;
this.done = done;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
public boolean isDone() {
return done;
}
public void setDone(boolean done) {
this.done = done;
}
@Override
public String toString() {
return "Todo{" +
"id=" + id +
", description='" + description + '\'' +
", details='" + details + '\'' +
", done=" + done +
'}';
}
}
このクラスは、todo スクリプトを実行する際に作成した テーブルにマップされるドメイン モデルです。
Azure HorizonDB にデータを挿入する
src/main/java/DemoApplication.java ファイルの main メソッドの後に、データベースにデータを挿入するための次のメソッドを追加します。
private static void insertData(Todo todo, Connection connection) throws SQLException {
log.info("Insert data");
PreparedStatement insertStatement = connection
.prepareStatement("INSERT INTO todo (id, description, details, done) VALUES (?, ?, ?, ?);");
insertStatement.setLong(1, todo.getId());
insertStatement.setString(2, todo.getDescription());
insertStatement.setString(3, todo.getDetails());
insertStatement.setBoolean(4, todo.isDone());
insertStatement.executeUpdate();
}
これで、main メソッドの次の 2 つの行のコメントを解除できます。
Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);
メイン クラスを実行すると、次の出力が生成されるはずです。
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Closing database connection
Azure HorizonDB からデータを読み取る
先ほど挿入したデータを読み取って、コードが正しく動作することを確認しましょう。
src/main/java/DemoApplication.java ファイルの insertData メソッドの後に、データベースからデータを読み取るための次のメソッドを追加します。
private static Todo readData(Connection connection) throws SQLException {
log.info("Read data");
PreparedStatement readStatement = connection.prepareStatement("SELECT * FROM todo;");
ResultSet resultSet = readStatement.executeQuery();
if (!resultSet.next()) {
log.info("There is no data in the database!");
return null;
}
Todo todo = new Todo();
todo.setId(resultSet.getLong("id"));
todo.setDescription(resultSet.getString("description"));
todo.setDetails(resultSet.getString("details"));
todo.setDone(resultSet.getBoolean("done"));
log.info("Data read from the database: " + todo.toString());
return todo;
}
これで、main メソッドの次の行のコメントを解除できます。
todo = readData(connection);
メイン クラスを実行すると、次の出力が生成されるはずです。
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO ] Closing database connection
Azure HorizonDB のデータを更新する
先ほど挿入したデータを更新しましょう。
引き続き src/main/java/DemoApplication.java ファイルの readData メソッドの後に、データベース内のデータを更新するための次のメソッドを追加します。
private static void updateData(Todo todo, Connection connection) throws SQLException {
log.info("Update data");
PreparedStatement updateStatement = connection
.prepareStatement("UPDATE todo SET description = ?, details = ?, done = ? WHERE id = ?;");
updateStatement.setString(1, todo.getDescription());
updateStatement.setString(2, todo.getDetails());
updateStatement.setBoolean(3, todo.isDone());
updateStatement.setLong(4, todo.getId());
updateStatement.executeUpdate();
readData(connection);
}
これで、main メソッドの次の 2 つの行のコメントを解除できます。
todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);
メイン クラスを実行すると、次の出力が生成されるはずです。
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO ] Update data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have updated data!', done=true}
[INFO ] Closing database connection
Azure HorizonDB のデータを削除する
最後に、先ほど挿入したデータを削除しましょう。
引き続き src/main/java/DemoApplication.java ファイルの updateData メソッドの後に、データベース内のデータを削除するための次のメソッドを追加します。
private static void deleteData(Todo todo, Connection connection) throws SQLException {
log.info("Delete data");
PreparedStatement deleteStatement = connection.prepareStatement("DELETE FROM todo WHERE id = ?;");
deleteStatement.setLong(1, todo.getId());
deleteStatement.executeUpdate();
readData(connection);
}
これで、main メソッドの次の行のコメントを解除できます。
deleteData(todo, connection);
メイン クラスを実行すると、次の出力が生成されるはずです。
[INFO ] Loading application properties
[INFO ] Connecting to the database
[INFO ] Database connection test: demo
[INFO ] Create database schema
[INFO ] Insert data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have set up JDBC correctly!', done=true}
[INFO ] Update data
[INFO ] Read data
[INFO ] Data read from the database: Todo{id=1, description='configuration', details='congratulations, you have updated data!', done=true}
[INFO ] Delete data
[INFO ] Read data
[INFO ] There is no data in the database!
[INFO ] Closing database connection
リソースをクリーンアップする
おめでとうございます! JDBC を使用して、Azure HorizonDB インスタンスのデータを格納および取得するJava アプリケーションを作成しました。
このクイックスタートで使用したすべてのリソースをクリーンアップするには、次のコマンドを使用してリソース グループを削除します。
az group delete \
--name $AZ_RESOURCE_GROUP \
--yes
関連するコンテンツ
Quickstart: Pythonを使用して、Azure HorizonDB (プレビュー) - Azure HorizonDB(プレビュー)に接続してクエリを実行する