この記事では、Azure Database for PostgreSQLで Spring Data R2DBC を使用して、情報を格納および取得するスケーラブルで完全にリアクティブな Spring Boot アプリケーションを構築する方法について説明します。 このサンプルでは、GitHub上の r2dbc-postgresql リポジトリから PostgreSQL 用の R2DBC 実装を使用します。
R2DBC は、従来のリレーショナル データベースにリアクティブ API を提供します。 これを Spring WebFlux と共に使用すると、非ブロッキング API を使用する完全にリアクティブな Spring Boot アプリケーションを作成できます。 "接続ごとに 1 つのスレッド" という従来の手法よりも優れたスケーラビリティが実現されます。
前提条件
Azure サブスクリプション - 無料アカウントを作成します。
Java Development Kit (JDK)、バージョン 8 以降。
cURL または機能をテストするための類似の HTTP ユーティリティ。
サンプル アプリケーション参照
この記事では、サンプル アプリケーションをコーディングします。 より早く進めたい場合は、このアプリケーションは既にコーディングされており、https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-postgresql で入手できます。
作業環境を準備する
まず、次のコマンドを実行して、いくつかの環境変数を設定します。
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_ADMIN_USERNAME=spring
export AZ_POSTGRESQL_ADMIN_PASSWORD=<YOUR_POSTGRESQL_ADMIN_PASSWORD>
export AZ_POSTGRESQL_NON_ADMIN_USERNAME=nonspring
export AZ_POSTGRESQL_NON_ADMIN_PASSWORD=<YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>
export AZ_LOCAL_IP_ADDRESS=<YOUR_LOCAL_IP_ADDRESS>
プレースホルダーは、この記事全体で使用される次の値に置き換えてください。
-
<YOUR_DATABASE_SERVER_NAME>: PostgreSQL サーバーの名前。Azure 全体で一意である必要があります。 -
<YOUR_DATABASE_NAME>: PostgreSQL サーバーのデータベース名。Azure 内で一意である必要があります。 -
<YOUR_AZURE_REGION>: 使用する Azure リージョン。 既定ではeastusを使用できますが、住んでいる場所に近いリージョンを構成できます。az account list-locationsを使用して、使用可能なリージョンの完全な一覧を参照してください。 -
<YOUR_POSTGRESQL_ADMIN_PASSWORD><YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>: PostgreSQL データベース サーバーのパスワード。少なくとも 8 文字にする必要があります。 これには、英大文字、英小文字、数字 (0 から 9)、英数字以外の文字 (!、$、#、% など) のうち、3 つのカテゴリの文字が含まれている必要があります。 -
<YOUR_LOCAL_IP_ADDRESS>:ローカル コンピューターの IP アドレス。そこから、Spring Boot アプリケーションを実行します。 これを見つける簡単な方法は、ブラウザーで whatismyip.akamai.com にアクセスすることです。
注
Microsoft では、使用可能な最も安全な認証フローを使用することをお勧めします。 この手順で説明する認証フロー (データベース、キャッシュ、メッセージング、AI サービスなど) には、アプリケーションに対する非常に高い信頼が必要であり、他のフローには存在しないリスクが伴います。 このフローは、パスワードレス接続やキーレス接続のマネージド ID など、より安全なオプションが有効でない場合にのみ使用します。 ローカル コンピューターの操作では、パスワードレス接続またはキーレス接続にユーザー ID を使用します。
次に、次のコマンドを使用し、リソース グループを作成します。
az group create \
--name $AZ_RESOURCE_GROUP \
--location $AZ_LOCATION \
--output tsv
Azure Database for PostgreSQL インスタンスを作成し、管理者ユーザーを設定する
最初に作成するのは、管理ユーザーを持つマネージド PostgreSQL サーバーです。
注
PostgreSQL サーバーの作成の詳細については、「Azure ポータルを使用したAzure Database for PostgreSQL サーバーの作成」を参照してください。
az postgres flexible-server create \
--resource-group $AZ_RESOURCE_GROUP \
--name $AZ_DATABASE_SERVER_NAME \
--location $AZ_LOCATION \
--admin-user $AZ_POSTGRESQL_ADMIN_USERNAME \
--admin-password $AZ_POSTGRESQL_ADMIN_PASSWORD \
--yes \
--output tsv
PostgreSQL データベースを構成する
先ほど作成した 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
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) から PostgreSQL サーバーに接続する場合は、WSL ホストの ID をファイアウォールに追加する必要があります。
WSL で次のコマンドを実行して、ホスト コンピューターの IP アドレスを取得します。
cat /etc/resolv.conf
nameserverという用語の後に IP アドレスをコピーし、次のコマンドを使用して WSL IP アドレスの環境変数を設定します。
export 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
PostgreSQL の非管理者ユーザーを作成し、アクセス許可を付与する
次に、非管理者ユーザーを作成し、データベースに対するすべてのアクセス許可を付与します。
注
PostgreSQL ユーザーの作成の詳細については、「Azure Database for PostgreSQL でのユーザーの作成」を参照してください。
管理者以外のユーザーを作成するための create_user.sql という名前の SQL スクリプトを作成します。 次の内容を追加し、ローカルに保存します。
注
Microsoft では、使用可能な最も安全な認証フローを使用することをお勧めします。 この手順で説明する認証フロー (データベース、キャッシュ、メッセージング、AI サービスなど) には、アプリケーションに対する非常に高い信頼が必要であり、他のフローには存在しないリスクが伴います。 このフローは、パスワードレス接続やキーレス接続のマネージド ID など、より安全なオプションが有効でない場合にのみ使用します。 ローカル コンピューターの操作では、パスワードレス接続またはキーレス接続にユーザー ID を使用します。
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作成します。
psql "host=$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com 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
リアクティブ Spring Boot アプリケーションを作成する
リアクティブ Spring Boot アプリケーションを作成するために、Spring Initializr を使用します。 作成するアプリケーションでは、以下が使用されます。
- Spring Boot 2.7.11。
- 次の依存関係: Spring Reactive Web (Spring WebFlux とも呼ばれます) と Spring Data R2DBC。
Spring Initializr を使用してアプリケーションを生成する
以下のコマンドを使用して、コマンド ラインでアプリケーションを生成します。
curl https://start.spring.io/starter.tgz -d dependencies=webflux,data-r2dbc -d baseDir=azure-database-workshop -d bootVersion=2.7.11 -d javaVersion=17 | tar -xzvf -
リアクティブ PostgreSQL ドライバー実装を追加する
生成されたプロジェクトの pom.xml ファイルを開いてから、GitHub の r2dbc-postgresql リポジトリにあるリアクティブ PostgreSQL ドライバーを追加します。
spring-boot-starter-webflux 依存関係の後に、次のテキストを追加します。
<dependency>
<groupId>io.r2dbc</groupId>
<artifactId>r2dbc-postgresql</artifactId>
<version>0.8.12.RELEASE</version>
<scope>runtime</scope>
</dependency>
Azure Database for PostgreSQL を使用するように Spring Boot を構成する
src/main/resources/application.properties ファイルを開き、以下のテキストを追加します。
logging.level.org.springframework.data.r2dbc=DEBUG
spring.r2dbc.url=r2dbc:pool:postgres://$AZ_DATABASE_SERVER_NAME.postgres.database.azure.com:5432/$AZ_DATABASE_NAME
spring.r2dbc.username=nonspring
spring.r2dbc.password=$AZ_POSTGRESQL_NON_ADMIN_PASSWORD
spring.r2dbc.properties.sslMode=REQUIRE
$AZ_DATABASE_SERVER_NAME、$AZ_DATABASE_NAME、および$AZ_POSTGRESQL_NON_ADMIN_PASSWORD変数を、この記事の冒頭で構成した値に置き換えます。
警告
セキュリティ上の理由から、Azure Database for PostgreSQLには SSL 接続が必要です。
spring.r2dbc.properties.sslMode=REQUIRE構成プロパティを追加します。 それ以外の場合、R2DBC PostgreSQL ドライバーは安全でない接続を使用して接続を試みますが、これは失敗します。
注
パフォーマンスを向上させるために、spring.r2dbc.url プロパティは r2dbc-pool を使用して接続プールを使用するように構成されています。
次のように、提供された Maven ラッパーを使用してアプリケーションを起動できるようになりました。
./mvnw spring-boot:run
アプリケーションを初めて実行したときのスクリーンショットを次に示します。
データベース スキーマを作成する
DemoApplication メイン クラス内で、次のコードを使用し、データベース スキーマを作成する新しい Spring Bean を構成します。
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.r2dbc.connectionfactory.init.ConnectionFactoryInitializer;
import org.springframework.data.r2dbc.connectionfactory.init.ResourceDatabasePopulator;
import io.r2dbc.spi.ConnectionFactory;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Bean
public ConnectionFactoryInitializer initializer(ConnectionFactory connectionFactory) {
ConnectionFactoryInitializer initializer = new ConnectionFactoryInitializer();
initializer.setConnectionFactory(connectionFactory);
ResourceDatabasePopulator populator = new ResourceDatabasePopulator(new ClassPathResource("schema.sql"));
initializer.setDatabasePopulator(populator);
return initializer;
}
}
この Spring Bean では schema.sql というファイルが使用されるので、src/main/resources フォルダーにそのファイルを作成し、次のテキストを追加します。
DROP TABLE IF EXISTS todo;
CREATE TABLE todo (id SERIAL PRIMARY KEY, description VARCHAR(255), details VARCHAR(4096), done BOOLEAN);
次のコマンドを使用して、実行中のアプリケーションを停止して再起動します。 アプリケーションでは、先ほど作成した demo データベースが使用され、その中に todo テーブルが作成されます。
./mvnw spring-boot:run
データベース テーブルの作成中のスクリーンショットを次に示します。
アプリケーションをコーディングする
次に、R2DBC を使用して PostgreSQL サーバーのデータを格納および取得するJava コードを追加します。
次のコードを使用し、Todo クラスの横に新しい DemoApplication Java クラスを作成します。
package com.example.demo;
import org.springframework.data.annotation.Id;
public class Todo {
public Todo() {
}
public Todo(String description, String details, boolean done) {
this.description = description;
this.details = details;
this.done = done;
}
@Id
private Long id;
private String description;
private String details;
private boolean 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;
}
}
このクラスは、先ほど作成した todo テーブルにマップされるドメイン モデルです。
このクラスを管理するにはリポジトリが必要です。 次のコードを使用し、同じパッケージ内に新しい TodoRepository インターフェイスを定義します。
package com.example.demo;
import org.springframework.data.repository.reactive.ReactiveCrudRepository;
public interface TodoRepository extends ReactiveCrudRepository<Todo, Long> {
}
このリポジトリは、Spring Data R2DBC によって管理されるリアクティブ リポジトリです。
データを格納および取得できるコントローラーを作成して、アプリケーションを完成させます。 同じパッケージに TodoController クラスを実装し、次のコードを追加します。
package com.example.demo;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@RestController
@RequestMapping("/")
public class TodoController {
private final TodoRepository todoRepository;
public TodoController(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}
@PostMapping("/")
@ResponseStatus(HttpStatus.CREATED)
public Mono<Todo> createTodo(@RequestBody Todo todo) {
return todoRepository.save(todo);
}
@GetMapping("/")
public Flux<Todo> getTodos() {
return todoRepository.findAll();
}
}
最後に、次のコマンドを使用して、アプリケーションを停止して再起動します。
./mvnw spring-boot:run
アプリケーションをテストする
アプリケーションをテストするには、cURL を使用します。
まず、次のコマンドを使用して、データベースに新しい "todo" 項目を作成します。
curl --header "Content-Type: application/json" \
--request POST \
--data '{"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done": "true"}' \
http://127.0.0.1:8080
このコマンドからは、ここに示すように、作成された項目が返されるはずです。
{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}
次に、次のコマンドを使用し、新しい cURL 要求を使用してデータを取得します。
curl http://127.0.0.1:8080
このコマンドからは、ここに示すように、作成した項目を含む "todo" 項目の一覧が返されます。
[{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}]
これらの cURL 要求のスクリーンショットを次に示します。
おめでとうございます。 R2DBC を使用してデータを格納し、Azure Database for PostgreSQLから取得する、完全にリアクティブな Spring Boot アプリケーションを作成しました。
リソースをクリーンアップする
このクイック スタートで使用したすべてのリソースをクリーンアップするには、次のコマンドを使用してリソース グループを削除します。
az group delete \
--name $AZ_RESOURCE_GROUP \
--yes
次のステップ
Spring Data アプリケーションを Azure Spring Apps にデプロイし、マネージド ID を使用する方法の詳細については、「 Tutorial: Azure データベースへのパスワードなしの接続を使用して Spring アプリケーションを Azure Spring Apps にデプロイする」を参照してください。
Spring および Azure の詳細については、Azure ドキュメント センターで引き続き Spring に関するドキュメントをご確認ください。
関連項目
Spring Data R2DBC の詳細については、Spring の「リファレンス ドキュメント」を参照してください。
Java での Azure の使用の詳細については、「Java 開発者向けの Azure」および Azure DevOps と Java の操作に関するページを参照してください。