クイックスタート: Azure Database for PostgreSQL - フレキシブル サーバーで Java と JDBC を使用する

この記事では、Javaと JDBC を使用してAzure Database for PostgreSQLに情報を格納および取得するサンプル アプリケーションを作成する方法について説明します。

JDBC は、従来のリレーショナル データベースに接続するための標準的なJava API です。

この記事には、Microsoft Entra認証と PostgreSQL 認証という 2 つの認証方法が含まれています。 [パスワードレス] タブには Microsoft Entra 認証が表示され、[パスワード] タブには PostgreSQL 認証が表示されます。

Microsoft Entra 認証は、Microsoft Entra ID で定義された ID を使用して Azure Database for PostgreSQL に接続するための仕組みです。 Microsoft Entra認証を使用すると、データベース ユーザー ID やその他のMicrosoft サービスを一元的な場所で管理できるため、アクセス許可の管理が簡略化されます。

PostgreSQL 認証では、PostgreSQL に格納されているアカウントが使用されます。 アカウントの資格情報としてパスワードを使用する場合は、これらの資格情報を user テーブルに格納します。 これらのパスワードは PostgreSQL に格納されるため、パスワードのローテーションを自分で管理する必要があります。

[前提条件]

  • Azure アカウント。 所有していない場合は、無料試用版を入手してください。
  • Azure Cloud Shell または Azure CLI。 Azure Cloud Shellを使用して、自動的に認証され、必要なすべてのツールにアクセスできるようにします。
  • サポートされている Java 開発キット、バージョン 8 (Azure Cloud Shell に含まれます)。
  • Apache Maven ビルド ツール。

作業環境を準備する

まず、次のコマンドを使用して、いくつかの環境変数を設定します。

export AZ_RESOURCE_GROUP=database-workshop
export AZ_DATABASE_SERVER_NAME=<YOUR_DATABASE_SERVER_NAME>
export AZ_DATABASE_NAME=<YOUR_DATABASE_NAME>
export AZ_LOCATION=<YOUR_AZURE_REGION>
export AZ_POSTGRESQL_AD_NON_ADMIN_USERNAME=<YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
export CURRENT_USERNAME=$(az ad signed-in-user show --query userPrincipalName -o tsv)

プレースホルダーを次の値に置き換えます。この値は、この記事全体で使用されます。

  • <YOUR_DATABASE_SERVER_NAME>: Azure Database for PostgreSQL フレキシブル サーバーの名前です。Azure 全体で一意である必要があります。
  • <YOUR_DATABASE_NAME>: Azure内で一意である必要がある、Azure Database for PostgreSQL フレキシブル サーバーのデータベース名。
  • <YOUR_AZURE_REGION>: 使用する Azure リージョン。 eastusは既定で使用できますが、住んでいる場所に近いリージョンを選択します。 使用できるリージョンの完全な一覧を表示するには、「az account list-locations」と入力します。
  • <YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>: Azure Database for PostgreSQLフレキシブル サーバーのユーザー名。 ユーザー名が、Microsoft Entra テナント内の有効なユーザーであることを確認します。
  • <YOUR_LOCAL_IP_ADDRESS>: Spring Boot アプリケーションを実行するローカル コンピューターの IP アドレス。 それを見つけるのに便利な方法の1つは、whatismyip.akamai.com を開く 方法です

Important

<YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>を設定する場合、ユーザーは既にMicrosoft Entra テナントに存在しているか、データベースにMicrosoft Entraユーザーを作成できません。

次に、次のコマンドを使用し、リソース グループを作成します。

az group create \
    --name $AZ_RESOURCE_GROUP \
    --location $AZ_LOCATION \
    --output tsv

フレキシブル サーバーを作成する

次のセクションでは、データベース インスタンスを作成および構成する方法について説明します。

フレキシブル サーバーを作成し、管理者ユーザーを設定する

フレキシブル サーバー Azure Database for PostgreSQL作成の詳細については、「クイック スタート: Azure Database for PostgreSQL フレキシブル サーバーを作成する」を参照してください。

Azure CLI を使用する場合は、次のコマンドを実行して、十分なアクセス許可があることを確認します。

az login --scope https://graph.microsoft.com/.default

次のコマンドを実行してサーバーを作成します。

az postgres flexible-server create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --location $AZ_LOCATION \
    --yes \
    --output tsv

サーバーの作成後に Microsoft Entra 管理者を設定するには、「 Azure Database for PostgreSQL で Microsoft Entra ロールを管理する」の手順に従います。

Important

管理者を設定するときに、完全な管理者権限を持つ新しいユーザーをAzure Database for PostgreSQLフレキシブル サーバーのAzure データベースに追加します。 Azure Database for PostgreSQL Flexible Server ごとに、複数の Microsoft Entra 管理者を作成できます。

何か問題がありますか? ぜひご意見をお寄せください。

Azure Database for PostgreSQL インスタンスのファイアウォール規則を構成する

Azure Database for PostgreSQLフレキシブル サーバーは既定でセキュリティで保護されています。 すべての着信接続をブロックするファイアウォールがあります。 データベースを使用するには、ローカル IP アドレスにデータベース サーバーへのアクセスを許可するファイアウォール規則を追加します。

この記事の冒頭でローカル IP アドレスを構成したので、次のコマンドを実行してサーバーのファイアウォールを開くことができます。

az postgres flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --rule-name $AZ_DATABASE_SERVER_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 Database for PostgreSQL フレキシブル サーバーに接続する場合は、WSL ホスト ID をファイアウォールに追加する必要があります。

WSL で次のコマンドを実行して、ホスト コンピューターの IP アドレスを取得します。

cat /etc/resolv.conf

nameserverという用語に従う IP アドレスをコピーし、次のコマンドを使用して WSL IP アドレスの環境変数を設定します。

AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

次に、以下のコマンドを使って、サーバーのファイアウォールを WSL ベースのアプリに開放します。

az postgres flexible-server firewall-rule create \
    --resource-group $AZ_RESOURCE_GROUP \
    --name $AZ_DATABASE_SERVER_NAME \
    --rule-name $AZ_DATABASE_SERVER_NAME-database-allow-local-ip \
    --start-ip-address $AZ_WSL_IP_ADDRESS \
    --end-ip-address $AZ_WSL_IP_ADDRESS \
    --output tsv

Azure Database for PostgreSQL データベースを構成する

次のコマンドを使用して、新しいデータベースを作成します。

az postgres flexible-server db create \
    --resource-group $AZ_RESOURCE_GROUP \
    --database-name $AZ_DATABASE_NAME \
    --server-name $AZ_DATABASE_SERVER_NAME \
    --output tsv

Azure Database for PostgreSQL の管理者以外のユーザーを作成し、アクセス許可を付与する

次に、非管理者ユーザーを作成し、データベースに対するすべてのアクセス許可を付与します。

Azure Database for PostgreSQLユーザーの管理の詳細については、「Azure Database for PostgreSQLでのMicrosoft Entraロールの管理」を参照してください。

管理者以外のユーザーを作成するための create_ad_user.sql という名前の SQL スクリプトを作成します。 次の内容を追加し、ローカルに保存します。

cat << EOF > create_ad_user.sql
select * from pgaadauth_create_principal('$AZ_POSTGRESQL_AD_NON_ADMIN_USERNAME', false, false);
EOF

次に、次のコマンドを使用して SQL スクリプトを実行し、管理者以外のユーザー Microsoft Entra作成します。

psql "host=$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com user=$CURRENT_USERNAME dbname=postgres port=5432 password=$(az account get-access-token --resource-type oss-rdbms --output tsv --query accessToken) sslmode=require" < create_ad_user.sql

一時 SQL スクリプト ファイルを削除するには、次のコマンドを使用します。

rm create_ad_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.7.5</version>
      </dependency>
      <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-identity-extensions</artifactId>
        <version>1.2.0</version>
      </dependency>
    </dependencies>
</project>

このファイルは、以下を使用するようにプロジェクトを構成する Apache Maven ファイルです。

  • Java 8
  • 最近の Java 用 PostgreSQL ドライバー

Azure Database for PostgreSQL に接続するための構成ファイルを準備する

src/main/resources/application.properties ファイルを作成し、次の内容を追加します。

cat << EOF > src/main/resources/application.properties
url=jdbc:postgresql://${AZ_DATABASE_SERVER_NAME}.postgres.database.azure.com:5432/${AZ_DATABASE_NAME}?sslmode=require&authenticationPluginClassName=com.azure.identity.extensions.jdbc.postgresql.AzurePostgresqlAuthenticationPlugin
user=${AZ_POSTGRESQL_AD_NON_ADMIN_USERNAME}
EOF

構成プロパティ url には、データベースへの接続時に JDBC ドライバーで TLS (トランスポート層セキュリティ) が使用されるようにする ?sslmode=require が含まれています。 Azure Database for PostgreSQLフレキシブル サーバーでは TLS の使用が必須であり、推奨されるセキュリティプラクティスです。

データベース スキーマを生成するための SQL ファイルを作成する

src/main/resources/schema.sql ファイルを使用してデータベース スキーマを作成します。 そのファイルを作成し、次の内容を追加します。

DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);

アプリケーションをコーディングする

次のセクションでは、データベースに接続し、データ モデルを定義し、基本的な CRUD 操作を実行するJava コードを記述する手順について説明します。

データベースに接続する

次に、JDBC を使用して Azure Database for PostgreSQL フレキシブル サーバーからデータを格納および取得する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 Database for PostgreSQL フレキシブル サーバーに接続し、データを格納するスキーマを作成します。

このファイルでは、データを挿入、読み取り、更新、および削除するメソッドがコメント アウトされます。この記事の残りの部分では、これらのメソッドのコーディングについて説明します。コメントを解除することもできます。

データベースの資格情報は、application.properties ファイルの user プロパティと password プロパティに格納されます。 コードでは、プロパティ ファイルが引数として渡されるため、 DriverManager.getConnection(properties.getProperty("url"), properties);の実行時にこれらの資格情報が使用されます。

以後、このメイン クラスは、次の任意のツールを使用して実行することができます。

  • IDE を使用すると、 DemoApplication クラスを右クリックして実行できます。
  • Maven を使用する場合: mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication" を実行することによってアプリケーションを実行できます。

コンソール ログに示すように、アプリケーションは Azure Database for PostgreSQL フレキシブル サーバーに接続し、データベース スキーマを作成して接続を閉じます。

[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 Database for PostgreSQL にデータを挿入する

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 Database for PostgreSQLからデータを読み取る

コードが正しく動作することを検証するには、前に挿入したデータを読み取ります。

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 Database for PostgreSQLのデータを更新する

データを更新するには、次の手順を使用します。

引き続き 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 Database for PostgreSQL内のデータを削除する

最後に、前に挿入したデータを削除します。

引き続き 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 Database for PostgreSQLフレキシブル サーバーからデータを取得するJava アプリケーションを作成しました。

このクイック スタートで使用したすべてのリソースをクリーンアップするには、次のコマンドを使用してリソース グループを削除します。

az group delete \
    --name $AZ_RESOURCE_GROUP \
    --yes