Gunakan Spring Data R2DBC dengan Azure Database for PostgreSQL

Artikel ini menunjukkan cara menggunakan Spring Data R2DBC dengan Azure Database for PostgreSQL untuk membangun aplikasi Spring Boot yang dapat diskalakan dan sepenuhnya reaktif yang menyimpan dan mengambil informasi. Sampel menggunakan implementasi R2DBC untuk PostgreSQL dari repositori r2dbc-postgresql pada GitHub.

R2DBC membawa API reaktif ke database relasional tradisional. Anda dapat menggunakannya dengan Spring WebFlux untuk membuat aplikasi Spring Boot yang sepenuhnya reaktif, yang menggunakan API non-blocking. Ini akan memberikan skalabilitas yang lebih baik daripada pendekatan klasik "satu utas per koneksi".

Prasyarat

  • Klien baris perintah PostgreSQL.

  • cURL atau utilitas HTTP serupa untuk menguji fungsionalitas.

Lihat aplikasi sampel

Dalam artikel ini, Anda membuat kode aplikasi sampel. Jika Anda ingin lebih cepat, aplikasi ini sudah dikodekan dan tersedia di https://github.com/Azure-Samples/quickstart-spring-data-r2dbc-postgresql.

Menyiapkan lingkungan kerja

Pertama, siapkan beberapa variabel lingkungan dengan menjalankan perintah berikut:

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>

Ganti placeholder dengan nilai berikut, yang digunakan di artikel ini:

  • <YOUR_DATABASE_SERVER_NAME>: Nama server PostgreSQL Anda, yang harus unik di seluruh Azure.
  • <YOUR_DATABASE_NAME>: Nama database server PostgreSQL, yang harus unik dalam Azure.
  • <YOUR_AZURE_REGION>: Wilayah Azure yang akan Anda gunakan. Anda dapat menggunakan eastus secara default, tetapi mengonfigurasi wilayah yang lebih dekat dengan tempat Anda tinggal. Lihat daftar lengkap wilayah yang tersedia dengan menggunakan az account list-locations.
  • <YOUR_POSTGRESQL_ADMIN_PASSWORD> dan <YOUR_POSTGRESQL_NON_ADMIN_PASSWORD>: Kata sandi server database PostgreSQL Anda, yang harus memiliki minimal delapan karakter. Kata sandi Anda harus berisi karakter dari tiga kategori berikut – huruf besar Inggris, huruf kecil Inggris, angka (0-9), dan karakter non-alfanumerik (!, $, #,%, dll.).
  • <YOUR_LOCAL_IP_ADDRESS>: Alamat IP komputer lokal, tempat Anda akan menjalankan aplikasi Spring Boot. Salah satu cara mudah untuk menemukannya adalah dengan membuka whatismyip.akamai.com.

Catatan

Microsoft merekomendasikan penggunaan alur autentikasi paling aman yang tersedia. Alur autentikasi yang dijelaskan dalam prosedur ini, seperti untuk database, cache, olahpesan, atau layanan AI, memerlukan tingkat kepercayaan yang sangat tinggi dalam aplikasi dan membawa risiko yang tidak ada dalam alur lain. Gunakan alur ini hanya ketika opsi yang lebih aman, seperti identitas terkelola untuk koneksi tanpa kata sandi atau tanpa kunci, tidak layak. Untuk operasi komputer lokal, lebih suka identitas pengguna untuk koneksi tanpa kata sandi atau tanpa kunci.

Berikutnya, buat grup sumber daya menggunakan perintah berikut:

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

Membuat instans Azure Database for PostgreSQL dan menyiapkan pengguna admin

Hal pertama yang Anda buat adalah server PostgreSQL terkelola dengan pengguna admin.

Catatan

Untuk informasi selengkapnya tentang membuat server PostgreSQL, lihat Membuat server Azure Database for PostgreSQL dengan menggunakan portal Azure.

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

Mengonfigurasi database PostgreSQL

Server PostgreSQL yang Anda buat sebelumnya kosong. Gunakan perintah berikut untuk membuat database baru.

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

Mengonfigurasi aturan firewall untuk server PostgreSQL Anda

Instans Azure Database for PostgreSQL diamankan secara default. Mereka memiliki firewall yang tidak mengizinkan koneksi masuk. Untuk menggunakan database, Anda perlu menambahkan aturan firewall yang memungkinkan alamat IP lokal Anda mengakses server database.

Karena Anda mengonfigurasi alamat IP lokal kami di awal artikel ini, Anda dapat membuka firewall server dengan menjalankan perintah berikut:

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

Jika Anda menyambungkan ke server PostgreSQL dari Subsistem Windows untuk Linux (WSL) di komputer Windows, Anda perlu menambahkan ID host WSL ke firewall Anda.

Dapatkan alamat IP komputer host Anda dengan menjalankan perintah berikut di WSL:

cat /etc/resolv.conf

Salin alamat IP dengan mengikuti istilah nameserver, lalu gunakan perintah berikut untuk mengatur variabel lingkungan untuk Alamat IP WSL:

export AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

Kemudian, gunakan perintah berikut untuk membuka firewall server ke aplikasi berbasis WSL Anda:

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

Membuat pengguna non-admin PostgreSQL dan memberikan izin

Selanjutnya, buat pengguna non-admin dan berikan semua izin ke database.

Catatan

Untuk informasi selengkapnya tentang membuat pengguna PostgreSQL, lihat Membuat pengguna di Azure Database for PostgreSQL.

Buat skrip SQL bernama create_user.sql untuk membuat pengguna non-admin. Tambahkan konten berikut dan simpan secara lokal:

Catatan

Microsoft merekomendasikan penggunaan alur autentikasi paling aman yang tersedia. Alur autentikasi yang dijelaskan dalam prosedur ini, seperti untuk database, cache, olahpesan, atau layanan AI, memerlukan tingkat kepercayaan yang sangat tinggi dalam aplikasi dan membawa risiko yang tidak ada dalam alur lain. Gunakan alur ini hanya ketika opsi yang lebih aman, seperti identitas terkelola untuk koneksi tanpa kata sandi atau tanpa kunci, tidak layak. Untuk operasi komputer lokal, lebih suka identitas pengguna untuk koneksi tanpa kata sandi atau tanpa kunci.

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

Kemudian, gunakan perintah berikut untuk menjalankan skrip SQL dan membuat pengguna non-admin 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

Sekarang, gunakan perintah berikut untuk menghapus file skrip SQL sementara:

rm create_user.sql

Buat aplikasi Spring Boot reaktif

Untuk membuat aplikasi Spring Boot reaktif, kita akan menggunakan Spring Initializr. Aplikasi yang akan kita buat akan menggunakan:

  • Spring Boot 2.7.11.
  • Dependensi berikut: Spring Reactive Web (juga dikenal sebagai Spring WebFlux) dan Spring Data R2DBC.

Hasilkan aplikasi dengan menggunakan Spring Initializr

Buat aplikasi pada baris perintah dengan menggunakan perintah berikut:

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 -

Tambahkan implementasi driver PostgreSQL reaktif

Buka file pom.xml proyek yang dihasilkan, lalu tambahkan driver PostgreSQL reaktif dari repositori r2dbc-postgresql di GitHub. Setelah dependensi spring-boot-starter-webflux, tambahkan teks berikut:

<dependency>
    <groupId>io.r2dbc</groupId>
    <artifactId>r2dbc-postgresql</artifactId>
    <version>0.8.12.RELEASE</version>
    <scope>runtime</scope>
</dependency>

Konfigurasikan Spring Boot untuk menggunakan Azure Database for PostgreSQL

Buka file src/main/resources/application.properties, dan tambahkan teks berikut ini:

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_NAMEGanti variabel , $AZ_DATABASE_NAME, dan $AZ_POSTGRESQL_NON_ADMIN_PASSWORD dengan nilai yang Anda konfigurasi di awal artikel ini.

Peringatan

Untuk alasan keamanan, Azure Database for PostgreSQL memerlukan koneksi SSL. spring.r2dbc.properties.sslMode=REQUIRE Tambahkan properti konfigurasi. Jika tidak, driver R2DBC PostgreSQL mencoba terhubung menggunakan koneksi yang tidak aman, yang gagal.

Catatan

Untuk kinerja yang lebih baik, properti spring.r2dbc.url dikonfigurasi untuk menggunakan kumpulan koneksi menggunakan r2dbc-pool.

Anda sekarang dapat memulai aplikasi Anda dengan menggunakan pembungkus Maven yang disediakan sebagai berikut:

./mvnw spring-boot:run

Berikut adalah cuplikan layar aplikasi yang berjalan untuk pertama kalinya:

Cuplikan layar aplikasi yang sedang berjalan.

Buat skema database

Di dalam kelas DemoApplication utama, konfigurasikan bean Spring baru yang akan membuat skema database, menggunakan kode berikut:

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;
    }
}

Bean Spring ini menggunakan file yang disebut schema.sql, maka buatlah file tersebut di folder src/main/resources, dan tambahkan teks berikut:

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

Hentikan aplikasi yang berjalan, lalu mulai kembali menggunakan perintah berikut. Aplikasi sekarang menggunakan demo database yang Anda buat sebelumnya, dan membuat todo tabel di dalamnya.

./mvnw spring-boot:run

Berikut adalah tangkapan layar tabel database saat sedang dibuat:

Cuplikan layar pembuatan tabel database.

Kodekan aplikasi

Selanjutnya, tambahkan kode Java yang menggunakan R2DBC untuk menyimpan dan mengambil data dari server PostgreSQL Anda.

Tambahkan kelas Java Todo baru, di samping kelas DemoApplication, menggunakan kode berikut:

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;
    }
}

Kelas ini adalah model domain yang dipetakan pada tabel todo yang Anda buat sebelumnya.

Untuk mengelola kelas itu, Anda memerlukan repositori. Tentukan antarmuka TodoRepository baru dalam paket yang sama, menggunakan kode berikut:

package com.example.demo;

import org.springframework.data.repository.reactive.ReactiveCrudRepository;

public interface TodoRepository extends ReactiveCrudRepository<Todo, Long> {
}

Repositori ini adalah repositori reaktif yang dikelola Spring Data R2DBC.

Selesaikan aplikasi dengan membuat pengontrol yang dapat menyimpan dan mengambil data. Terapkan kelas TodoController dalam paket yang sama, dan tambahkan kode berikut:

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();
    }
}

Terakhir, hentikan aplikasi lalu mulai kembali menggunakan perintah berikut:

./mvnw spring-boot:run

Uji aplikasi

Untuk menguji aplikasi, Anda dapat menggunakan cURL.

Pertama, buat item "todo" baru dalam database menggunakan perintah berikut:

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

Perintah ini harus menghasilkan item yang dibuat, seperti yang ditampilkan di sini:

{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}

Selanjutnya, ambil data menggunakan permintaan cURL baru dengan perintah berikut:

curl http://127.0.0.1:8080

Perintah ini akan menghasilkan daftar item "todo", termasuk item yang telah Anda buat, seperti yang ditampilkan berikut ini:

[{"id":1,"description":"configuration","details":"congratulations, you have set up R2DBC correctly!","done":true}]

Berikut adalah tangkapan layar beberapa permintaan cURL:

Cuplikan layar pengujian cURL.

Selamat! Anda membuat aplikasi Spring Boot yang sepenuhnya reaktif yang menggunakan R2DBC untuk menyimpan dan mengambil data dari Azure Database for PostgreSQL.

Membersihkan sumber daya

Untuk membersihkan semua sumber daya yang digunakan selama mulai cepat ini, hapus grup sumber daya dengan menggunakan perintah berikut:

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

Langkah berikutnya

Untuk mempelajari selengkapnya tentang menyebarkan aplikasi Spring Data ke Azure Spring Apps dan menggunakan identitas terkelola, lihat Tutorial: Menyebarkan aplikasi Spring ke Azure Spring Apps dengan koneksi tanpa kata sandi ke database Azure.

Untuk mempelajari selengkapnya tentang Spring dan Azure, lanjutkan ke pusat dokumentasi Spring di Azure.

Lihat juga

Untuk informasi selengkapnya tentang Spring Data R2BDC, lihat dokumentasi referensi Spring.

Untuk informasi selengkapnya tentang menggunakan Azure dengan Java, lihat Azure untuk pengembang Java dan Bekerja dengan Azure DevOps dan Java.