Guia de início rápido: usar Java e JDBC com o Banco de Dados do Azure para PostgreSQL - Servidor flexível

APLICA-SE A: Banco de Dados do Azure para PostgreSQL - Servidor Flexível

Este artigo demonstra a criação de um aplicativo de exemplo que usa Java e JDBC para armazenar e recuperar informações no Banco de Dados do Azure para servidor flexível PostgreSQL.

JDBC é a API Java padrão para se conectar a bancos de dados relacionais tradicionais.

Neste artigo, incluiremos dois métodos de autenticação: autenticação Microsoft Entra e autenticação PostgreSQL. A guia Sem senha mostra a autenticação do Microsoft Entra e a guia Senha mostra a autenticação do PostgreSQL.

A autenticação do Microsoft Entra é um mecanismo para se conectar ao Banco de Dados do Azure para PostgreSQL usando identidades definidas na ID do Microsoft Entra. Com a autenticação do Microsoft Entra, você pode gerenciar identidades de usuário de banco de dados e outros serviços da Microsoft em um local central, o que simplifica o gerenciamento de permissões.

A autenticação do PostgreSQL usa contas armazenadas no PostgreSQL. Se você optar por usar senhas como credenciais para as contas, essas credenciais serão armazenadas na user tabela. Como essas senhas são armazenadas no PostgreSQL, você precisará gerenciar a rotação das senhas por conta própria.

Pré-requisitos

Preparar o ambiente de trabalho

Primeiro, use o seguinte comando para configurar algumas variáveis de ambiente.

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)

Substitua os marcadores de posição pelos seguintes valores, que são utilizados ao longo deste artigo:

  • <YOUR_DATABASE_SERVER_NAME>: O nome da sua instância de servidor flexível do Banco de Dados do Azure para PostgreSQL, que deve ser exclusiva no Azure.
  • <YOUR_DATABASE_NAME>: O nome do banco de dados da instância de servidor flexível do Banco de Dados do Azure para PostgreSQL, que deve ser exclusivo no Azure.
  • <YOUR_AZURE_REGION>: A região do Azure a ser usada. Pode utilizar a região eastus por predefinição, mas recomendamos que configure uma região mais próxima do local onde vive. Você pode ver a lista completa de regiões disponíveis digitando az account list-locations.
  • <YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>: O nome de usuário do seu Banco de Dados do Azure para instância de servidor flexível PostgreSQL. Verifique se o nome de usuário é um usuário válido em seu locatário do Microsoft Entra.
  • <YOUR_LOCAL_IP_ADDRESS>: O endereço IP do seu computador local, a partir do qual irá executar a sua aplicação Spring Boot. Uma maneira conveniente de encontrá-lo é abri-whatismyip.akamai.com.

Importante

Ao definir <YOUR_POSTGRESQL_AD_NON_ADMIN_USERNAME>o , o nome de usuário já deve existir no locatário do Microsoft Entra ou você não poderá criar um usuário do Microsoft Entra em seu banco de dados.

Em seguida, crie um grupo de recursos usando o seguinte comando:

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

Criar um Banco de Dados do Azure para instância de servidor flexível do PostgreSQL

As seções a seguir descrevem como criar e configurar sua instância de banco de dados.

Criar uma instância de servidor flexível do Banco de Dados do Azure para PostgreSQL e configurar o usuário administrador

A primeira coisa que você cria é uma instância de servidor flexível do Banco de Dados do Azure gerenciado para PostgreSQL.

Nota

Você pode ler informações mais detalhadas sobre como criar instâncias de servidor flexíveis do Banco de Dados do Azure para PostgreSQL em Criar uma instância de servidor flexível do Banco de Dados do Azure para PostgreSQL usando o portal do Azure.

Se estiver a utilizar a CLI do Azure, execute o seguinte comando para se certificar de que tem permissão suficiente:

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

Execute o seguinte comando para criar o servidor:

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

Para configurar um administrador do Microsoft Entra depois de criar o servidor, siga as etapas em Gerenciar funções do Microsoft Entra no Banco de Dados do Azure para PostgreSQL - Servidor Flexível.

Importante

Ao configurar um administrador, um novo usuário com privilégios completos de administrador é adicionado ao banco de dados do Azure para instância de servidor flexível do PostgreSQL. Você pode criar vários administradores do Microsoft Entra por instância de servidor flexível do Banco de Dados do Azure para PostgreSQL.

Tem algum problema? Deixe-nos saber.

Configurar uma regra de firewall para sua instância de servidor flexível do Banco de Dados do Azure para PostgreSQL

As instâncias de servidor flexíveis do Banco de Dados do Azure para PostgreSQL são protegidas por padrão. O serviço tem uma firewall que não permite ligações de entrada. Para poder usar seu banco de dados, você precisa adicionar uma regra de firewall que permitirá que o endereço IP local acesse o servidor de banco de dados.

Como você configurou seu endereço IP local no início deste artigo, você pode abrir o firewall do servidor executando o seguinte comando:

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

Se você estiver se conectando à instância de servidor flexível do Banco de Dados do Azure para PostgreSQL do Subsistema Windows para Linux (WSL) em um computador Windows, precisará adicionar a ID de host WSL ao firewall.

Obtenha o endereço IP da sua máquina host executando o seguinte comando no WSL:

cat /etc/resolv.conf

Copie o endereço IP após o termo nameservere, em seguida, use o seguinte comando para definir uma variável de ambiente para o endereço IP WSL:

AZ_WSL_IP_ADDRESS=<the-copied-IP-address>

Em seguida, use o seguinte comando para abrir o firewall do servidor para seu aplicativo baseado em 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

Configurar um Banco de Dados do Azure para banco de dados de servidor flexível PostgreSQL

Crie um novo banco de dados usando o seguinte comando:

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

Criar um Banco de Dados do Azure para usuário não administrador do servidor flexível PostgreSQL e conceder permissão

Em seguida, crie um usuário não administrador e conceda todas as permissões ao banco de dados.

Nota

Você pode ler informações mais detalhadas sobre como gerenciar o Banco de Dados do Azure para usuários do servidor flexível do PostgreSQL em Gerenciar usuários do Microsoft Entra - Banco de Dados do Azure para PostgreSQL - Servidor Flexível.

Crie um script SQL chamado create_ad_user.sql para criar um usuário não administrador. Adicione o seguinte conteúdo e salve-o localmente:

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

Em seguida, use o seguinte comando para executar o script SQL para criar o usuário não administrador do 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

Agora use o seguinte comando para remover o arquivo de script SQL temporário:

rm create_ad_user.sql

Criar um novo projeto Java

Usando seu IDE favorito, crie um novo projeto Java usando Java 8 ou superior e adicione um arquivo pom.xml em seu diretório raiz com o seguinte conteúdo:

<?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>

Este arquivo é um Apache Maven que configura nosso projeto para usar:

  • Java 8
  • Um driver PostgreSQL recente para Java

Preparar um arquivo de configuração para se conectar ao Banco de Dados do Azure para servidor flexível PostgreSQL

Crie um arquivo src/main/resources/application.properties e adicione o seguinte conteúdo:

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

Nota

A propriedade url de configuração anexada ?serverTimezone=UTC diz ao driver JDBC para usar TLS (Transport Layer Security) ao se conectar ao banco de dados. É obrigatório usar TLS com o Banco de Dados do Azure para servidor flexível PostgreSQL e é uma boa prática de segurança.

Criar um arquivo SQL para gerar o esquema de banco de dados

Você usará um arquivo src/main/resources/schema.sql para criar um esquema de banco de dados. Crie esse arquivo, com o seguinte conteúdo:

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

Codificar a aplicação

Ligue-se à base de dados

Em seguida, adicione o código Java que usará JDBC para armazenar e recuperar dados do seu Banco de Dados do Azure para instância de servidor flexível PostgreSQL.

Crie um arquivo src/main/java/DemoApplication.java e adicione o seguinte conteúdo:

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

Tem algum problema? Deixe-nos saber.

Esse código Java usará os arquivos application.properties e schema .sql que criamos anteriormente para se conectar à instância flexível do servidor do Banco de Dados do Azure para PostgreSQL e criar um esquema que armazenará nossos dados.

Neste arquivo, você pode ver que comentamos métodos para inserir, ler, atualizar e excluir dados: codificaremos esses métodos no resto deste artigo, e você poderá descomentá-los um após o outro.

Nota

As credenciais do banco de dados são armazenadas nas propriedades de usuário e senha do arquivo application.properties . Essas credenciais são usadas durante a execução DriverManager.getConnection(properties.getProperty("url"), properties);do , pois o arquivo de propriedades é passado como um argumento.

Agora você pode executar esta classe principal com sua ferramenta favorita:

  • Usando seu IDE, você deve ser capaz de clicar com o botão direito do mouse na classe DemoApplication e executá-la.
  • Usando o Maven, você pode executar o aplicativo executando: mvn exec:java -Dexec.mainClass="com.example.demo.DemoApplication".

O aplicativo deve se conectar à instância flexível do servidor do Banco de Dados do Azure para PostgreSQL, criar um esquema de banco de dados e fechar a conexão, como você deve ver nos logs do console:

[INFO   ] Loading application properties
[INFO   ] Connecting to the database
[INFO   ] Database connection test: demo
[INFO   ] Create database schema
[INFO   ] Closing database connection

Criar uma classe de domínio

Crie uma nova Todo classe Java, ao lado da DemoApplication classe, e adicione o seguinte código:

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

Essa classe é um modelo de domínio mapeado todo na tabela que você criou ao executar o script schema.sql .

Inserir dados no Banco de Dados do Azure para servidor flexível PostgreSQL

No arquivo src/main/java/DemoApplication.java, após o método principal, adicione o seguinte método para inserir dados no banco de dados:

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

Agora você pode descomentar as duas linhas a main seguir no método:

Todo todo = new Todo(1L, "configuration", "congratulations, you have set up JDBC correctly!", true);
insertData(todo, connection);

A execução da classe principal agora deve produzir a seguinte saída:

[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

Lendo dados do Banco de Dados do Azure para servidor flexível PostgreSQL

Vamos ler os dados inseridos anteriormente, para validar que o nosso código funciona corretamente.

No arquivo src/main/java/DemoApplication.java, após o insertData método, adicione o seguinte método para ler dados do banco de dados:

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

Agora você pode descomentar a seguinte linha no main método:

todo = readData(connection);

A execução da classe principal agora deve produzir a seguinte saída:

[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

Atualizando dados no Banco de Dados do Azure para servidor flexível PostgreSQL

Vamos atualizar os dados que inserimos anteriormente.

Ainda no arquivo src/main/java/DemoApplication.java , após o método, adicione o readData seguinte método para atualizar dados dentro do banco de dados:

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

Agora você pode descomentar as duas linhas a main seguir no método:

todo.setDetails("congratulations, you have updated data!");
updateData(todo, connection);

A execução da classe principal agora deve produzir a seguinte saída:

[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

Excluindo dados no Banco de Dados do Azure para servidor flexível PostgreSQL

Por fim, vamos apagar os dados que inserimos anteriormente.

Ainda no arquivo src/main/java/DemoApplication.java , após o método, adicione o updateData seguinte método para excluir dados dentro do banco de dados:

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

Agora você pode descomentar a seguinte linha no main método:

deleteData(todo, connection);

A execução da classe principal agora deve produzir a seguinte saída:

[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

Clean up resources (Limpar recursos)

Parabéns! Você criou um aplicativo Java que usa JDBC para armazenar e recuperar dados do Banco de Dados do Azure para servidor flexível PostgreSQL.

Para limpar todos os recursos usados durante este início rápido, exclua o grupo de recursos usando o seguinte comando:

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

Próximos passos