التشغيل السريع: استخدام Java وJDBC مع قاعدة بيانات Azure ل PostgreSQL - خادم مرن

يطبق على: قاعدة بيانات Azure لـ PostgreSQL - الخادم المرن

توضح هذه المقالة إنشاء نموذج تطبيق يستخدم Java وJDBC لتخزين المعلومات واستردادها في قاعدة بيانات Azure لخادم PostgreSQL المرن.

JDBC هو Java API القياسية للاتصال بقواعد البيانات العلائقية التقليدية.

في هذه المقالة، سنتضمن طريقتين للمصادقة: مصادقة Microsoft Entra ومصادقة PostgreSQL. تعرض علامة التبويب Passwordless مصادقة Microsoft Entra وتعرض علامة التبويب Password مصادقة PostgreSQL.

مصادقة Microsoft Entra هي آلية للاتصال بقاعدة بيانات Azure ل PostgreSQL باستخدام الهويات المحددة في معرف Microsoft Entra. باستخدام مصادقة Microsoft Entra، يمكنك إدارة هويات مستخدمي قاعدة البيانات خدمات Microsoft الأخرى في موقع مركزي، ما يبسط إدارة الأذونات.

تستخدم مصادقة PostgreSQL الحسابات المخزنة في PostgreSQL. إذا اخترت استخدام كلمات المرور كبيانات اعتماد للحسابات، فسيتم تخزين بيانات الاعتماد هذه في user الجدول. نظرا إلى تخزين كلمات المرور هذه في 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_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 لمثيل خادم PostgreSQL المرن، والذي يجب أن يكون فريدا عبر Azure.
  • <YOUR_DATABASE_NAME>: اسم قاعدة بيانات Azure Database لمثيل خادم PostgreSQL المرن، والذي يجب أن يكون فريدا داخل Azure.
  • <YOUR_AZURE_REGION>: منطقة Azure المراد استخدامها. يمكنك استخدام eastus بشكل افتراضي، لكننا نوصي بتكوين منطقة أقرب إلى المكان الذي تعيش فيه. يمكنك مشاهدة القائمة الكاملة للمناطق المتوفرة عن طريق إدخال az account list-locations.
  • <YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>: اسم المستخدم الخاص بقاعدة بيانات Azure لمثيل خادم PostgreSQL المرن. تأكد من أن اسم المستخدم مستخدم صالح في مستأجر Microsoft Entra.
  • <YOUR_LOCAL_IP_ADDRESS>: عنوان IP للكمبيوتر المحلي، الذي ستقوم بتشغيل تطبيق Spring Boot منه. إحدى الطرق الملائمة للعثور عليه هي فتح whatismyip.akamai.com.

هام

عند تعيين <YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>، يجب أن يكون اسم المستخدم موجودا بالفعل في مستأجر Microsoft Entra الخاص بك أو لن تتمكن من إنشاء مستخدم Microsoft Entra في قاعدة البيانات الخاصة بك.

بعد ذلك، قم بإنشاء مجموعة موارد باستخدام الأمر التالي:

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

إنشاء مثيل خادم مرن لقاعدة بيانات Azure ل PostgreSQL

تصف الأقسام التالية كيفية إنشاء مثيل قاعدة البيانات وتكوينه.

إنشاء مثيل خادم مرن لقاعدة بيانات Azure ل PostgreSQL وإعداد مستخدم مسؤول

أول شيء تقوم بإنشائه هو قاعدة بيانات Azure المدارة لمثيل خادم PostgreSQL المرن.

إشعار

يمكنك قراءة معلومات أكثر تفصيلا حول إنشاء قاعدة بيانات Azure لمثيلات الخادم المرن PostgreSQL في إنشاء قاعدة بيانات Azure لمثيل خادم PostgreSQL المرن باستخدام مدخل Microsoft Azure.

إذا كنت تستخدم 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 بعد إنشاء الخادم، اتبع الخطوات الواردة في إدارة أدوار Microsoft Entra في قاعدة بيانات Azure ل PostgreSQL - الخادم المرن.

هام

عند إعداد مسؤول، تتم إضافة مستخدم جديد يتمتع بامتيازات المسؤول الكاملة إلى قاعدة بيانات Azure لقاعدة بيانات Azure لمثيل خادم PostgreSQL المرن. يمكنك إنشاء العديد من مسؤولي Microsoft Entra لكل مثيل خادم مرن لقاعدة بيانات Azure ل PostgreSQL.

هل تواجه أي مشاكل؟ أبلغنا بها.

تكوين قاعدة جدار حماية لقاعدة بيانات Azure لمثيل خادم 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

إذا كنت تتصل بمثيل خادم Azure Database for PostgreSQL المرن من نظام Windows الفرعي لـ Linux‬ (WSL) على كمبيوتر Windows، فستحتاج إلى إضافة معرف مضيف WSL إلى جدار الحماية الخاص بك.

احصل على عنوان IP للجهاز المضيف الخاص بك عن طريق تشغيل الأمر التالي في WSL:

cat /etc/resolv.conf

انسخ عنوان IP التالي للمصطلح nameserver، ثم استخدم الأمر التالي لتعيين متغير بيئة لعنوان IP WSL:

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 لقاعدة بيانات الخادم المرنة 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 لخادم PostgreSQL المرن غير مستخدم غير مسؤول ومنح الإذن

بعد ذلك، أنشئ مستخدما غير مسؤول وامنح جميع الأذونات لقاعدة البيانات.

إشعار

يمكنك قراءة معلومات أكثر تفصيلا حول إدارة قاعدة بيانات Azure لمستخدمي الخادم المرن ل PostgreSQL في إدارة مستخدمي Microsoft Entra - قاعدة بيانات Azure ل PostgreSQL - الخادم المرن.

إنشاء برنامج نصي SQL يسمى create_ad_user.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 جديد باستخدام Java 8 أو أحدث، وأضف ملف 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>
      <dependency>
        <groupId>com.azure</groupId>
        <artifactId>azure-identity-extensions</artifactId>
        <version>1.0.0</version>
      </dependency>
    </dependencies>
</project>

هذا الملف هو Apache Maven الذي يقوم بتكوين مشروعنا لاستخدامه:

  • Java 8
  • مشغل PostgreSQL الحديث لـ Java

إعداد ملف تكوين للاتصال بقاعدة بيانات Azure لخادم 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

إشعار

تم ?serverTimezone=UTC إلحاق خاصية url التكوين بإخبار برنامج تشغيل JDBC باستخدام TLS (أمان طبقة النقل) عند الاتصال بقاعدة البيانات. من الضروري استخدام TLS مع قاعدة بيانات Azure لخادم PostgreSQL المرن، وهي ممارسة أمان جيدة.

إنشاء ملف 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);

إنشاء التعليمة البرمجية للتطبيق

الاتصال بقاعدة البيانات

بعد ذلك، أضف رمز Java الذي سيستخدم JDBC لتخزين البيانات واستردادها من قاعدة بيانات Azure لمثيل خادم PostgreSQL المرن.

إنشاء ملف 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. يتم استخدام بيانات الاعتماد هذه عند تنفيذ 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 فئة Java جديدة، بجانب DemoApplicationالفئة، وإضافة التعليمة البرمجية التالية:

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 الذي قمت بإنشائه عند تنفيذ البرنامج النصي schema.sql.

إدراج البيانات في قاعدة بيانات Azure لخادم PostgreSQL المرن

في الملف src/main/java/DemoApplication.java، بعد الأسلوب الرئيسي، أضف الأسلوب التالي لإدراج البيانات في قاعدة البيانات:

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:

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 لخادم 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 لخادم 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:

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 لخادم 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

تنظيف الموارد

تهانينا! لقد أنشأت تطبيق Java يستخدم JDBC لتخزين البيانات واستردادها من قاعدة بيانات Azure لخادم PostgreSQL المرن.

لتنظيف جميع الموارد المستخدمة في أثناء هذا التشغيل السريع حذف مجموعة الموارد باستخدام الأمر التالي:

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

الخطوات التالية